1976 年,迪斯科还大行其道,冷战正处于高潮,而我要到 9 年之后才出生。那年,正是 Cray-1 在计算机领域大显身手之际,个人计算当时还处于发展的初期(MITS Altair 一年前刚刚推出),同时 Control Data 和 IBM 等公司统领高端市场。Cray-1 是人们印象中用于定义“超级计算机”的传奇机器之一。其采用独特的 C 型结构,运行速度高达惊人的 80 MHz,桌面电脑直到 20 年之后才能达到这样的速度。Cray 速度快,也极富吸引力。
现在,让我们把时间快进到 33 年后,那是 2009 年初的一个清晨,我起床后也想拥有一台 Cray 超级计算机。
我首先要回顾一下基于 FPGA 的复古计算机技术。我 2007 年 12 月从南加州大学毕业并获得 BSEE 学位,当时我把它称作“计算机招魂术”。作为新生代电子工程师,我对神秘的计算机架构特别感兴趣,觉得正好可以借此提高我的 Verilog 水平。我毕业时为自己买了一套 Digilent 公司的 Spartan®-3E 1200 开发板当礼物。我的第一台计算机则是 1980 年代的老古董 NonVon-1。它属于首批“大型并行”机之一,类似于同样古老但更为成功的 Connection Machine 系列(不过主要用于数据库)。这是一台非常有趣的设备,采用 8 位处理器的二进制树状结构(带 1 位 ALU)。
Cray-1 是人们印象中用于定义“超级计算机”的传奇机器之一。其采用独特的 C 型结构,运行速度高达惊人的 80 MHz,桌面电脑直到 20 年之后才能达到这样的速度。
经过几个月的折腾,我总算造出了一台 31 节点的超级计算机,不过其计算能力还比不上现今任何一块手表。虽然这东西没什么用处,却让我明白了摩尔定律的巨大作用,也激发我进一步动手的欲望。
首台 NonVon-1 获得成功后,我又开始寻找新的项目(我的 Verilog 技能仍比较欠缺)。我认识到,低端 FPGA 已经能够处理一些比较高级的硬件了,目前甚至 32 位软处理器都比较常见了。我努力寻找一个能焕发新生的新目标,也考虑了不少选择,包括 UNIVAC 这台有趣的设备,不过它确实有点太老了。 Digital Equipment 公司的 PDP 系列已经被硬件仿真过。Z80 设备的软件仿真器也非常常见。因此,我想到了 Cray。
Cray-1 是什么?
Cray-1 是 Seymour Cray 于 20 世纪 70 年代初离开 Control Data 后所成立新公司 Cray Research 推出的首台设备。当时该设备计算能力强大,需要占用整个房间来放置计算机和磁盘才能保证数据接收。此外,它还拥有一个全职工程师团队来确保正常运行,甚至还需要自备发电设备才能确保加电启动。该设备重新定义了当时的“超级计算机”(毕竟这是 Cray),而且幸运的是它的设计美妙而简单,相关资料也非常齐备(图 1 所示)。Cray-1 硬件参考手册(在因特网上很容易找到)非常详细,现在的用户往往只能拿到黑盒子,看到这么详细的说明肯定会感到震惊。几乎所有运算代码、寄存器及时序图都得到了妥善而详尽的保留。
这台计算机本身是一款64 位流水线处理器,顺序指令发送,只有 128 条独特指令。它采用类似 RISC 的指令集,所有指令都既可在存储器和寄存器(加载或存储指令)之间,也可在两个操作数寄存器和一个目的地寄存器之间(全部算术/逻辑指令)。指令为 16 位或 32 位长。该设备使用三种不同类型的寄存器:地址、标量和矢量寄存器。地址寄存器为 24 位宽,并能够让设备对高达 4 Megaword (32 MB) 的主存储器进行寻址。标量寄存器为 64 位宽,用于计算。每个矢量寄存器包括 64 个 64 位寄存器,从而能够在进行大矩阵科学计算时确保出色的性能。
图 1 — 让计算机爱好者感到幸运的是,Cray 的架构设计美妙而简单,而且相关资料保存完好。
在 CPU 中,指令可发送给 13 个独立的全流水线“功能单元”。高强度的流水线功能对实现 Cray 当时极高的 80MHz 时钟频率而言至关重要。不同的功能单元处理逻辑操作、移位、乘法等。比方说,一个浮点乘法指令需要 7 个周期才能完成,但计算机每个周期都能发出一条新的乘法指令(假定不存在寄存器冲突)。该设计会产生一种有趣的情况,即没有“除法”指令,而是采用倒数近似值除法。也就是说,我们不是计算 X / Y,而是计算 (1 / Y) * X。单独的浮点“倒数近似值”函数单元可在 14 个时钟周期内计算出倒数。
马拉松
我刚开始着手这一项目时,并不完全确定是否能靠自己的力量重新构建如此复杂的计算设备。原始的 Cray-1 花了整个工作团队多年的时间才设计和构建完成。我有无足够的决心做下去呢?(结果是我确实做下去了。)我的 FPGA 能否真的满足要求?(结果是不能满足。)即便设计比较简单而直接,但设计规模仍然较大(目前需要约 5,600 行 Verilog 代码,而且数量还在不断增多)。我必须要保持信念。构建自己的超级计算机是一场马拉松,而不是一场冲刺赛。我只能一步步稳扎稳打地前进。
我开始逐一创建功能单元。就像改装汽车一样,构建完整的计算机也必须熟悉设计的各个方面,这是一种全新的体验。我探索乘法器和加法器设计。我重新打开教科书研究浮点算法。我学习如何使用 Newton Raphson 法三次迭代计算 30 位精度的倒数近似值。(我前面提到过硬件参考手册的详细度吧?)
功能单元逐一成型。这完全是一项业余时间的项目,因此项目只能一点点地慢慢推进。我从最简单的模块开始,很轻松地就完成了两个地址功能单元(一个简单的加法器和一个乘法器)。进入标量函数单元时(一个加法器、一个逻辑单元、一个移位器和一个总体 (population)/前导零计数 (leading zero count)),进度就放缓了。处理三个浮点函数单元(一个加法器、一个乘法器和麻烦的倒数近似值单元)时,我已经感到动力不足了。如前所述,这就是一场马拉松,不是一场冲刺赛。我 2009 年初开始着手 Cray-1 项目,可能在这个项目上总共花了 19 到 20 个月的时间。
随后我的工作进度再度加快,开始接近浮点单元设计的尾声,在矢量单元方面的推进速度也开始加快。如前所述,Cray-1 设计作为一款具有高计算强度的巨型机,拥有 8 个矢量寄存器,每个都包含 64 个 64位寄存器。矢量指令执行时,比方说进行加法计算,每个运算对象录入后每个周期都添加并存储在第三个矢量上(结果矢量)。
Cray-1 支持一个出色的特性,即“矢量链”。比方说,矢量加法单元只需三个周期即能生成首个结果。如果我们将两个含有 64 个条目的矢量相加,我们希望在所有 64 个条目都完成加法计算前就可以对结果进行操作。矢量链使我们能够将加法器单元的结果直接“链接”到另一个单元的输入,不必等待操作结束。我们可在获得首个结果的两个周期后让结果与第三个矢量相乘。对于一些大型矩阵计算而言,在 80 MHz 频率上我们几乎可以保持每个时钟周期两次浮点操作,也就是峰值速率达 160 MFLOPS!直到 20 世纪 90 年代中期,普通台式电脑还不及 Cray-1 的水平。
有了功能单元,我已经能看到长夜将近的黎明曙光了。显然,只需添加一些胶合逻辑就差不多完工了。是的,确实接近完工了。不过我发现,胶合逻辑的工作量其实很大。尽管 Cray-1 的相关存档非常齐备,但齐备的程度还不够。我非常清楚,我在一些不大不小细节的逆向工程方面遇到了困难,如指令发布、冒险检测以及矢量链等。有些问题,比如较宽的 64 位数据总线可用分立式逻辑芯片更方便地解决,而不必使用面向较窄数据路径的FPGA。矢量寄存器在布线时总是让我头疼。
此外,我还要修改一些特性。Cray-1 采用 16 组全 SRAM 存储器系统,体积跟我的冰箱差不多大,其 4 Megaword 存储器可实现每秒 640MB 的带宽,我开发工具套件所用的简陋的 DDR 存储器芯片肯定达不到这样的性能。我使用几乎所有的 FPGA 片上 BRAM 也只能获得 4 kiloword 的存储器空间,这是我的 Cray 目前面临的最大瓶颈。而且我也必须忽略掉一些特性:用于与磁盘驱动器和“主机式”微型计算机进行通信的 DMA 类 I/O 通道和快速上下文切换支持。我要是能找到设备可用的存储器和相关软件,或许可以再添加进这些特性。
硬件障碍
我在此简要介绍一下在设计过程中遇到的一些与 FPGA 相关的难题。首先,我最初的 Spartan-3E 1200 芯片已经证明不能满足要求。我在设计中添加了 Cray 的庞大矢量寄存器后,芯片有限的逻辑资源就不够用了。这时我开始有些犯憷,因为这时我的项目已经推进了 1 年多时间了,而且较大型 FPGA 的价格看似贵了很多。更大的 Virtex® 芯片能方便地满足我的设计要求,但开发板的成本已经超出了我几年兴趣爱好所能承受的预算范畴。幸运的是,Digilent 还出售了一款稍大型的 Spartan-3E 1600 开发板,价格对业余爱好者来说还能承担。实践证明,这块开发板对满足整个系统要求已经足够了(显著扩展了我所使用 BRAM 的容量)。
我遇到的另一个问题就是速度问题。尽管摩尔定律发展了 30 多年,但 Cray-1 原始的80MHz 设计对我可怜的 Spartan-3E 而言还是太高了。我的原始设计最高速度大约为 33 MHz,关键路径在级联加法器中,那是用在我简陋的浮点乘法器实施方案中的。幸运的是,Spartan-3E 配套提供众多 18 位硬件乘法器,能够将速度提升到近 50 MHz(面积却节省了 5%),但这时设计的其它部分又遇到了麻烦。Cray-1 具有大量 64 位数据路径,以及复杂的指令发布逻辑,这将 Spartan-3E 上的周期时间限制在 20 纳秒左右。目前我还算满意,而且较新的 Spartan-6 芯片将能满足 8-0 的水平要求。
外壳构造
硬件已经基本可以正常工作了,我开始投入一项有趣的工作,进行外壳构造。当然,电路设计是所有工程师都感兴趣的部分,不过我也要让自己的 Cray-1 看上去像个 Cray-1 的样子,这同样有趣。打造外壳的工作正好也让我的朋友 Pat 能试试他的新型 CNC 铣床。我去了几趟 Home Depot,在 Pat 的车库里度过了一个繁忙的周六(见图 2),总算获得了一个很像小型 Cray 的外壳。开发板为方形,我必须在基座方面多些创意(方形和 C 形不太搭配),不过该板尺寸很小,也就是说我设计的 Cray-1 的尺寸正好是正常 Cray-1 的十分之一。
我接下来又花了几周的时间去打磨、喷漆和抛光,最后还去了趟当地的织物店,以让我的小型 Cray-1也跟原型机一样有了特色化的内置仿皮座了,这样 Mattel 的新计算机工程师芭比娃娃终于有个地方歇脚了!
软件
CPU 基本可以正常工作了,外壳也已经就位,我准备宣布胜利了。我能够毫无问题地执行一些简单的指令回环和程序。不过能不能使用真正的软件呢?我全新的 Cray-1 有一大遗憾,就是完全缺乏软件,而且没有软件的计算机着实没什么价值。不幸的是,Cray-1 就诞生在一个没有因特网的时代,主要出售给一些听起来冠冕堂皇的政府机构。我花了几个月的时间在因特网上寻找软件,但还是一无所获。我给一些在国家实验室工作的朋友发了电子邮件,甚至还根据信息自由法案 (Freedom of Information Act) 向国家核安全机构(此处是指政府严密监察的名单)发函,但还是一无所获。
感到自己确实需要更多帮助,我最终决定在互联网上求助。我在自己网站的 micro-Cray 页面上发出了求助呼吁(同时展示我可爱的比例仅为正常 Cray-1 十分之一的外壳),而且还通过 Twitter 账户向一些朋友介绍该项目,通过因特网资源寻找帮助。几天之后,一些新闻站点都得知了我的故事,从全球各地给我发来大量电子邮件。不少电子邮件都是同情我经历的Cray爱好者发来的怀旧信。然而,最终有人表示有大摞大摞纸质版的几十年前的源代码,九轨磁带,甚至还有微缩胶片。有人还发电子邮件给我提供一份 20 年前的博士论文,包括一种少见的编程语言的Cray 兼容编译器的源代码(当然,需要在同样少见的编程语言中编写)。看来人们保存过时软件和文档以备今后之需,还真能应不时之需啊。
未来
我的缩微版大型机今后该怎么办呢(图 3)?我还想解决这台设备的一些故障并添加缺失的特性。我还没有完全解决软件问题,不过情况已经有所改观。一位热心网友找到了 20 世纪 80 年代末基于 DOS 的 Cray 仿真器,它同时也可作为简单的汇编程序(在 Windows 7 中也能正常运行)。相比直接使用 8 位机器码,用 Cray 汇编语言编程简直是一个梦想。如果我能读取老式介质,我或许就能获得源代码,运行至少一种操作系统,并使用真正的 Fortran 编译器。
另外,我的冷门爱好还引发了计算机历史博物馆 (
http://www.computerhistory.org/) 的兴趣,或许我的微缩版 Cray 有朝一日会归隐于加利福尼亚的山景城。不过同时我也开始设想下一个项目了。