RyuJIT 没有充分利用 SIMD 内在函数
RyuJIT not making full use of SIMD intrinsics
我是 运行 一些使用 System.Numerics.Vector<T>
的 C# 代码,但据我所知,我没有充分利用 SIMD 内在函数。我正在使用 Visual Studio Community 2015 with Update 1,我的 clrjit.dll 是 v4.6.1063.1.
我 运行 在 Intel Core i5-3337U Processor 上,它实现了 AVX 指令集扩展。因此,我认为,我应该能够在 256 位寄存器上执行大多数 SIMD 指令。例如,反汇编应包含 vmovups
、vmovupd
、vaddups
等指令,而 Vector<float>.Count
应 return 8、Vector<double>.Count
应该是 4,等等...但这不是我所看到的。
相反,我的反汇编包含 movups
、movupd
、addups
等指令以及以下代码:
WriteLine($"{Vector<byte>.Count} bytes per operation");
WriteLine($"{Vector<float>.Count} floats per operation");
WriteLine($"{Vector<int>.Count} ints per operation");
WriteLine($"{Vector<double>.Count} doubles per operation");
产生:
16 bytes per operation
4 floats per operation
4 ints per operation
2 doubles per operation
我哪里错了?要查看所有项目设置等,该项目可用 here。
您的处理器有点过时,它的 micro-architecture 是 Ivy Bridge。 Sandy Bridge 的 "tock",一个功能在没有架构变化的情况下缩小。你的克星是 RyuJIT 中的这段代码,located in ee_il_dll.cpp,CILJit::getMaxIntrinsicSIMDVectorLength() 函数:
if (((cpuCompileFlags & CORJIT_FLG_PREJIT) == 0) &&
((cpuCompileFlags & CORJIT_FLG_FEATURE_SIMD) != 0) &&
((cpuCompileFlags & CORJIT_FLG_USE_AVX2) != 0))
{
static ConfigDWORD fEnableAVX;
if (fEnableAVX.val(CLRConfig::EXTERNAL_EnableAVX) != 0)
{
return 32;
}
}
注意 CORJIT_FLG_USE_AVX2 的用法。您的处理器尚不支持 AVX2,该扩展在 Haswell 中可用。 Ivy Bridge 之后的下一个 micro-architecture,一个 "tick"。非常好的处理器顺便说一句,像 这样的发现有一个主要的令人惊叹的因素。
除了去购物,你别无他法。为了获得灵感,您可以查看它在 .
中生成的代码类型
我是 运行 一些使用 System.Numerics.Vector<T>
的 C# 代码,但据我所知,我没有充分利用 SIMD 内在函数。我正在使用 Visual Studio Community 2015 with Update 1,我的 clrjit.dll 是 v4.6.1063.1.
我 运行 在 Intel Core i5-3337U Processor 上,它实现了 AVX 指令集扩展。因此,我认为,我应该能够在 256 位寄存器上执行大多数 SIMD 指令。例如,反汇编应包含 vmovups
、vmovupd
、vaddups
等指令,而 Vector<float>.Count
应 return 8、Vector<double>.Count
应该是 4,等等...但这不是我所看到的。
相反,我的反汇编包含 movups
、movupd
、addups
等指令以及以下代码:
WriteLine($"{Vector<byte>.Count} bytes per operation");
WriteLine($"{Vector<float>.Count} floats per operation");
WriteLine($"{Vector<int>.Count} ints per operation");
WriteLine($"{Vector<double>.Count} doubles per operation");
产生:
16 bytes per operation
4 floats per operation
4 ints per operation
2 doubles per operation
我哪里错了?要查看所有项目设置等,该项目可用 here。
您的处理器有点过时,它的 micro-architecture 是 Ivy Bridge。 Sandy Bridge 的 "tock",一个功能在没有架构变化的情况下缩小。你的克星是 RyuJIT 中的这段代码,located in ee_il_dll.cpp,CILJit::getMaxIntrinsicSIMDVectorLength() 函数:
if (((cpuCompileFlags & CORJIT_FLG_PREJIT) == 0) &&
((cpuCompileFlags & CORJIT_FLG_FEATURE_SIMD) != 0) &&
((cpuCompileFlags & CORJIT_FLG_USE_AVX2) != 0))
{
static ConfigDWORD fEnableAVX;
if (fEnableAVX.val(CLRConfig::EXTERNAL_EnableAVX) != 0)
{
return 32;
}
}
注意 CORJIT_FLG_USE_AVX2 的用法。您的处理器尚不支持 AVX2,该扩展在 Haswell 中可用。 Ivy Bridge 之后的下一个 micro-architecture,一个 "tick"。非常好的处理器顺便说一句,像
除了去购物,你别无他法。为了获得灵感,您可以查看它在