Skip to content
EVM+协处理器

胶水和协处理器架构

作者:维塔利克·布特林 2024年9月2日 原文链接

特别感谢 Justin Drake、Georgios Konstantopoulos、Andrej Karpathy、Michael Gao、Tarun Chitra 以及各位 Flashbots 贡献者的反馈和审阅。

如果你对现代世界中任何资源密集型计算进行较为详细的分析,你会反复发现这样一个特点:计算可以被分为两个部分:

  1. 相对较少量的复杂但计算强度不高的"业务逻辑"

  2. 大量密集但高度结构化的"计算密集型工作"

这两种形式的计算最好用不同的方式来处理:前者需要使用可能效率较低但必须具有很高通用性的架构,而后者需要使用可能通用性较低但必须具有很高效率的架构。

在实践中有哪些这种分离的例子?

首先,让我们看看我最熟悉的环境——以太坊虚拟机(EVM) 的内部运作。这是我最近一笔以太坊交易的 geth 调试追踪:更新我的博客在 ENS 上的 IPFS 哈希值。这笔交易总共消耗了 46924 gas,可以按以下方式分类:

  • 基础成本:21000

  • 调用数据:1556

  • EVM 执行:24368

  • SLOAD 操作码:6400

  • SSTORE 操作码:10100

  • LOG 操作码:2149

  • 其他:6719

ENS 哈希更新的 EVM 追踪。倒数第二列是 gas 消耗。

这个案例告诉我们:大部分执行(如果只看 EVM 约占 73%,如果包括覆盖计算的基础成本部分则约占 85%)集中在极少数结构化的昂贵操作上:存储读写、日志记录和加密(基础成本包括 3000 用于签名验证,EVM 还包括 272 用于哈希计算)。其余的执行是"业务逻辑":处理调用数据的位来提取我试图设置的记录 ID 和要设置的哈希值等。在代币转账中,这将包括添加和减少余额,在更高级的应用中,可能包括循环等。

在 EVM 中,这两种形式的执行以不同方式处理。高级业务逻辑通常用更高级的语言编写,比如 Solidity,然后编译到 EVM。昂贵的工作仍然由 EVM 操作码(SLOAD 等)触发,但实际计算的 99% 以上是在客户端代码(甚至库)中直接编写的专门模块中完成的。

为了加深对这种模式的理解,让我们在另一个场景中探讨它:使用 torch 编写的 AI 代码。

transformer 模型中一个区块的前向传播,源代码

我们在这里看到了什么?我们看到用 Python 编写的相对较少的"业务逻辑"代码,它描述了正在执行的操作的结构。在实际应用中,还会有另一类业务逻辑,用于确定如何获取输入以及如何处理输出等细节。但是,如果我们深入观察每个独立操作本身(self.normtorch.cat+*,以及 self.attn 内部的各个步骤……),我们会看到向量化计算(vectorized computation):同样的操作在大量数值上并行计算。与第一个示例类似,只有少部分计算用于业务逻辑,而大部分计算都用于执行大规模结构化的矩阵和向量运算——实际上,主要就是矩阵乘法。

就像在 EVM 示例中一样,这两类工作是以不同方式处理的。高层业务逻辑代码是用 Python 编写的,这是一种高度通用和灵活但速度很慢的语言,我们接受这种低效是因为它只涉及总计算成本的一小部分。同时,密集型运算操作是用高度优化的代码编写的,通常是在 GPU 上运行的 CUDA 代码。我们甚至越来越多地看到大语言模型(LLM)推理在专用集成电路(ASIC)上进行

现代可编程密码学,例如SNARKs,再次展现了类似的模式,而且是在两个层面上。首先,证明系统可以用高级语言编写,其中繁重的计算通过向量化操作完成,就像上面的人工智能示例一样。我的圆形STARK代码展示了这一实践。其次,在密码学内部执行的程序本身可以采用将通用业务逻辑和高度结构化的复杂计算分开的方式编写。

要了解这是如何运作的,我们可以关注STARK证明领域的最新趋势。为了实现通用性和易用性,各个团队越来越多地为广泛采用的最小虚拟机(如RISC-V)构建STARK证明器。任何需要证明其执行过程的程序都可以被编译成RISC-V,然后证明器可以证明该代码在RISC-V上的执行过程。

图片来源于RiscZero文档

