配了三年 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 方向各编译一次,看生成的指令差异。
评论区
登录后可评论。