.NET中的SIMD

在Mono六年之后,微软的CLR实现最终通过RyuJIT提供了对SIMD的支持。RyuJIT 目前仍处在社区预览阶段,它是下一代的.NET JIT编译器。

SIMD代表的是单指令流多数据流(Single Instruction,Multiple Data)。它是一组特殊的CPU 指令集,其中的指令可以对包含在大小为2、4、8或16的数组中的每个元素同时执行同一操作。在2008年Mono宣布对SIMD的支持时,我们曾报道过。

性能收益非常显著。执行Spring-Gravity算法,原生C++程序用了9.5秒。比较而言,将其逐行转换到Mono中,执行用了17.7秒。而再将其从标准操作符转换为SIMD函数,运行Mono的时间下降到1.7秒。

很明显这种特性可以应用于游戏物理引擎和科学研究中,还可以应用于在一系列股票和基金上执行同样计算的金融应用中。

在.NET中开启SIMD,不仅需要安装RyuJIT并使用正确的向量类型。微软的Kevin Frei列出了一些步骤:

  1. 下载并安装RyuJIT CTP3(同以前一样,需要x64 Windows 8.1或Window Server 2012R2)
  2. 设置“use RyuJIT”环境变量:set COMPLUS_AltJit=*
  3. 现在请注意,下面和以前有点区别了:
  4. 设置一个新的(而且是临时的)“enable SIMD stuff”环境变量:set COMPLUS_FeatureSIMD=1
  5. 把Microsoft.Bcl.Simd NuGet包添加到你的项目中(必须选择“include Prerelease”或使用–Pre选项)
  6. 在RyuJIT最终配置好之前还有一些必须处理的麻烦事:对于你编写的会使用新的Vector类型的方法,请将一个对Microsoft.Numerics.Vectors.Vector<T>的引用添加到会在该方法调用之前调用的某个类的构造器中。我建议就把它放在你的程序的入口类的类构造器中。它必须出现在类的构造器,而不是实例构造器中。
  7. 确保应用确实运行在x64上。如果没有看到你的进程中加载了protojit.dll(通过tasklist /M protojit.dll查看),那应该是遗漏了上面的某些东西。

应该注意的是,可用的SIMD不止一类。Kevin写道,

对那些想直接尝试这一特性的人而言,我们可以快速地看一个细节:在AVX代码应该会比SSE2更好的硬件上,我们打算(而且我们已经开发了原型)让Vector<T>自动使用AVX SIMD类型。然而要想正确处理,还需要对.NET运行时做些修改。因为这一限制(时间也不允许),CTP版本只能支持SSE2。

RyuJIT本身主要是为改进应用在64位机器上的启动时间而设计的。以前微软假定消费者使用的是x86,而x64仅被用于运行服务器的IT部门手中,所以启动时间并不是很严重的问题。这使他们可以选择面向x86的快速JIT编译器,面向x64的则是慢一些、但更高效的JIT编译器。快进了大约十年,情况已经发生了变化。

2013年9月的.NET框架博客上曾经介绍:

.NET代码生成团队一直在为一个新的下一代x64编译器而努力工作,该编译器代号为RyuJIT。这一新的JIT编译器是原来的两倍快,使用它编译的应用,启动时间最多可以减少30%(花在JIT编译器上的时间只是启动时间的一部分,所以应用启动时间并不会随着JIT性能加倍而减半)。此外,新的JIT编译器仍然会生成极好的代码,可以在服务器进程长期运行的过程中高效执行。

查看英文原文:SIMD Support in .NET

你可能感兴趣的:(.NET中的SIMD)