比特大陆蚂蚁矿机S7

用Zynq SoC实现高效比特币矿机系统

长铗 发布在 技术指南,矿业动态 0 10683

作者:
Alexander Standridge

理学硕士研究生

加州大学北岭分校 astandridge@gmail.com

Calvin Ho

理学硕士研究生

加州大学北岭分校 calvin.ho.67@my.csun.edu

Shahnam Mirzaei

助理教授

加州大学北岭分校 shahnam.mirzaei@csun.edu

Ramin Roosta

教授

加州大学北岭分校 ramin.roosta@csun.edu
将可编程逻辑与处理器子系统集成在单个器件中,开发出适应性强、经济适用的比特币矿机。

比特币是一种虚拟货币,在过去几年里逐渐流行开来。由此,比特币的追随者通过采购或者“挖矿”比特币的形式,投入其部分资产来支持这种货币。挖矿是指使用计算机硬件为比特币网络执行数学计算的过程。提供服务的比特币矿工可以得到一笔报酬(目前是25比特币)以及任何内含的交易费用。由于网络报酬是按照所有矿工完成的计算量进行分配的,故挖矿的竞争异常激烈。

比特币挖矿开始是在CPU和GPU这样的低成本硬件上运行的一个软件进程。但随着比特币流行开来,挖矿过程发生了戏剧性转变。早期的矿工必须使用高功耗处理器才能实现令人满意的“哈希速度”,也就是挖矿速度。虽然使用CPU/GPU挖矿效率十分低下,但其灵活度足以适应比特币协议的变化。近年来,挖矿活动的重心慢慢转移到专用或半专用ASIC硬件上,以优化和实现高效“哈希速度”。转用这种硬件提高了挖矿效率,但其代价是降低了适应挖矿协议变化的灵活性。

ASIC是一种在特定应用中用来高效执行某些特定任务的专用硬件。虽然ASIC比特币矿机成本相对较低,且得到的“哈希速度”也相当优异,但其代价是降低了灵活性,难以适应协议的变化。

与ASIC相似,FPGA可也用作高效矿机系统,而且成本也相对较低。此外,FPGA与ASIC相比灵活性更强,能够适应比特币协议的变化。目前的难题是需要设计出一款不依靠PC主机或中继装置就能连接到比特币网络的完全高效且相当灵活的挖矿系统。我们团队使用赛灵思Zynq-7000 All Programmable SoC顺利完成了这一任务。

总体思路

要设计出一个由可行的比特币节点和高效灵活的矿机等组成的完整挖矿系统,我们需要某种功能强大的FPGA芯片,来同时满足灵活性和性能要求。除FPGA外,我们还需要使用处理引擎来提高效率。

