原文标题:《Glue and coprocessor architectures》
撰文:Vitalik Buterin,以太坊联合创始人
编译:Chris,Techub News
在现代的资源密集型计算中,如果你对任何计算过程进行中等程度的分析,你会发现这个计算过程通常可以分为两个部分:
-
相对较少的复杂但计算强度不高的「业务逻辑」
这是指在计算过程中,需要进行一些复杂的决策或规则处理。这些逻辑虽然复杂,但并不需要大量的计算资源。这部分通常涉及到数据的验证、条件判断、数据流的控制等操作。
-
大量密集但高度结构化的「昂贵工作」:
这是指计算中需要执行的繁重的、需要大量计算资源的任务。虽然这些任务的计算强度很高,但它们通常是有规律和可预测的。例如,大规模的数据处理、数值计算或机器学习训练等。这部分工作虽然需要消耗大量的计算资源,但因为它们的结构化特性,可以通过优化或并行处理来提高效率。
在计算任务中,将「业务逻辑」和「昂贵工作」分开的例子
我最近在以太坊上执行了一笔交易,该交易是为了更新ENS上我博客的IPFS哈希。我通过 geth 的调试工具对这次交易进行了跟踪分析。结果显示,这笔交易总共消耗了46924 Gas,具体分布如下:
-
基础费用是21000 Gas,这是每笔交易都需要支付的基本成本。
-
发送给智能合约的 Calldata 耗了1556 Gas。
-
EVM 执行过程中,用于处理智能合约的计算和逻辑的部分消耗了24368 Gas。
-
SLOAD 花费了6400 Gas,而 SSTORE 则花费了10100 Gas。
-
LOG 操作消耗了2149 Gas,剩下的6719 Gas则花在了其他各种小操作上。

交易执行的大部分资源(大约73%到85%)被用于执行一些「昂贵」的操作。这些操作包括读取和写入存储(存储读写)、记录日志(logs),以及与加密相关的操作(比如哈希和签名验证)。基础成本中包含了为签名验证支付的3000 Gas,EVM 还为哈希操作支付了272 Gas,这些都属于昂贵操作的一部分。剩下的部分(大约15%到27%)是「业务逻辑」,比如处理输入数据(Calldata)中的位信息,以提取要设置的记录ID和哈希值。在更复杂的应用中,比如代币转移,这部分业务逻辑可能包括增加和减少余额;在更高级的应用中,还可能包括循环等更复杂的操作。
在 EVM 中,业务逻辑和资源密集型操作以不同的方式处理:
业务逻辑
这部分逻辑通常用高级编程语言(如Solidity)编写。Solidity是一种专门用于编写智能合约的语言。开发者用Solidity编写智能合约的业务逻辑,然后将其编译成EVM可以理解和执行的字节码。这些编译后的代码在EVM中运行。
资源密集型操作
虽然资源密集型操作(如SLOAD,用于从存储中读取数据)是由EVM的操作码触发的,但实际的计算大部分是在客户端代码中完成的。这些操作的计算不是直接在EVM内部进行的,而是在客户端(比如运行以太坊节点的软件)或者相关的库中执行的。这意味着,虽然EVM触发了这些昂贵操作,但计算的实际执行是依赖于更底层的系统或模块。
为了加深我们对这种模式的理解,接下来我们分析一下使用Python和Torch(PyTorch库)编写的 AI 代码

