我正在查看CIL Spec。在附录中,它谈到了“不精确的错误”,这意味着用户可以指定空引用异常等的确切顺序可以放宽。附录讨论了 JITer 可以使用它来提高性能的各种方法。
一个引起我注意的特定小节:
F.5.2 向量化循环
向量化循环通常需要知道两件事:
循环迭代是独立的
循环迭代的次数是已知的。
在对可能出现故障的检查放宽的方法中,第 1 部分经常是错误的,因为出现故障的可能性会导致从每个循环迭代到后续循环迭代的控制依赖性。在宽松的方法中,可以忽略这些控制依赖性。在大多数情况下,宽松的方法通过允许将检查提升到循环之外来简化矢量化。然而,即使这种提升是不可能的,忽略故障隐含的交叉迭代依赖性对于“短向量”SIMD 硬件(如 IA-32 SSE 或 PowerPC Altivec)的向量化可能是至关重要的。
例如,考虑这个循环:
for (k = 0; k < n; k++) { x[k] = x[k] + y[k] * s[k].a; }
其中 s 是引用数组。即使在宽松的上下文中,对空引用的检查也不能脱离循环。但是轻松确实允许成功应用“展开和卡纸”。循环可以展开 4 倍以创建聚合迭代,并将检查提升到每个聚合迭代的顶部。
也就是说,如果 JITer 使用这些宽松的故障,则表明循环可以自动转向 SIMD 操作。规范建议您可以使用 System.Runtime.CompilerServices.CompilationRelaxations 枚举来设置这些宽松的故障。但在实际的 C# 中,枚举只有 NoStringInterning 选项,没有任何其他选项。我已经尝试将 System.Runtime.CompilerServices.CompilationRelaxationsAttribute 设置为从其他来源提取的一些 int 代码,但生成的 x86 程序集没有区别。
据我所知,微软官方 JIT 并没有实现这一点。而且我知道 Mono 有Mono.Simd命名空间,所以我猜它也没有实现这个。
所以我很好奇我是否缺少关于该附录(以及第 12.6.4 节“优化”,也谈到了这一点)的一些历史记录。如果两个主要供应商都没有真正实施它,为什么它在标准中?微软是否有计划在未来开展这项工作?