向量化¶
为了找到并行指令,跟踪器必须提供足够关于内存加载/存储操作的信息。它们必须在内存中相邻。对此的要求是它们使用相同的索引变量,并且偏移量可以表示为线性或仿射组合。
命令行标志
- –jit vec=1:为标记的 jitdrivers 打开向量化(例如,NumPyPy 模块中的那些)。
- –jit vec_all=1:为任何 jit 驱动程序打开向量化。请参阅跟踪过滤启发式的参数。
特性¶
如果跟踪包含并行操作,则当前可以向量化以下操作
- float32/float64:加法、减法、乘法、除法、取反、绝对值
- int8/int16/int32/int64 算术:加法、减法、乘法、取反、绝对值
- int8/int16/int32/int64 逻辑:与、或、异或
常量和变量扩展¶
打包的算术运算将标量变量或常量扩展到向量寄存器中。
保护增强¶
展开的保护在算术级别上得到增强(参见 GuardStrengthenOpt)。生成的向量跟踪将只有一个检查索引的保护。
由于合并的加载/存储指令而冗余的索引变量上的计算不会被删除。后端在组装跟踪时会删除这些指令。
此外,一个简单的启发式方法(由 –jit vec_all=1 启用)尝试删除应用程序级循环的数组边界检查。它尝试识别数组边界检查并在循环顶部添加一个传递性保护。
label(...)
...
guard(i < n) # index guard
...
guard(i < len(a))
a = load(..., i, ...)
...
jump(...)
# becomes
guard(n < len(a))
label(...)
guard(i < n) # index guard
...
a = load(..., i, ...)
...
jump(...)
未来工作和限制¶
- 当前唯一支持的 SIMD 指令架构是 SSE4.1
- int8、int64 的打包乘法(参见 PMUL)。可以使用 PCLMULQDQ。仅受某些 CPU 支持,必须在 cpuid 中进行检查。
- 将类型从 int(8|16|32|64) 转换为 int(8|16) 的循环在当前的 SSE4.1 汇编器实现中不受支持。所需的操作码跨越多个指令。在性能方面,使用 SIMD 指令进行这些转换可能只有很少或没有优势。
- 对于检查向量整数寄存器上的 true/false 的保护,拥有 2 个 xmm 寄存器(一个填充零位,另一个每个位都填充 1)会很方便。这减少了 2 条保护检查指令,但代价是更高的寄存器压力。
- prod、sum 仅受 64 位数据类型支持
- 同构函数阻止以下情况组合成对:1) getarrayitem_gc、getarrayitem_gc_pure 2) int_add(v,1)、int_sub(v,-1)