我们在代码中看到的是相对少量的用 Python 编写的「业务逻辑」,这些「业务逻辑」用来描述操作的整体结构和流程。例如,如何将输入数据传递到模型中,以及如何处理模型的输出。在实际应用中,还存在另一种「业务逻辑」,它负责决定如何获取输入数据和如何处理输出结果。当我们进一步探究代码中的每个具体操作时(比如self.norm、torch.cat、加法+、乘法*、以及self.attn中的步骤),我们会发现这些操作实际上涉及矢量化计算。矢量化计算意味着同一个操作在大量数据上同时执行,也就是并行计算。类似于以太坊中的计算,大部分计算资源并不是花在这些业务逻辑上,而是集中在执行这些大型的、结构化的矩阵和矢量运算上。
类似于以太坊中的计算,两种类型的工作以两种不同的方式处理。高层次的业务逻辑用Python编写。Python是一种通用且灵活的语言,易于编写和理解,但它的执行速度相对较慢。然而,由于这部分代码只涉及到计算总量的一小部分,我们可以接受它的低效性。密集计算操作,包括大量的数学计算,如矩阵和向量运算。这些操作通常用高度优化的代码编写,特别是CUDA代码,在GPU上运行以获得更高的计算效率。CUDA是为并行计算设计的编程语言,专门用于加速这些密集型计算任务。随着技术的发展,越来越多的大型语言模型(LLM)的推理过程正在使用 ASICs 来进行。
现代可编程密码学(如SNARKs)遵循了与AI计算相似的模式。首先,prover 可以使用高级编程语言编写程序,其中重度计算工作是通过矢量化操作来完成的。这与之前提到的AI示例类似,即使用高度优化的并行计算来处理大量的数据,我有关 circle STARK 的文章证明了这一点。其次,在密码学程序内部,执行的代码本身也可以按照类似的模式进行编写,即将代码分为通用的业务逻辑部分和高度结构化的、资源密集型的工作部分。
为了使STARK证明通用且易于使用,越来越多的团队正在为广泛采用的最小化虚拟机(如RISC-V)构建STARK证明器。任何需要被证明执行的程序都可以先编译成RISC-V指令集,然后STARK证明器可以针对这些RISC-V代码的执行过程进行证明。

使用RISC-V这样的通用虚拟机架构来构建STARK证明器非常方便。因为这样一来,只需编写一次证明逻辑,之后任何需要证明的程序都可以用常规编程语言(如Rust)编写,然后通过这个通用架构进行证明。但是编程密码学(例如STARKs)本身就需要大量的计算资源,成本很高。而在RISC-V解释器中运行代码会进一步增加计算负担,导致整个证明过程变得更加耗费资源,降低了系统的效率。为了克服这个问题,开发者想出了一个方案,他们会识别出占据大部分计算资源的特定昂贵操作(如哈希和签名),并为这些操作创建专门的模块,这些模块能够非常高效地证明这些操作。然后,他们将这种低效但通用的RISC-V证明系统与高效但专门化的证明系统结合起来。通过这种方式,他们能够在保持通用性的同时,大幅提高处理那些资源密集型操作的效率,从而实现两全其美的效果。
除了ZK-SNARK之外的其他可编程加密技术,如多方计算(MPC)和全同态加密(FHE),也可能采用类似的方法来进行优化。
通用的处理方式
现代计算架构越来越倾向于采用一种我称之为「glue and coprocessor」的架构模式。在这种架构中:
-
glue是中心部分,具有很高的通用性,但效率较低。它负责在不同的协处理器之间传递数据,管理整体流程和协调各个部分的操作。
-
coprocessor的通用性较低,但效率极高。它们专门负责处理特定类型的计算任务,比如大规模的并行计算、加密操作或图像处理。

虽然「glue and coprocessor」架构是一个有用的概念,但在实际应用中,存在多个层次,这些层次之间存在效率和通用性的权衡,例如,GPU在工业界中,GPU通常被称为coprocessor,它们比CPU(中央处理器)更专用,但比ASIC(专用集成电路)更通用。而 ASIC 则更专用,只能执行特定的任务,但它们在这些任务上效率极高。在决定硬件或算法的专用程度时,通常需要权衡。这种决策基于对未来的预测和直觉,例如哪个部分的算法在未来五年内不会改变,哪个部分可能在六个月内就会发生变化。这些判断影响着系统的设计和硬件的选择。类似地,在ZK证明架构中,也常常看到多层次的专用化。不同的部分可能会有不同程度的专用性,以达到最佳的性能和灵活性。尽管实际情况复杂,但为了便于理解和思考,通常可以将这些复杂性简化为两个层次:一个是高通用性但低效率的部分,另一个是低通用性但高效率的部分。这种简化模型在许多计算领域都有类似的应用。