这种方法极为便利:这意味着我们只需要编写一次证明器逻辑,从那时起,任何需要被证明的程序都可以用任何"传统"的编程语言来编写(例如,RiskZero支持Rust)。然而,这里存在一个问题:这种方法会产生显著的开销。可编程密码学本身已经非常昂贵;再加上在RISC-V解释器内运行代码的开销就太大了。因此,开发人员提出了一个解决方案:识别构成计算主体的特定昂贵操作(通常是哈希和签名),然后创建专门的模块来高效地证明这些操作。然后,你只需将效率低但通用的RISC-V证明系统和高效但专用的证明系统结合起来,就能够兼得两者的优势。

除了ZK-SNARKs之外的可编程密码学,比如多方计算(MPC)全同态加密(FHE)很可能也会使用类似的方法进行优化。

这里存在什么样的一般模式?

现代计算越来越多地遵循我所称的粘合层和协处理器架构:你有一个中央"粘合"组件,它具有高通用性但低效率,负责在一个或多个协处理器组件之间传输数据,而这些协处理器组件具有低通用性但高效率。

这是一个简化的说法:实际上,在效率和通用性的权衡曲线上,几乎总是存在两个以上的层次。GPU和其他在业界常被称为"协处理器"的芯片,比CPU的通用性低,但比ASIC的通用性高。关于专业化程度的取舍非常复杂,这些决策通常基于对算法哪些部分在五年内仍将保持不变、哪些部分在六个月内就会改变的预测和直觉。在零知识证明架构中,我们同样经常看到多层专业化。但就广泛的思维模型而言,考虑两个层次就足够了。在计算的许多领域都存在这种相似之处:

领域粘合层协处理器
以太坊EVM用于专门操作的专用操作码/预编译
AI(如大语言模型)Python(通常)通过CUDA的GPU;ASIC
Web应用JavascriptWASM
可编程密码学RISC-V专用模块(如用于哈希和签名)

从上述例子来看,计算可以这样拆分似乎是很自然的事情。确实,在计算领域中几十年来都能找到专业化的例子。然而,我认为这种分离正在加剧。我认为这是出于以下几个关键原因:

  1. 我们最近才遇到了提升 CPU 时钟速度的极限,因此进一步的性能提升只能通过并行化来实现。然而,并行化的推理过程很困难,所以对开发者而言,继续按照顺序思维进行推理往往更加实用,而让并行化在后端进行,将其封装在为特定操作构建的专门模块中。

  2. 计算能力直到最近才变得如此之快,以至于业务逻辑的计算成本变得真正可以忽略不计。在这种情况下,对运行业务逻辑的虚拟机进行优化时,将重点放在计算效率之外的目标上是有意义的:开发者友好性、熟悉度、安全性以及其他类似目标。与此同时,专门的"协处理器"模块可以继续以效率为导向进行设计,并通过与系统核心之间相对简单的"接口"来获得安全性和开发者友好性。

  3. 最重要的高计算成本操作正变得越来越明确。这在密码学领域最为显著,其中最可能被使用的特定昂贵操作已经很清晰:模运算、椭圆曲线线性组合(又称多标量乘法)、快速傅里叶变换等。这在人工智能领域也变得越来越清晰,二十多年来,计算的主体一直是"主要是矩阵乘法"(尽管有着不同的精度水平)。类似的趋势在其他领域也有出现。与 20 年前相比,(计算密集型)计算中的未知因素已经少了很多。

这意味着什么?

一个关键要点是,粘合层应该优化其作为粘合层的功能,而协处理器应该优化其作为协处理器的功能。让我们从几个关键领域来探讨这一点的含义。

EVM

区块链虚拟机(如 EVM)不需要高效,它们只需要让开发者感到熟悉。 在低效率虚拟机中的计算,通过添加适当的协处理器(也称为"预编译"),在实践中可以达到与原生高效虚拟机几乎相同的效率。EVM 的 256 位寄存器所带来的开销相对较小,而 EVM 的熟悉度和现有开发者生态系统带来的好处则是巨大且持久的。优化 EVM 的开发团队甚至发现,并行化的缺失通常并不是可扩展性的主要障碍。

改进 EVM 的最佳方式可能就是(i)添加更好的预编译或专门的操作码,例如,EVM-MAXSIMD的某种组合可能是合理的,以及(ii)改进存储布局,例如Verkle树变更通过大幅降低访问相邻存储槽的成本,从而产生了这种效果。

以太坊 Verkle 树提案中的存储优化,将相邻的存储键放在一起,并调整 gas 成本以反映这一点。像这样的优化,加上更好的预编译,可能比调整 EVM 本身更重要。

安全计算和开放硬件

现代计算在硬件层面提升安全性的一大挑战在于其过于复杂和专有的特性:芯片设计追求高效率,这就需要专有的优化。后门容易隐藏,而且侧信道漏洞不断被发现。

