分布式计算 —尤其是租借空闲 CPU 周期的技术 —是用于解决计算复杂性问题的一种已经成熟的方法。目前,正在开展的比较著名的分布式计算项目有 SETI@home(分析用于查找潜在的宇宙广播信号的射电望远镜数据)、Folding@home (分析蛋白质如何折叠)和 Prime95(搜索非常大的 Mersenne 素数)。而其他分布式计算项目有数百个,其中也有一部分是广为人知的。Sony 甚至在其 PLAYSTATION®3 游戏控制台的主流固件中集成了一个特定尺寸的 Folding@home 客户机。
利用闲置计算机的空闲 CPU 周期固然不错,但是实现此技术的传统方法存在一些难点:
- 如果要发行应用程序的源代码,那么算法自然也会公诸于众。这并不是所希望的。由于任何加密密钥和密码系统都必须位于源代码中,因此同时还会将应用程序的源数据流公开出来。更糟糕的是,人们可以使用破解版本的客户端软件将伪造的结果注入计算。
- 另一方面,如果不发布源代码,那么人们很难信任应用程序是完全良性的。毕竟,正常运行的分布式计算客户机需要经常与其父服务器通信;谁能保证客户机的键盘输入、口令或文档的重要内容未暴露给某个人呢?
- 并不是所有的分析任务都能够被轻易地 “分解”(分成相互独立的小块,每块都可以独立进行处理)。
- 收集结果和管理工作负载时存在一个单点故障(Single Point of Failure)。您的搜索结果很容易受到攻击,只需对总部(home base)服务器(其地址硬编码到客户机软件中)执行拒绝服务攻击即可。
本文的灵感一定程度上来自于一种叫做 “Chinese Lottery Attack” 的密码分析技术。这是一种用于查找加密密钥的假想方法,方法是使用用户设备作为分布式计算节点。前提很简单:政府首先开发一个廉价的代码破解芯片(在人们还认为 56 位 DES 加密方法相当安全时,这种攻击就被提出了),用于针对小密钥空间执行强力攻击。然后,政府引入立法要求所有面向国内销售的收音机和电视机都安装此芯片(顺便提一下,这一措施毫不牵强。美国就曾于 2000 年通过立法将 V-Chip 置于电视中)。通过电视广播,每台设备都分配了一个密钥空间进行分析。如果某台设备找到了可能的解决方案,则会点亮其 LED,而该设备所有者便可以通过免费电话获得一份现金奖励;然后,政府检索出 “获胜” 设备并从其内存中读取密钥。
与上述的其他分布式计算系统一样,Chinese Lottery 也存在一个问题:任何人都可以对密码芯片进行反向工程,然后监听广播信号来获取您试图破解的确切信息。这比您想象的更为严重,因为这意味着您的对手掌握了强大的线索,根据这个线索他们可以发现哪些通信频道遭到截听。
更糟的是,他们可以精确地估算出您破解特定密钥的时间,因为每个节点的计算能力都是已知的,监听广播频道的任何人和知道正在被攻击的密钥的人都会知道 “获胜” 包发出的精确时间。此外,还可以针对此类系统假设多种类型的攻击手段。比如说,攻击者可以构建一个小型发射器,然后使用它在小范围内覆盖广播信号并通过发送伪造的 “获胜” 数据包淹没领奖热线。
当然, 可以通过一些机制处理所有这些问题,但是不可否认的是分布式计算机制至少具有以下优点:
- 没有单点故障的冗余设计
- 阻止通过流量分析导致的信息泄漏
- 可自由公开的易于分析的计算引擎,并且不会影响正在处理的任务,而且该引擎对于终端用户来说是无害的
- 具有不透明性,即便给定特定节点的算法和数据有效载荷,观察者也无法推断出系统的整体功能
当然,说到冗余信息网络,因特网就是一个最好的例子。如果使用标准因特网协议链接您的节点, 那么可以使用大量的现有技术,而不需额外的开发成本。鉴于此,您应该使用 HTTP 作为传输协议。 这样,所有因特网的正常路由冗余便随之而来,并且还可以使用自动负载平衡和故障转移机制(这些机制普遍应用于当今的因特网中)。除了算法本身之外,还有其他一些有益的作用,但是此处只考虑冗余的问题,其他的问题以后再讨论。
如何才能抵抗流量分析呢?首先,我们给出流量分析的定义。流量分析即通过监测通信方以及传输的数据量来收集关于消息或协议的信息。比如说,假设您试图登录系统 A。然后,输入用户名和密码并观察流量。可以看到系统 A 向系统 B 发送了一个小数据包,然后等待响应包,已决定同意或拒绝登录请求。您可能会据此推测身份验证数据库位于系统 B 中,而系统 A 只是一个前端。这或许只是一个简单的示例,但是此类分析可能是渗透密码系统的一个开端。
可以使用以下两种方法加固您的系统(针对此类攻击):
- 以网格拓扑结构在地理上分散节点。 攻击者不可能监控节点之间的所有链接,因为任何实体(政府或其他)都没有对所有相关主干部分的访问权限。
- 在实体之外无法知道系统的输入和输出边界。所有节点之间都在不断地传送信息。只有拥有网络 “地图” 的人才能知道哪个节点的输出数据是有用的以及输出信息的具体含义。对于其他人来说,各个节点只是在输出一连串随机的数字。
接下来我们讨论程序的主要内容,即处理算法本身。通过神经网络可以很好地实现上面提到的后两个设计目标(当然,假设初始计算问题可以通过此网络解决)。在过去的几十年中,对神经网络的研究已经日趋平淡。但是此类算法在各种多样的应用程序(如光学字符识别、信用计分、天气预报、甚至控制大型家用电器)中的应用却相当广泛。
从最基本的程序来说,任何神经网络都由一些相互连接的节点组成。每个节点都有 n 个输入,i1…… in,每个输入都有相应的加权系数,w1…… wn,以及一个输出 O。注意,此处我使用的是自己指定的变量名称,但是术语却是标准的。每个节点的输出都是对所有输入运行 sigma(求和)函数得到的结果,最简单的情形可通过下图表示:
当输入表示数字值(是 / 否)时,将节点输入定义为 -1 ≤ in ≤ 1 范围是很常见的(但这显然不是科学需求) 。加权可以是任何实际数字。
神经网络有几种不同的拓扑结构,但是最简单的一种是前馈网络。网络的实际神经部分由三个部分构成:输入、隐藏和输出(显示为黄色、绿色和紫色,如图 2 所示)。但是,一个完整的系统还包含其他一些部分,如下所示:
图 1. 简单前馈网络
要理解这些部分的具体含义,请考虑一个光学字符识别系统,该系统扫描纸张上的符号并将它们转换为 3 位的十进制数。这是应用神经网络的典型示例(参考资料中含有这类网络的动手演示)。
该系统的输入为原始纸张的扫描图像。然后,系统可以将图像分成 2 x 3 灰阶像素的小块,每个小块包含一个字符;这是上图显示的特征提取步骤。2 x 3 可能无法达到此应用程序对解析度的要求,但是我们只是在讨论一个假想的应用程序,并且显示更多节点会使图 1 难以理解。
然后,将每个像素的灰阶值 提供给 6 个输入层节点。再将各个输入层节点的输出 提供给 6 个隐藏层节点,这些隐藏层节点将依次提供给 3 个输出接点。我将对输出进行定义,我期望各个输出节点的输出范围为 0 到 9。换句话说,我可以只取输出的整数部分并使用它作为预期输出代码的合适位。
您应该注意到我并没有在各层的节点数量上应用特别的技巧;事实上,各层甚至可以由更多的子层节点构成。一般而言,节点的数量越多,网络的可调优性就更好。在最极端的情况下,您可以使用加权和互联的组合构建等价的 Boolean 门,从而实现 “简单” 的组合系统,但是这并不是利用神经网络编程的有效途径;此类算法更适合于从模糊输入推出概率性的答案。
至此,我已经介绍了如何构建互连(它是一个通用的、可扩展的接线计划;如果目标节点的输入加权为零,则该路径可以有效地删除),如何运行 sigma 函数,以及如何使用有用的方法定义输入和输出特性。还有一个重要部分没有讨论,那就是加权。获得它们的方法是使用已知的输入数据培训网络(请参阅 参考资料),并且没有实际的分析能从这些数字中得到客观的含义;它们确实不可思议。加权只有在特定网络的上下文中才有含义。
此处蕴含了神经网络的魔力和特性(使神经网络专门适合我们的设计目标)。就它们自己而言,加权是绝对透明的幻数 —从中无法推出任何含义(事实上,这有时会造成人们的抱怨 —您无法通过查看神经网络将其中的简单算法提取出来。但是对我们而言却是极好的,因为这意味着没有人可以通过查看一个节点(或者甚至一组节点)计算出系统的具体作用)。与此类似,如果没有相应的加权信息,描述节点互连的路由信息就失去了其意义。
最后,我们将构建一个演示系统。本文的示例代码实现了一个简单的节点。虽然是使用 C 语言编写,但是您可以使用任何其他语言轻易编写该实现:perl、Pascal、Java 或者甚至是 bash 外壳脚本(shell script)。其过程如下:
每个节点都指定了一个惟一的标识序列号。一台主机上可以运行任意数量的节点。每个节点都有 n 个输入(从 i1 到 in),每个输入都有一个与之关联的加权(从 w1 到 wn)以及生成该输入的序列号(从 s1 到 sn)。在示例代码中,加权是随机指定的(表示未经训练的网络)。为了便于测试,节点还假定所有其他节点在本地主机(127.0.0.1)上运行。在实际环境中,还需要使用其他一些路由信息将特定 序列号关联到不同的主机。
系统作为总体上拥有一个量子化的时间概念:时间从 1 开始,并且当信号从某层传递到下一层时便会增加 1。只有当时间 n 的所有输入收集并求和完成 之后,节点才会生成时间 n+1 的输出。
使用以下命令行启动演示 applet:
neurnode a b c |
这里,a 是此节点的序列号,b 是第一个输入节点的序列号,而 c 是最后一个输入节点的序列号。比如说,neurnode 100 200 299 将启动序列号为 100 的节点,它具有 100 个输入节点,序列号从 200 到 299。注意,该程序需要在 Web 服务器的根目录下运行。
每隔 1 秒,每个节点将尝试收集其输入。源代码的序列号和时间的当前值构成输入 URL。比如说,如果您有一个序列号为 20 的节点,其输入为节点 5 到 10,时间的当前值为 3,那么此节点将获得以下 URL:
http://127.0.0.1/5-3.txt http://127.0.0.1/6-3.txt http://127.0.0.1/7-3.txt http://127.0.0.1/8-3.txt http://127.0.0.1/9-3.txt http://127.0.0.1/10-3.txt |
如果成功获得所有输入,程序将计算输出信号并将结果写入文件 "./20-3.txt" —供下一层使用(如果有下一层)。否则,程序将休眠一分钟并再次尝试。您可以使用以下命令运行演示系统(它只有 1 个输出,10 个中间层节点和 10 个输入),记得要在 Web 服务器的主目录下启动:
neurnet 100 1 10 >/dev/null & neurnet 101 1 10 >/dev/null & neurnet 102 1 10 >/dev/null & neurnet 103 1 10 >/dev/null & neurnet 104 1 10 >/dev/null & neurnet 105 1 10 >/dev/null & neurnet 106 1 10 >/dev/null & neurnet 107 1 10 >/dev/null & neurnet 108 1 10 >/dev/null & neurnet 109 1 10 >/dev/null & neurnet 200 100 109 |
在整个系统的输入端,只需为网络的每一层直接 创建相关的输入文件。程序期望查找 ASCII 格式的单精度浮点数;任何无关的字符都将忽略。在输出端,您可以使用任何 Web 服务器读取结果。
您可能想知道我为什么使用这种略显古老的 pull 方法实现传输机制。其原因是 模糊结果,以防止将信息泄露给外部观察者。如果节点使用 push 方法,则很容易从路由表推出最终输出节点。使用 pull 方法则无法知道节点究竟位于输入层、隐藏层还是输出层。
还需注意,这种 push 方法还可以轻易集成一个隐写模块,以隐藏其他数据内部的神经元交互。比如说,您可以将各节点的输出嵌入到一个图像文件中并将其存储在 Web 服务器上,以供网络的下一层获取。如果想要其他方式,还可以将输出存放在因特网上随机的地方,嵌入到一个带有奇怪的搜索关键字的页面中,而且此关键字正常情况下不会在别处被使用。要检索它,可以使用常规的因特网搜索引擎查找容器页面。(显然,这将对消息传递造成很大的延时,但是其想法很有意思) 。
这样,我们已经拥有了一个简单且基于标准的分布式神经网络,并且具有一些迷人的特性。要使它成为一个功能完整的分布式计算客户机,则需要添加一个基础结构以分配和路由 节点,并设置和更新各个节点内部的加权因子。此技巧可适用的应用程序包括需要大范围收集并处理数据以形成某种 monetizable 结果的系统。
| 描述 | 名字 | 大小 | 下载方法 |
|---|---|---|---|
| 示例代码 | wa-wwwits_code.zip | 2KB | HTTP |
学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文。
-
Folding@home 项目可在 Stanford University 找到,而 SETI@home则位于 Berkeley。
请参阅 Wikipedia 上的分布式计算项目列表。
-
RFC3607 概括了 Chinese Lottery Attack 的结构;有关详细信息,请阅读 “Applied Cryptography”(第 2 版)Bruce Schneier,ISBN 0-471-12845-7。
- ThinkQuest 库的 Bernard Willers
& Sep Vrba 部分含有 关于神经网络的有趣的入门级讨论(连同一个非常简单的网络的 JavaScript 实现)。
-
阅读 Neil Fraser 撰写的 a very
light introduction to network training
—这篇文章探讨一个基于 Windows 的自学习字符识别程序,并提供了源代码。
-
Web 开发专区技术库含有大量有帮助的技术文章。
-
订阅
developerWorks Web 开发时事通讯。
获得产品和技术
-
下载 IBM 产品试用版。
讨论
-
参与 developerWorks 社区:
博客、论坛等。
Lewin A.R.W. Edwards 现任职于一家 “财富 50 强” 公司,是该公司的一名无线安全/防火安全设备设计工程师。在此之前,他用了五年时间在 Digi-Frame Inc 开发 x86、ARM 和基于 PA-RISC 的联网多媒体装置。他在加密和安全软件领域有着广泛的经验,并且是两本有关嵌入式系统开发的书的作者。您可以通过 sysadm@zws.com 与他联系。