通过前面的例子,这种将计算任务分为通用的 glue 组件和专用的Coprocessor 组件的模式,无论是在区块链、人工智能、网页应用还是可编程加密领域都无处不在。几十年来,在计算领域我们一直可以看到这种分离的例子。无论是CPU与GPU的分工,还是操作系统中的内核与用户态的分离,专门化一直存在。尽管专门化的分离模式已经有历史渊源,但我认为,这种分离的趋势正在增加。为什么这种趋势会越来越明显?
-
在过去的几十年里,计算机性能的提升很大程度上依赖于提高CPU的时钟速度(即处理器每秒钟执行指令的频率)。然而,随着技术的发展,CPU时钟速度的增长已经接近物理极限,进一步提高变得非常困难。由于单纯依赖提高时钟速度已经不能显著提升性能,计算性能的提升现在主要依赖于并行化。然而,并行化计算非常复杂,开发者在设计和实现并行算法时,需要考虑如何有效地分配任务、避免竞争条件、管理同步等问题,这使得并行化变得困难且容易出错。为了简化开发过程,开发者通常仍然采用传统的顺序思维方式编写代码,而将并行化的复杂性交由后台处理。这意味着,并行计算通常被封装在专用的模块中,这些模块专门为特定操作设计,能够高效地在后台进行并行化处理。这样,开发者可以继续使用熟悉的顺序逻辑,而后台系统则负责将这些任务并行化。
-
随着计算技术的发展,计算速度大幅提升,业务逻辑(即处理流程和控制逻辑)的计算成本变得微不足道。在这种情况下,虚拟机(如EVM、Python解释器等)不再需要专注于计算效率的优化。相反,可以将优化目标转向其他方面,例如:
开发者友好性:提供更直观、易用的编程接口和工具。
熟悉性:采用开发者已经熟悉的编程语言或环境,降低学习曲线。
安全性:确保业务逻辑的执行环境安全可靠,防止漏洞和攻击。
在现代计算领域,尤其是加密学和人工智能中,最昂贵的计算操作已经变得非常明确。在加密学中,昂贵的操作类型包括模运算、椭圆曲线线性组合(即多标量乘法)、快速傅里叶变换(FFT)等。在人工智能中,绝大多数的计算资源都被用于矩阵乘法,尽管在不同情况下需要不同精度的矩阵运算。事实上,过去二十多年里,矩阵乘法一直是AI计算的主要负担。当与二十年前相比,前计算领域中「未知的未知」(即我们尚未意识到的挑战或问题)比20年前要少得多。
这意味着什么?
glue 组件应该专注于成为优秀 的glue,而 coprocessor 组件则应该专注于成为优秀的 coprocessor。
EVM
EVM不需要在所有方面都追求最高的计算效率。相反,它的设计优先考虑的是开发者的熟悉度和现有的开发者生态系统。这使得开发者能够快速上手,并利用已有的工具和资源进行开发。尽管EVM本身可能存在一些效率低下的地方,比如其256位寄存器带来的开销,但通过添加 coprocessor (如预编译合约),这些低效的部分可以得到弥补。
为了改进 EVM,可以考虑两种策略,一是增加更好的预编译合约或专用操作码,比如引入EVM-MAX和SIMD技术,以提高特定计算任务的执行效率;二是优化EVM的存储布局,例如通过引入 Verkle tree 结构,降低相邻存储槽位访问的成本。这些改进将有助于提升EVM的整体性能,使其更加高效和有更高的可扩展性。

