向量化

为了找到并行指令,跟踪器必须提供足够关于内存加载/存储操作的信息。它们必须在内存中相邻。对此的要求是它们使用相同的索引变量,并且偏移量可以表示为线性或仿射组合。

命令行标志

  • –jit vec=1:为标记的 jitdrivers 打开向量化(例如,NumPyPy 模块中的那些)。
  • –jit vec_all=1:为任何 jit 驱动程序打开向量化。请参阅跟踪过滤启发式的参数。

特性

如果跟踪包含并行操作,则当前可以向量化以下操作

  • float32/float64:加法、减法、乘法、除法、取反、绝对值
  • int8/int16/int32/int64 算术:加法、减法、乘法、取反、绝对值
  • int8/int16/int32/int64 逻辑:与、或、异或

归约

实现了归约

  • sum、prod、any、all

常量和变量扩展

打包的算术运算将标量变量或常量扩展到向量寄存器中。

保护增强

展开的保护在算术级别上得到增强(参见 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)