配了三年 SIMD,每次换硬件都要重写——今天同一套 Rust 代码自己会认路:CPU 跑 x86-64,GPU 跑 warp 指令

配了三年 SIMD,每次换硬件都要重写——今天同一套 Rust 代码自己会认路:CPU 跑 x86-64,GPU 跑 warp 指令

2026 年 8 月 10 日,一家叫 VectorWare 的公司宣布了一个让 Rust 社区等了许久的消息:Rust 的 portable SIMD(core::simd)可以在 GPU 上跑了。

这意味着,过去你为 CPU SIMD 写的向量化代码,现在同一份源文件,往 GPU 上一编译,生成的就是 warp 指令。零改写,零适配。


SIMD 的问题是「换一台机器就要换一套代码」

SIMD(Single Instruction, Multiple Data)是什么?简单说就是一条指令同时处理多个数据。比如把两个数组对应元素相加,标量代码要循环一千次,SIMD 一条指令同时加 8 个 f32,循环次数直接除以 8。

在 Rust 里,传统写 SIMD 要用 core::arch 里的供应商内联函数:__m256_add_ps(x86)、vaddq_f32(Arm),每换一个架构就要重写一套。Rust 的 portable SIMD 解决了这个问题——它提供通用的 Simd<T, N> 类型,同样的算术、比较、归约代码写一次,编译器自动降级到目标硬件的向量指令。

但过去 GPU 是另一个世界。GPU 的并行单元叫 warp,一个 warp 同时跑 32 个 lane,执行同一条指令——这在结构上和 CPU SIMD 完全一致,但写 GPU SIMD 要用 CUDA、PTX 或供应商特定的 intrinsics,等于又来一套新代码。

VectorWare 意识到:GPU 不过是可以 target 的又一种向量硬件。


warp 就是 32 路的 SIMD

GPU 的执行模型叫 SIMT(Single Instruction, Multiple Thread),本质和 SIMD 一样——一条指令,多个数据并行处理。关键洞察是:warp 就是一个宽向量单元,lane 就是 SIMD lane,Simd 向量直接映射到 warp lane 上。

具体是怎么实现的:

元素操作 → 编译成原生 GPU 指令,比如 Simd<i16, 32> 做加法,直接对应单条 warp 指令 add.s16,每个 lane 同时加自己的元素,和 x86 的 vpaddw 一样一条指令搞定。

归约操作 → 使用 warp shuffle 指令,在 lane 之间交换数据,不需要共享内存。

掩码操作 → 用 vote/ballot 指令,让 lane 之间投票。

同一段 core::simd 代码:

let a: Simd<i16, 32> = Simd::splat(1);
let b: Simd<i16, 32> = Simd::splat(2);
let c = a + b; // 32 个 lane 同时加

在 CPU 上编译成 x86 的 vpaddw %zmm2, %zmm1, %zmm0,在 GPU 上编译成 add.s16 %rs3, %rs1, %rs2。源文件一个字不用改。

而且这不是运行时兜底——VectorWare 用 Rust 的类型系统编码了 warp 级别的 IR,lane 数量和操作形状都在类型里约束着,无效的程序根本编译不过,生成的是零开销的等价 GPU 指令。


还有几个限制

portable SIMD 仍不稳定,目前需要 Rust nightly,#![feature(portable_simd)] 才能用。

lane 宽度不匹配时会有浪费:warp 固定 32 lane,如果 Simd<f32, 8> 编译过去,32 个 lane 里只有 8 个在干活,其余 24 个空着。VectorWare 认为这是 Rust 类型系统的责任,在编译器层面编码约束,未来可能由编译器自动填补。

跨 lane 操作(比如任意 shuffle)有时需要多指令或共享内存,比不上手写的 warp 指令。VectorWare 的判断是:只要向量宽度和 warp 宽度匹配,这个抽象就有价值。

下一步:接 tensor core、自动向量化(把标量循环直接变成 SIMD)、支持 AMD wavefront 和 Vulkan subgroups。


这意味着什么

对 Rust 来说,这补全了完整的并行层次结构:

  • 线程/warp 层:Rust std::thread → GPU warp(VectorWare 此前已完成)
  • SIMD 层:core::simd → CPU SIMD lane / GPU warp lane(刚完成)
  • async 层:Rust async → GPU 异步并发(同样已完成)

三层全部打通,同一套 Rust 抽象贯穿 CPU 和 GPU。

对前端工程师来说,另一个趋势正在并行推进:Rust + WebAssembly SIMD 已经在浏览器里把性能差距拉开了。Rust WASM SIMD 跑向量操作 210ms,JavaScript(V8)跑同样的东西要 1420ms,6.7 倍的差距。WASM 2.0 的 256-bit SIMD 比 1.0 的 128-bit 吞吐翻倍,Rust 1.85 稳定支持 +simd128+relaxed-simd,加上 WebGPU 把 GPU 计算直接接进了浏览器。

这两条线在 2026 年的交汇处很清晰:高性能计算正在从服务器端迁移到浏览器端,Rust 的类型安全 + 向量化抽象 + WASM 的沙箱执行,正在把「前端写不了高性能代码」这个标签彻底撕掉。

下一步可以动手试:cargo +nightly build --target wasm32-unknown-unknown 配合 wasm-pack,然后在浏览器里用 wasm-bindgen 接 Rust 函数。在 Rust nightly 上开启 #![feature(portable_simd)],写一段 Simd<f32, 8> 的向量加法,往 CPU 和 GPU 方向各编译一次,看生成的指令差异。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 15 阅读