安全计算和开放硬件
在现代计算硬件层面提升安全性面临的一个重大挑战是:芯片设计的过度复杂。这种复杂性使得隐藏后门变得容易,同时也增加了side channel vulnerabilities 的风险。
各方正在从多个角度努力推动硬件和计算环境变得更加开放和安全。这些努力旨在减少硬件设计的复杂性和专有性,从而提高安全性,减少隐藏后门和 side channel vulnerabilities 的风险。部分计算任务正在越来越多地在可信执行环境中完成。同时,开源硬件的进展,如RISC-V笔记本电脑的成功,标志着在提供更透明和可审查的硬件解决方案方面取得了重要进展。这些努力为构建更安全的计算环境带来了新的希望和可能性。

将RISC-V计算机构建在FPGA(现场可编程门阵列)上是一种更加偏向安全和定制化的设计思路,但这种方法通常会带来更高的性能开销。即使性能有所牺牲,也能通过「glue and coprocessor」架构来弥补这一损失。开放且安全的主芯片可以处理敏感的核心计算,而更为复杂和资源密集的计算任务则由专用的ASIC模块来完成。这种设计可以在保证系统整体安全性的前提下,仍然提供高效的计算能力,并减少对专有优化的依赖,同时抵抗 side channel vulnerabilities 的风险。
密码学
随着密码学技术的发展,尤其是在可编程密码学(如SNARKs和MPC)领域,我们已经看到了对某些特定高度结构化计算的超优化实现。在一些特定的计算环境下(如SNARKs中),已经实现了对高度结构化计算的超优化。例如,某些哈希函数的开销现在仅比直接运行计算高出数百倍。这种优化大大降低了运行这些复杂计算的成本。对于AI计算(主要是矩阵乘法),已经实现了极低的开销。这表明在处理AI任务时,尽管有些计算是通过复杂的密码学手段进行的,但其开销已经可以接受。像GKR这种协议,用于证明在并行计算环境中的低复杂度性,它可能会帮助进一步优化密码学计算。尽管在特定计算上实现了显著的优化,但在通用目的虚拟机中执行的计算,特别是在RISC-V解释器中执行时,仍然可能会有高达一万倍的开销。然而,由于最密集的计算部分可以通过高效的专用技术来单独处理,因此总体的开销仍然是可控的。

矩阵乘法专用 MPC 的简化图,这是 AI 模型推理中最大的组件
结论
当前的趋势是以一种合理的方式最大化计算效率,同时保持开发者的友好性。这种方式对所有人都有好处,因为它能够在提高效率的同时,确保开发者能够继续使用熟悉且方便的工具和环境。通过在客户端进行更高效的专门化处理(例如通过专用协处理器进行优化),用户能够在本地硬件上运行既敏感又性能要求高的计算任务(如零知识证明和大语言模型的推理)。此外,这种趋势还提供了一个重要的机会窗口,确保在追求效率的同时,不会忽视安全性、开放性和简洁性等其他重要价值。通过「glue and coprocessor」架构,系统的不同部分能够专注于各自的优化目标,确保整体的和谐与平衡。
密码学本身就是一种典型的「昂贵的结构化计算」,需要大量计算资源。这些计算任务非常适合通过当前的趋势(如专用coprocessor的使用)来加速。通过加速密码学计算,我们不仅能提高性能,还能在不牺牲安全性的前提下,增加系统的整体安全性。
随着计算越来越模块化,参与计算的门槛大幅降低。新兴和小型参与者不需要掌握整个复杂系统,只需专注于优化特定类型的计算任务(例如为特定计算设计一个ASIC),就有可能在行业中产生影响。在 ZK-proving 领域,小型团队可以专注于优化特定的证明算法,而不必掌握整个系统的复杂性。在 EVM 优化方面,模块化的趋势使得编写高效代码变得更容易。模块化的计算结构使得代码的审计和形式验证变得更简单。不同计算领域(如ZK证明、AI计算、EVM优化等)正在趋向于一些共同的模式。这种融合为跨领域的协作和学习提供了更多的空间。