在这个完整的片上系统(SoC)上,我们需要经优化的内核来运行包括网络维护和交易处理在内的所有要求的比特币任务。能满足所有这些条件的硬件就是位于ZedBoard开发板上的Zynq-7020 SoC。 ZedBoard售价大约在300到400美元,与同类产品相比,价格相当便宜(参见 http://www.zedboard.org/buy )。

Zynq-7020 SoC芯片集成有两个ARM® Cortex™-A9处理器和85,000个Artix®-7 FPGA逻辑单元。ZedBoard开发板还内置有512MB DDR3存储器,能够让我们更快速地运行SoC设计。最后,ZedBoard还提供一个用于海量存储的SD卡槽,以便于我们把整个更新后的比特币程序存放在SD卡上。

我们使用ZedBoard实现了我们的SoC比特币矿机。它由主机、中继器、驱动程序和矿机组成。我们使用原始比特币客户端的非图形化界面作为主机,与比特币网络进行互动。中继器使用驱动程序从主机向矿机传递工作。

简单来说,可以把比特币挖矿进程归结为一个SHA-256进程和一个比较器的组合。 SHA-256进程负责对块头信息进行两次处理,然后将其与比特币网的扩展目标难度做比较。

挖矿内核的深入

我们根据用美国商务部SHA-256的规格,采用Vivado® HLS(高层次综合)开始开发挖矿内核。使用Vivado HLS的快速行为测试功能,我们很快完成了几个原型挖矿内核的布局,从简单的单进程系统到复杂的多进程系统都有。但在探究挖矿内核的详细结构前,先了解一下SHA-256进程的基本知识是大有裨益的。

SHA-256经过64次移位、相加和异或运算迭代,将64字节数据生成32字节哈希值。在这个运算过程中,用8个4字节寄存器保存每一轮迭代的结果。当这一过程完成后,将四个寄存器连接起来,生成哈希值。如果输入数据不足63字节,就将其填补为63字节,第64个字节用于存储输入数据的长度。更为常见的情况是输入数据的长度大于63字节。

在这种情况下,数据填补为64的最接近倍数,并将最后一个字节保留用于存储数据长度。每一个64字节数据块使用上一个数据块的输出(也称为中间态)作为下一个数据块的基础,依次运行SHA-256进程。

使用Vivado HLS,SHA-256进程就是个简单的“for”循环设计:用一个阵列保持每次迭代所需的常数,用另一个阵列保持后续迭代使用的临时值,用8个变量保持每次迭代的结果,并且定义逻辑运算。如图2所示。

4590-9400-tu1

简单的来说,可以把比特币挖矿过程归结为一个SHA-256进程和一个比较器的组合。 SHA-256进程负责对块头信息进行两次处理,然后将其与比特币网的扩展目标难度做比较,如图3A所示。这个简单的概念在硬件中实施起来却很复杂,因为第一版的比特币块头为80字节长。这就意味着初始路径需要运行SHA-256进程两次,后续路径仅需要运行一次,如图3B所示。这种定义两个单独的SHA-256模块的双路径,会让情况复杂化,因为我们需要让SHA-256模块尽量通用,以节省开发时间,实现重复利用。 这种对SHA-256模块的一般性要求决定了我们使用的输入和输出,可将其设定为32字节初始值、64字节数据和32字节的哈希值。因此,在隔离SHA-256进程的内核侧后,我们可以随意布局这些输入。

我们开发的三个原型中的第一个原型使用单个SHA-256进程模块。从一开始我们就知道这个内核是三个中最慢的,因为没有使用流水线。但我们想看看能实现的最小SHA-256进程是多大。

第二个原型内置三个串联起来的单独SHA-256进程模块,如图3C所示。这种配置在第一个进程处理数据头信息中的第一个64个字节时允许静态输入。第二个进程负责处理数据头中剩余的16个字节以及加上填补数据所需的48字节。第三个进程负责处理从前两个进程得到的哈希值结果。 这三个单独的进程简化了控制逻辑,便于使用简单流水线。

第三个也是最后一个原型使用两个SHA-256进程模块,并在比特币挖矿社区使用的比特币数据头信息和挖矿进程中充分利用专用补丁的作用。只有在修改模块使头64字节发生变化时,才会布局这种数据头信息。这意味着一旦头64个字节处理完毕,就可以保存输出数据(中间态),只处理数据头中的最后16个字节,就可以大幅度地提升哈希速度(参见图3D)。

4590-9401-tu2

比较器属于主要组件,经适当设计能够显著提升性能。解是一个哈希值,其数值小于比特币系统定义的32字节扩展目标难度。这就意味着必须比较产生的每一个哈希值,等待看是否可以找到解。由于扩展目标难度搭配有一个专用补丁,所以不管难度如何,头四个字节会一直为0。随着网络难度的增大,前导零的数量也在增多。在编写本程序时,扩展目标难度的头13个字节都是零。因此,除了要将整个哈希值与目标难度做比较,我们还需要检查前多少个字节是零。如果它们是零,我们就将哈希值与目标难度做比较。如果它们不是零,我们需要将此哈希值丢弃,从新再来。

在清楚现有各种原型的结果后,我们最终选用比特币开源社区专为赛灵思FPGA开发的第三个内核。

ISE的开发

比特币挖矿是在0和232-1之间找到可作为解的数值的比赛。因此,实际上只有两种方法可以改善挖矿内核的性能:加快处理或分而治之。我们使用Spartan®-3和Spartan-6开发板测试了一系列不同的频率、流水线技巧和并行化方法。

我们先用Spartan-3E开发板开始频率测试。但很快就发现超过50MHz就无能为力。为此,我们只好用Spartan-6来完成频率测试。

我们在Spartan-6开发板上测试了50、100和150MHz三种不同频率,得到了可预测的结果,分别得到了0.8 MHps、1.6 MHps和2.4 MHps。 在并行化和流水线测试中,我们还尝试了75MHz和125MHz,不过这两种频率只是使矿机适配Spartan-6所做的妥协。

我们从开源社区选择挖矿内核的原因之一是:它的设计理念是用深度变量来控制流水线级数。深度是介于0和6之间的一个指数值,用于控制以2的幂计的VHDL“generate”命令的执行次数,即20次到26次。我们进行初始频率测试的深度是0,即每个进程只执行一轮。

在Spartan-3e上,我们测试了深度0和1,直至运行到发生时序约束问题。深度0在50MHz下可得到大约0.8MHps,深度1可得到大约1.6MHps。

在Spartan-6上,在运行到发生时序约束问题之前,我们实现的深度可以达 到3。运行在50MHz,深度为0和1时,Spartan-6与Spartan3得到的结果一样。这时我们注意到一个有趣的趋势。频率翻倍与增大流水线深度的效果相同。上限由可用的路由资源决定,峰值平均数大约为3.8MHps,如图4所示。

4590-9402-tu3

SHA-256进程模块需要完成10次不同的32位相加。在本设计中,我们试图在一个时钟周期内完成全部相加。为缩短最长路径,我们试图将加法器链细分为一系列阶段。但这样做会让整个核的控制逻辑发生显著改变,需要彻底重新编写。我们放弃了这些修改,以节省时间和精力。

我们最后测试的性能改进方法是并行化。只需稍作修改,就可以让SHA-256组数变成2倍和4倍。每组由两个SHA-256进程模块组成。对组数提高2倍的SHA-256而言,这种调整可有效地把组数减半;对组数提高4倍的SHA-256,就是四分之一。为让这些额外的SHA进程能够在Spartan-6上运行,我们不得不降低系统频率。四组SHA-256进程模块在75MHz运行,两组在125MHz运行。哈希速度的改善情况难以记录。我们可以轻易地看到单个SHA-256组的哈希速度,不过多组SHA-256构成的挖矿内核找到解的速度比隐含的哈希速度更快。

使用EDK

在FPGA测试之后,下一步是把挖矿内核连接到Zynq SoC的AXI4总线。赛灵思嵌入式开发套件(EDK)预先加载有专为Zynq SoC设计的配置实用工具,便于我们轻松地配置每一个方面。默认情况下该系统会启用512MB DDR3、以太网、USB和SD接口,这是比特币SoC所需的全部配置。

两个Cortex-A9处理器采用AXI4接口,而非以往软核系统使用的PLB系统。所有的外设均经AXI4接口连接到处理器,如图5所示。

4590-9403-tu4

EDK定制外设向导针对AXI4接口的不同变种提供存根代码,且用作挖矿内核AXI接口的开发基础。为简单起见,我们使用AXI4-Lite接口为挖矿内核提供简单的读写功能。在理想的情况下,开发人员会想要使用标准的AXI4接口,以发挥先进接口控制功能的作用,如数据突发。

为达到简单的目的,我们使用三个存储器映射寄存器来处理挖矿内核的I/O。第一个寄存器负责向矿机馈送主机数据包。该寄存器记录通过的数据量,到第11个字通过后自我加锁。加锁会在找到解后自动解锁。如果有必要,也可通过状态寄存器手动解锁。

我们将第二个寄存器用作状态寄存器,给特定的位做上标记,用于代表挖矿内核在运行过程中所处的不同状态。鉴于我们的设计简单,我们只使用三个标记,即加载标记、运行标记和发现解标记。当挖矿内核收到11个字时即触发加载标记,如前所述,当我们向其写入时,即清除。开始/运行标记在启动挖矿内核时设置,在找到解时被挖矿内核清除。最终的寄存器为输出寄存器,用于加载找到的解。

在加入这个新组件前,我们对AXI4-Lite接口开发的每一个阶段进行了测试。我们还使用赛灵思软件开发套件中的准系统,测试了AXI4-Lite接口。测试有两个目的:首先,确认挖矿内核的AXI4-Lite接口是否正常工作;其次,确保挖矿内核是否以正确的字节存储次序格式接收数据。

为了在不牺牲适应性的前提下改进我们目前的设计,我们准备添加更多连接到主比特币节点的挖矿内核。添加更多挖矿内核后可显著提升性能,加快整体哈希速度。

嵌入式LINUX

完成挖矿内核与处理器的连接后,我们转向软件开发工作。理想的考虑是使用Linux内核构建我们自己的固件,以实现最高性能。为简化开发工作,我们安装完整的Linux版本。我们使用的是Xillybus开发的Xillinux,属于Ubuntu的衍生版本,用于快速完成嵌入式系统开发。

我们的首要任务是为Cortex-A9架构编译编译Bitcoind。我们使用原始的开源比特币软件,以保证与比特币网络的兼容性。

测试Bitcoin是件简单的事情。我们先运行后台程序,等待下载规模可观的数据库链,然后使用行命令,启动Bitcoind内建的CPU挖矿软件。

对于Linux驱动程序,必须实现一部分专用功能,将其链接到Linux内核,才能实现正确运行。当加载有特定初始化功能的驱动程序运行时,让系统为与硬件互动做好准备。在此项功能中,我们首先确认挖矿内核准备链接的存储器地址可以使用,然后将该地址保留起来。与准系统不同,Linux使用虚拟存储器地址方案,即在我们可以使用保留的地址之前,我们必须先为挖矿内核申请地址重映射。内核会通过重映射,为我们提供一个虚拟地址,供我们随后与挖矿内核寄存器通信。

既然现在我们可以使用这个硬件,初始化功能随即可对挖矿内核进行一个简单的测试,来确认内核工作正常。如果运行正常,就登记内核寄存器的主器件号和次器件号,用于在用户程序中识别该器件。每一项功能都有一个计数器,退出功能就是初始化功能的计数器。用此功能时,我们撤销在初始化过程中完成的一切操作,具体而言就是释放驱动程序使用的主器件号和次器件号,然后释放映射的虚拟地址。

我们首先从中继程序调用挖矿内核时,打开功能开始运行。我们在这里所做的全部工作是确认初始化过程中功能自检是否成功。如果自检失败,我们就给出系统出错信息,失败退出。当器件从中继程序中释放时,即调用关闭功能。但由于我们只在打开功能中检查自检结果,故关闭功能中没有什么可做的。读取功能负责查看数据缓存,判断用户正在读取哪一个端口,然后从挖矿内核获取数据,并将其传回。写入功能负责判断用户正在写入的寄存器,然后将数据传递给挖矿内核。

我们系统的最后一个组件是一个小巧的中继程序,用于通过驱动程序将工作从Bitcoind传递给挖矿内核,并会送结果。理所当然的,这个中继程序需要查看Bitcoind是否在运行中,挖矿内核是否准备就绪,是否工作正常。由于中继程序在大多数时间里处于待机状态,我们准备设计一个统计编制子系统,用于挖矿数据并将数据组织在一个日志文件中。在理想情况下,我们将使用Web主机界面供配置、显示统计结果和显示器件状态使用。

完整高效的挖矿系统
我们用ZebBoard开发板上的赛灵思Zynq-7000 All Programmable SoC开发出高效完整的比特币挖矿系统。该开发板能够灵活地适应比特币协议的变化,同时提供具备SoC功能的高性能FPGA解决方案。为了在不牺牲适应性的前提下改进我们目前的设计,我们准备添加更多连接到主比特币节点的挖矿内核。添加更多挖矿内核后可显著地提升性能,加快整体哈希速度。

另一项进一步优化该设计的改进是使用专用固件。我们目前的设计运行的是 Ubuntu Linux 12.04版。这个版本有大量不必要的进程和SSH等比特币程序同时运行。在比特币程序运行的同时运行这些进程是对开发板资源的浪费。在将来的版本中,我们将取消这些进程,只运行专为比特币任务定制的我们自己的固件。

原文

版权声明: by nc" sa 作者保留权利。文章为作者独立观点,不代表巴比特立场。

评论:0

您需要登录后才可以回复 登录|注册