使用AVX指令禁用exp()优化?

时间:2011-05-01 23:30:03

标签: visual-c++ x86 exp avx

我正在使用AVX内在函数在VC ++中编写一个前馈网络。我在C#中通过PInvoke调用此代码。调用计算包含函数exp()的大循环的函数时,我的性能对于160M的循环大小是~1000ms。一旦我调用使用AVX内在函数的任何函数,然后使用exp(),我的性能就会下降到大约8000ms的相同操作。请注意,计算exp()的函数是标准C,并且使用AVX内在函数的调用在处理的数据方面可能完全不相关。某种旗帜在运行时会在某处绊倒。

换句话说,

A(); // 1000ms calculates 160M exp() 
B(); // completely unrelated but contains AVX
A(); // 8000ms

或者,奇怪的是,

C(); // contains 128 bit SSE SIMD expressions
A(); // 1000ms

我很遗憾这里有什么可能的机制,或者如何追求一个解决方案。我在英特尔2500K cpu \ Win 7. Express版本的VS.

感谢。

1 个答案:

答案 0 :(得分:10)

如果使用任何AVX256指令,则“AVX上部状态”变为“脏”,如果随后使用SSE指令(包括在xmm寄存器中执行的标量浮点),则会导致大的停顿。这在英特尔优化手册中有记录,您可以download for free(如果您正在进行此类工作,则必须阅读):

  

AVX指令总是修改YMM寄存器的高位,而SSE指令不修改高位。从硬件角度来看,YMM寄存器集合的高位可以被认为是三种状态之一:

     

•清洁:YMM的所有高位都为零。这是处理器从RESET启动时的状态。

     

•已修改并保存到XSAVE区域YMM寄存器的高位内容与XSAVE区域中的已保存数据匹配。这在XSAVE / XRSTOR执行后发生。

     

•已修改和未保存:执行一条AVX指令(256位或128位)会修改目标YMM的高位。

     

只要处理器状态为“已修改且未保存”,AVX / SSE转换惩罚就适用。使用VZEROUPPER将处理器状态移至“清理”并避免转换惩罚。

您的例程B( )会弄脏YMM状态,因此A( )中的SSE代码会停止。在VZEROUPPERB之间插入A指令以避免此问题。