从多个角度来看,推动更开放、更安全的替代方案的努力一直在持续。越来越多的计算任务在可信执行环境中完成,包括在用户的手机上,这已经提高了用户的安全性。推动更开源的消费者硬件的努力仍在继续,最近的成功案例包括运行Ubuntu的RISC-V笔记本电脑

运行Debian的RISC-V笔记本电脑,来源

然而,效率仍然是一个问题。上述文章的作者写道:

对于像RISC-V这样较新的开源芯片设计来说,要与已经存在和改进了数十年的处理器技术正面竞争是不现实的。进步总是要有一个起点。

更偏执的想法,比如这个在 FPGA 上构建 RISC-V 计算机的设计,面临着更多的开销。但如果粘合层和协处理器架构意味着这种开销实际上并不重要呢?如果我们接受开源和安全芯片会比专有芯片慢的现实,必要时甚至放弃投机执行和分支预测等常见优化,但通过添加(如果需要的话,可以是专有的)ASIC 模块来补偿特定类型的最密集计算呢?敏感计算可以在"主芯片"上完成,该芯片将针对安全性、开源设计和侧信道攻击防护进行优化。更密集的计算(例如,零知识证明、人工智能)将在 ASIC 模块中完成,这些模块能获取更少的计算信息(通过加密混淆,在某些情况下甚至可能是零知识)。

密码学

另一个重要的收获是,这一切对密码学的发展都非常乐观,特别是可编程密码学正在逐步成为主流。我们已经看到在 SNARK、MPC 等环境中,某些特定的高度结构化计算已经实现了超高效率:某些哈希函数的计算成本仅比直接运行高几百倍,而在 AI 领域(主要是矩阵乘法运算)甚至可以实现更低的计算成本。像 GKR 这样的进一步改进可能会让这些成本进一步降低。虽然完全通用的虚拟机执行,特别是在 RISC-V 解释器内执行时,可能会继续保持约一万倍的资源消耗,但基于本文所述的原因,这并不会造成问题:只要计算中最密集的部分能够使用高效的专用技术单独处理,总体资源消耗就是可控的。

一个用于矩阵乘法的专用 MPC 的简化图,这是 AI 模型推理中最大的组成部分。更多细节请参见这篇论文,包括如何保持模型和输入的私密性。

"连接层只需要易于使用,不需要高效"这一理念存在一个例外,那就是延迟,以及在较小程度上的数据带宽。如果一个计算过程需要对同一数据进行数十次重复的密集运算(这在密码学和 AI 中都很常见),那么任何由低效连接层导致的延迟都可能成为运行时间的主要瓶颈。因此,连接层仍然需要满足效率要求,只是这些要求更加具有特定性。

结论

总的来说,我认为上述趋势从多个角度来看都是非常积极的发展。首先,这是在保持开发者友好性的同时实现计算效率最大化的合理方式,能够同时获得更多这两方面的好处对每个人都有利。特别是通过实现客户端更多的专业化效率提升,它提高了我们在用户本地硬件上运行既敏感又要求高性能的计算(例如 ZK 证明、LLM 推理)的能力。其次,它创造了一个确保效率提升不会损害其他价值(尤其是安全性、开放性和简单性)的重要机遇:计算机硬件的侧信道安全性和开放性、降低 ZK-SNARKs 的电路复杂度,以及降低虚拟机的复杂性。从历史上看,追求效率往往导致这些其他因素被放在次要位置。而在粘合层和协处理器架构中,这种情况不再必要。机器的一部分优化效率,另一部分优化通用性和其他价值,两者协同工作。

这种趋势对密码学也非常有利,因为密码学本身就是"昂贵的结构化计算"的一个重要例子,这种趋势可以加速这类计算。这为提高安全性提供了进一步的机会。在区块链世界中,安全性的提升也成为可能:我们可以减少对虚拟机的优化担忧,转而更多地关注预编译和其他与虚拟机并存的功能的优化。

第三,这一趋势为较小和较新的参与者提供了机会。如果计算变得不那么单一而更加模块化,那么准入门槛就会大大降低。即使只有一种类型计算的 ASIC,也有可能产生重要影响。这一点在 ZK 证明领域和 EVM 优化方面同样适用。编写接近前沿水平效率的代码将变得更加简单便捷。对此类代码进行审计和形式化验证也将变得更加容易上手。最后,由于这些截然不同的计算领域正在朝着某些共同模式发展,这为它们之间的合作和相互学习创造了更多机会。

ETHStudy (An Ethereum Ecosystem Initiative)
Supported by Uweb(University of Web3)