为什么每个开发者都应该掌握 SIMD
Everyone Should Know SIMD
很多人认为 SIMD 过于复杂,只适合顶尖的性能优化场景,但事实并非如此。SIMD 的核心逻辑其实非常直观:将原本逐个处理数据的循环,改为一次处理多个数据块。文章以 Zig 语言为例,拆解了 SIMD 代码通用的五个步骤,从广播常量到处理剩余数据,展示了如何轻松实现数倍的性能提升。在 Ghostty 项目中,简单的 SIMD 优化就带来了 4 到 16 倍的吞吐量增长。掌握这些基础概念,你也能在日常编程中显著加速代码运行,无需成为汇编专家。
一旦你掌握了基础知识,编写 SIMD 代码就和写普通的 for 循环一样简单。
HN 评论区
229- teo_zero
好文章!
不过我不建议一上来就用这么绝对的论断,比如:
> SIMD 很容易理解
以及
> 编写 SIMD 代码和写 for 循环一样简单
然后第一个例子却要用 12 行代码来替换一行标量代码。
还是诚实一点,承认 SIMD 很难,但结果值得付出吧!
(再挑个小刺:如果这篇文章是给新手看的,那在解释清楚之前,别用那些只有懂 SIMD 的人才懂的术语和概念。第 5 步做得很好:提到了并解释了标量尾部(scalar tails)。第 1 步就很糟糕:没人应该知道 broadcast 是什么意思。)
- kiaansaraiya
我稍微改一下标题,改成“每个人都应该知道 SIMD 何时不会发生”。现代编译器在向量化方面极其出色,直到它们突然失灵,而且它们经常会因为假设问题或单一数据依赖分支而回退到标量代码。学会检查编译器的优化报告,其价值可能更高。
- jwgarber
过去几天我一直在用 AVX-512 优化生物信息学项目中的矩阵运算,效果很棒!大多数应用的瓶颈是从内存读取大数据集,所以与其多次读取以计算多个操作,不如用 AVX 寄存器在一次遍历(融合内核)中完成所有操作。5 倍的加速非常常见。我一直是在用手动 intrinsics 实现,但 wide crate 也让常见操作变得极其简单。强烈推荐大家去试试。
- derf_
为了加强这个论点,即使你不打算自己写 SIMD,或者打算“让 AI 代劳”,了解 SIMD 能加速什么(以及在什么硬件上)依然很重要。这能让你在设计算法和构建代码结构时,确保 SIMD 是可行的。
当你亲自尝试过使用 SIMD 至少一段时间后,内化诸如“数据依赖为何重要”、“增加向量元素宽度的代价有多大(以及如何避免这种需求)”、“如何将条件和分支转换为掩码”,或者仅仅是像“除法不存在”这类概念,就会变得容易得多。
- hnal943
这里有一个很有帮助的视频,讲述了 Casey Muratori 开发的《The Witness》游戏开发团队如何利用 SIMD 解决具体的性能问题:https://www.youtube.com/watch?v=Ge3aKEmZcqY
- MomsAVoxell
我去年通过编写音频合成器开始学习多平台(x86 + ARM)SIMD:
https://github.com/seclorum/SIMDSynth
这是一次非常有回报的经历,合成器的架构——多音色复音——为应用 SIMD 原则提供了绝佳的数据流,即多个数据流经过相同的处理过程。
不过调试起来相当困难。我一度希望能有某种模拟器来帮助我理解每个管道中的状态。我想下次再深入这方面时,应该花点时间研究一下 SIMD 工具——但我担心这需要投入更多精力。如果有任何建议,我洗耳恭听。。
- Rendello
我喜欢 SIMD,但在用 SIMD 之类的手段对代码进行超级优化之前,真的要好好考虑你的数据结构和访问模式。
我一直都在吹捧数据导向设计(Data-Oriented Design),所以我在这里汇总一下我所有的评论 [1],但我认为这是一种很好的优化方法。我曾在旧代码(Zig 写的)里玩过 SIMD,但我对数据结构的建模方式与优化背道而驰,这就像给一辆引擎坏了的柠檬车装上了高性能赛车轮胎。
这是那种“万恶之源”式的过早优化,因为我没有测量性能,也没有考虑内存分配在哪里等等。现在,我尝试像 SQL 表一样建模我的数据,看看潜在的“主键”可能是什么,并围绕我的访问模式构建数据结构。
例如,我过去把树建模为指向堆上其他结构体的结构体:
struct Tree {
tag: TreeTag,
children: Vec<&Tree>
}
现在的树具备了链表的所有糟糕特性(* n 个节点 * m 个子节点),具有多个堆向量的所有碎片化问题(* n 个节点),以及糟糕的搭建/销毁时间(在这种情况下,仅 Drop 就占用了相当大一部分运行时间)。
但树可以用一百万种方式表示,并且总是可以线性化。所以现在我真的会考虑树的访问/插入模式,它到底是一棵树还是某种其他类型的图,我能否将其存储在 Vec 或 Vec 的结构体中,等等。自从真正审视了 t […]
- lifthrasiir
我认为更好的建议是,每个人都应该了解数组编程(array programming),因为你通常需要这种思维方式来进行 SIMD 优化,因为(打包的)SIMD 特定技术其实出奇地少。而且,即使没有 SIMD,数组编程也能让你写出通常性能不错的代码,因为它更容易被自动向量化。