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

发布于 2024-11-04 03:35:51 字数 573 浏览 2 评论 0原文

我正在使用 AVX 内在函数在 VC++ 中编写前馈网络。我通过 C# 中的 PInvoke 调用此代码。当调用计算大循环(包括函数 exp())的函数时,对于 160M 的循环大小,我的性能约为 1000 毫秒。一旦我调用任何使用 AVX 内在函数的函数,然后使用 exp(),对于相同的操作,我的性能就会下降到约 8000 毫秒。请注意,计算 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

我不知道这里可能发生什么机制,或者如何寻求解决方案。我使用的是 Intel 2500K cpu\Win 7. Express 版本的 VS。

谢谢。

I am writing a feed forward net in VC++ using AVX intrinsics. I am invoking this code via PInvoke in C#. My performance when calling a function that calculates a large loop including the function exp() is ~1000ms for a loopsize of 160M. As soon as I call any function that uses AVX intrinsics, and then subsequently use exp(), my performance drops to about ~8000ms for the same operation. Note that the function calculating the exp() is standard C, and the call that uses the AVX intrinsics can be completely unrelated in terms of data being processed. Some kind of flag is getting tripped somewhere at runtime.

In other words,

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

or, curiously,

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

I am lost as to what possible mechanism is going on here, or how to pursue a sol'n. I'm on an Intel 2500K cpu\Win 7. Express versions of VS.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜访吸血鬼 2024-11-11 03:35:51

如果您使用任何 AVX256 指令,“AVX 高位状态”将变为“脏”,如果您随后使用 SSE 指令(包括在 xmm 寄存器中执行的标量浮点),这会导致严重停顿。这在英特尔优化手册中有记录,您可以免费下载(如果你正在做这种工作):

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

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

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

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

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

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

If you use any AVX256 instruction, the "AVX upper state" becomes "dirty", which results in a large stall if you subsequently use SSE instructions (including scalar floating-point performed in the xmm registers). This is documented in the Intel Optimization Manual, which you can download for free (and is a must-read if you're doing this sort of work):

AVX instruction always modifies the upper bits of YMM registers and SSE instructions do not modify the upper bits. From a hardware perspective, the upper bits of the YMM register collection can be considered to be in one of three states:

• Clean: All upper bits of YMM are zero. This is the state when processor starts from RESET.

• Modified and saved to XSAVE region The content of the upper bits of YMM registers matches saved data in XSAVE region. This happens when after XSAVE/XRSTOR executes.

• Modified and Unsaved: The execution of one AVX instruction (either 256-bit or 128-bit) modifies the upper bits of the destination YMM.

The AVX/SSE transition penalty applies whenever the processor states is “Modified and Unsaved“. Using VZEROUPPER move the processor states to “Clean“ and avoid the transition penalty.

Your routine B( ) dirties the YMM state, so the SSE code in A( ) stalls. Insert a VZEROUPPER instruction between B and A to avoid the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文