写过三年 Rust SIMD,每次想让它跑在 GPU 里都要重写一整套 CUDA 内核——今天 VectorWare 把这件事用同一套代码彻底原生化了

写过三年 Rust SIMD,每次想让它跑在 GPU 里都要重写一整套 CUDA 内核——今天 VectorWare 把这件事用同一套代码彻底原生化了。

背景:CPU SIMD 和 GPU 本来是两套代码

Rust 的 portable SIMD(core::simd)让开发者用 Simd<T, N> 这个泛型类型写一次向量化代码,编译器自动降落到 x86 的 AVX、ARM 的 NEON 等目标平台。这比手写架构级 intrinsics(_mm256_add_ps 之类)已经方便很多。

但问题是:这只是在 CPU 上跑。

GPU 上的并行模型叫 SIMT(Single Instruction, Multiple Thread),一个 warp 一次发一条指令、32 个 lane 各自独立执行。听起来和 SIMD 很像,但 GPU 的 warp 是”可以分叉”的lane,不是一个硬编码的向量宽度。所以传统上,你想让同一套 SIMD 代码也跑在 NVIDIA GPU 上,就得专门写一套 CUDA kernel 或者用 core::arch::nvptx 手动翻译——和 CPU 代码完全不是一回事。

这件事,2026 年 8 月 10 日被 VectorWare 彻底变了。

VectorWare 做了什么

VectorWare 是自称”第一个 GPU 原生软件公司”的团队,之前已经把 std::thread 映射到了 GPU warp 上——让 Rust 线程在 GPU 上以 warp 为单位调度,解决了线程级并行的问题。但单个 warp 内部的 lane 级并行,他们还没有利用。

这次他们意识到:GPU warp 就是一个 32 宽的向量单元。 SIMT 的 lane 地址模型和 SIMD 的元素映射是一回事。所以他们把 core::simd 直接降到了 GPU 的 warp 指令上。

具体效果:

// CPU 上这么写
let a: Simd<i16, 32> = Simd::splat(1);
let b: Simd<i16, 32> = Simd::splat(2);
let c = a + b;

// 在笔记本电脑上(x86-64):编译器生成 vpaddw 指令
// 在 NVIDIA GPU 上:同样代码生成 add.s16 PTX 指令
// 一个 warp,32 个 lane 同时执行,一条指令搞定

这就是关键——同一份源代码,无需修改,编译目标不同,降落到对应指令。

VectorWare 还用 Rust 的类型系统(generics + const generics + trait bounds)构造了一个 warp-lane IR,让很多无效的程序在编译期就被拦掉,而不是到 GPU 上才发现行为不对。他们还写了一个 reference interpreter,可以在 CPU 上做确定性模拟,方便 differential testing——先在 CPU 上验证正确性,再上 GPU 跑。

三个关键细节

1. 为什么 core::simd 而非 std::simd

Rust 的 portable SIMD 在 core::simd 而不是 std::simdcore 是不依赖运行时环境的最小标准库,这意味着 VectorWare 不需要为 GPU 重新实现一整套 std 基础设施,直接用已有的 core 支持就行。

2. 32 lane 宽度 vs CPU 向量宽度

这个方案在 Simd 宽度恰好等于 32 时效率最高。如果向量宽度小于 32(如 Simd<i16, 8>),有些 lane 会空闲浪费;如果宽度大于 32(如 Simd<f32, 64>),一条指令放不下,需要拆成多条。

3. 目前仅限 NVIDIA

当前实现针对 NVIDIA 硬件。但 VectorWare 的 IR 是架构无关的,AMD 的 wavefront(同样是 32 或 64 宽)和 Vulkan subgroup 有类似的 lane 级原语,未来扩展到 AMD 和 Vulkan 不需要改太多代码。

为什么这件事值得单独说

此前 VectorWare 已经把 std::threadasync 映射到了 GPU warp 上,再加这次 core::simd 的映射,Rust 在 GPU 上的并行层次就补全了:

  • 线程级:Rust 线程 = GPU warp(已完成)
  • lane 级core::simd = warp 内的向量操作(已完成)
  • async:Rust async = GPU 上的异步等待(已完成)

三层都到位,意味着同一个 Rust 程序里,写向量化计算的部分用 SIMD、跑并发的部分用 async、拆任务的部分用 thread——全部无需 rewrite,直接跨 CPU 和 GPU 执行

HN 上有人提到 stable Rust 通道还用的是 fearless_simd 等第三方库(portable_simd 仍需 nightly),也有人追问有没有和手写 GPU kernel 相比的基准数据(如基数排序)。VectorWare 承认了这些局限,并表示下一步会探索 auto-vectorization——让编译器自动把标量循环变成 SIMD 操作。

三步下一步

  • 现在就想试:装 Rust nightly + VectorWare 工具链,在本地 NVIDIA GPU 上跑 core::simd 示例,地址见 vectorware.com
  • 评估是否适合你的场景:优先判断 Simd 向量宽度是否接近 32——图像处理、数据流式运算等固定宽度场景收益最大;变长向量或复杂跨 lane 操作仍有性能落差
  • 保持关注 portable_simd 稳定化进展:一旦 core::simd 进入 stable Rust,门槛将大幅降低,VectorWare 的方案也会随之进入主流

这件事的本质是:Rust 正在成为第一个真正打通 CPU/GPU 两种并行模型的主流系统语言——不是靠两套代码,而是在同一种抽象下,编译器决定往哪降。

评论区

0 条评论

登录后可评论。

铁锈·Rust工具链 12 阅读