一段能在CPU上编译通过的Rust向量代码,原封不动扔到NVIDIA GPU上,结果和CPU上分毫不差。

做到这件事的是VectorWare。他们把Rust的core::simd——那套写一次就能编译到x86或Arm向量指令的“可移植SIMD”——映射到了GPU的warp上。同一份源码,CPU编译成向量指令,GPU编译成warp指令,不用改一行。

这件事值得注意的不是又一个“Rust能跑GPU”的炫技demo。真正的问题是:把GPU包装成一个普通的Rust后端,能不能让开发者不学CUDA也拿到硬件级并行?答案要过三道坎——core::simd还在nightly、向量宽度和硬件写死的warp宽度是否对得上、编译器能不能兜住所有边界情况。

发生了什么

core::simd本来只服务CPU:定义一个Simd<T, N>,写一次加法、比较、归约、shuffle,编译器按目标架构生成对应向量指令。

VectorWare的判断是:GPU的warp本身就是一个向量单元。NVIDIA一个warp正好32个硬件lane,Simd<f32, 32>刚好一个lane装一个元素,一条加法指令32个lane同时算。

具体映射方式:

  • 逐元素运算 → GPU原生指令
  • mask/select → 原生选择指令
  • 归约(reduce_sum) → warp shuffle指令跨lane汇总
  • any/all → vote/ballot指令
Rust SIMD 如何映射到 GPU warp Simd<f32, 32> Rust portable SIMD 类型,写一次,CPU/GPU 通用 一个 NVIDIA warp 32 个硬件 lane,天然是一个向量单元 逐元素运算 → 原生指令 mask / select → 原生选择 归约(reduce) → warp shuffle any / all → vote / ballot 每类 SIMD 操作都能对上一条硬件指令

Simd<T, N>在GPU上仍是普通的Rust值,借用检查、生命周期照常生效。这意味着已经用core::simd写好的CPU代码和库,理论上不用重写就能获得GPU的lane级并行。

直接受益的两类人:写高性能计算和SIMD库的Rust开发者,以及做GPU工具链、异构计算架构的团队。前者可以省一次移植,后者多了一个统一编程模型的候选方案。

代价在哪

core::simd本身没稳定,得开#![feature(portable_simd)]才能用,接口随时可能变。这一条足够让追求稳定性的团队先观望。

更硬的限制是宽度。CPU上Simd<T, N>的N可以是1到64任意值,GPU的warp宽度却是硬件写死的:

场景结果
N = 32(对齐NVIDIA warp)每lane一元素,一条指令算完,接近零成本
N < 32部分lane闲置,硬件资源浪费
N > 32一次操作拆成多条指令,并行收益打折
跨lane任意shuffle可能要绕道共享内存,代价上升
归约、any/all变成warp内同步点,限制调度器自由度
零成本只在宽度对齐时成立 N = 32(匹配warp) 1 : 1 每个lane装一个元素 一条指令全部算完 接近零成本 N ≠ 32(不匹配) N < 32 → 部分lane闲置 N > 32 → 拆成多条指令 跨lane shuffle可能要绕道共享内存 归约/any/all是warp内同步点

VectorWare的工程做法是把warp当成一台带固定原语和lane占用规则的小机器,用Rust的泛型、const泛型、trait约束给它编了一套IR——操作类型不对就编译不过,同时用CPU上的确定性解释器做差分测试。

这套思路扎实,但团队自己也承认:为了让抽象在遇到Rust其他特性时保持sound,他们改过编译器,这是“没人走过的路”,目前不确定覆盖了所有正确性边界。

目前这套方案只支持NVIDIA。AMD wavefront和Vulkan subgroup架构上有类似原语,但这还只是一句“说得通”,没有实现。

平台当前状态
NVIDIA warp(32 lane)demo已跑通,映射到原生指令
AMD wavefront(32/64)架构类似,尚无实现
Vulkan subgroup架构类似,尚无实现

能跑通,不等于能用

这次demo至少证明了一点:SIMT和SIMD在“一条指令驱动多个lane同时处理数据”这个层面高度重合,把Rust现成的向量类型往warp上铺,逻辑是通的。

但SIMT不是SIMD的完全复刻。线程发散、per-lane寻址、warp内同步——这些执行语义上的差异,VectorWare是用编译器和IR绕过去的,不是消失了。

从“能跑通一个demo”到“生态可用”,中间没有公开的性能数字,没有跟手写PTX或CUDA kernel的对比。向量宽度不整除32、shuffle模式复杂时,收益还剩多少,目前看不清。

历史上类似的尝试不少。SIMD.js当年想在浏览器里统一向量计算,写起来漂亮,规范最终没落地。这不是说VectorWare会重蹈覆辙,而是提醒一句:“写一套抽象让两种硬件通用”,历史上失败的次数远比成功多。CPU上的intrinsics活到今天,恰恰是因为它离硬件足够近,近到不需要一层抽象讨好谁。

现在能给的建议很具体。已经在用core::simd写CPU向量代码的团队,可以拉这个demo跑一跑,看看自己的代码能不能直接过,但别急着把生产路径切过去——nightly功能加编译器魔改,稳定性还没人背书。做GPU工具链或异构架构选型的团队,可以先记下这个方向,AMD和Vulkan没落地之前,没必要为NVIDIA单平台的方案单独投入资源。

接下来最该盯的不是又一个demo,而是三件事:core::simd能不能进稳定版、这套编译器改动能不能扛住真实负载的正确性检验、AMD和Vulkan的移植什么时候从“架构上说得通”变成能跑的代码。


锐评:demo证明了方向不假,但零成本只兑现给宽度刚好对齐warp的那一小撮场景,剩下的路还得靠编译器和时间去填。