为啥内核中不使用 SIMD 指令?

Posted

技术标签:

【中文标题】为啥内核中不使用 SIMD 指令?【英文标题】:Why are SIMD instructions not used in kernel?为什么内核中不使用 SIMD 指令? 【发布时间】:2017-10-10 23:54:44 【问题描述】:

我在内核中找不到太多使用 SIMD 指令(如 SSE/AVX)的地方(除了一个用于加速 RAID6 奇偶校验计算的地方)。

Q1) 有什么具体原因,还是只是缺少用例?

Q2) 如果我想使用 SIMD 指令,比如设备驱动程序,今天需要做什么?

Q3) 将像 ISPC 这样的框架合并到内核中会有多难(仅用于实验)?

【问题讨论】:

【参考方案1】:

保存/恢复 FPU(包括 SIMD 向量寄存器)状态比仅整数 GP 寄存器状态更昂贵。在大多数情况下,这根本不值得。

在 Linux 内核代码中,您只需在代码周围调用 kernel_fpu_begin() / kernel_fpu_end()。这就是 RAID 驱动程序的作用。参见http://yarchive.net/comp/linux/kernel_fp.html


x86 没有任何面向未来的方法来保存/恢复一个或几个向量寄存器。 (除了使用旧版 SSE 指令手动保存/恢复 xmm 寄存器外,如果用户空间的任何 ymm/zmm 寄存器的上半部分脏,则可能导致 SSE/AVX transition stalls on Intel CPUs。

旧版 SSE 起作用的原因是,当英特尔想要引入 AVX 时,一些 Windows 驱动程序已经这样做了,因此他们发明了这种转换惩罚的东西,而不是让旧版 SSE 指令将 ymm 寄存器的高 128b 归零。 (有关该设计决策的更多详细信息,请参阅this。)因此,基本上我们可以将 SSE/AVX 转换惩罚混乱归咎于 Windows 仅二进制驱动程序。

关于非 x86 架构的 IDK,以及现有 SIMD 指令集是否有面向未来的方法来保存/恢复将继续适用于更长向量的寄存器。如果扩展继续使用多个 32 位 FP 寄存器作为单个更宽寄存器的模式,ARM32 可能会。 (例如,q2s8s11 组成。)因此,如果 256b NEON 扩展只允许您将 2 个 q 寄存器用作一个 256b,那么保存/恢复一对 q 寄存器应该是面向未来的登记。或者,如果新的更宽向量是独立的,并且不扩展现有寄存器。

【讨论】:

相关:memcpy moving 128 bit in linux。我的回答还提到 kernel_fpu_end() 实际上在 Linux 3.7 及更高版本中“急切”地恢复了 FPU 状态,因此不要围绕小块工作使用多个开始/结束调用。

以上是关于为啥内核中不使用 SIMD 指令?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 AngularJS 指令中不推荐使用 `replace` 属性? [复制]

指令级并行与 SIMD

DSP视频教程DSP视频教程第10期:DSP运算加速的精髓,含SIMD指令,饱和运算指令和浮点以及定点的MAC乘累加指令

如果我们有 GPGPU,为啥还要使用 SIMD? [关闭]

使用 SIMD 指令避免无效的内存加载

如何使用 SIMD 指令截断值