問題描述
我的 C++ 代碼使用 SSE,現在我想改進它以在可用時支持 AVX.所以我檢測 AVX 何時可用并調用一個使用 AVX 命令的函數.我使用 Win7 SP1 + VS2010 SP1 和一個帶 AVX 的 CPU.
My C++ code uses SSE and now I want to improve it to support AVX when it is available. So I detect when AVX is available and call a function that uses AVX commands. I use Win7 SP1 + VS2010 SP1 and a CPU with AVX.
要使用 AVX,必須包含這個:
To use AVX, it is necessary to include this:
#include "immintrin.h"
然后你可以使用內在的 AVX 函數,比如 _mm256_mul_ps
、_mm256_add_ps
等.問題是,默認情況下,VS2010 生成的代碼運行速度非常慢并顯示警告:
and then you can use intrinsics AVX functions like _mm256_mul_ps
, _mm256_add_ps
etc.
The problem is that by default, VS2010 produces code that works very slowly and shows the warning:
警告 C4752:發現英特爾(R) 高級矢量擴展;考慮使用/arch:AVX
warning C4752: found Intel(R) Advanced Vector Extensions; consider using /arch:AVX
似乎 VS2010 實際上不使用 AVX 指令,而是模擬它們.我在編譯器選項中添加了 /arch:AVX
并得到了不錯的結果.但是這個選項告訴編譯器在可能的情況下在任何地方使用 AVX 命令.所以我的代碼可能會在不支持 AVX 的 CPU 上崩潰!
It seems VS2010 actually does not use AVX instructions, but instead, emulates them. I added /arch:AVX
to the compiler options and got good results. But this option tells the compiler to use AVX commands everywhere when possible. So my code may crash on CPU that does not support AVX!
所以問題是如何讓 VS2010 編譯器生成 AVX 代碼,但只有當我直接指定 AVX 內在函數時.對于 SSE,它可以工作,我只使用 SSE 內在函數并生成 SSE 代碼,而無需任何編譯器選項,例如 /arch:SSE
.但是對于 AVX,由于某種原因它不起作用.
So the question is how to make VS2010 compiler to produce AVX code but only when I specify AVX intrinsics directly. For SSE it works, I just use SSE intrinsics functions and it produce SSE code without any compiler options like /arch:SSE
. But for AVX it does not work for some reason.
推薦答案
2021 更新:現代版本的 MSVC 不需要手動使用 _mm256_zeroupper()
即使在沒有 的情況下編譯 AVX 內部函數/arch:AVX
.VS2010 做到了.
2021 update: Modern versions of MSVC don't need manual use of _mm256_zeroupper()
even when compiling AVX intrinsics without /arch:AVX
. VS2010 did.
您所看到的行為是昂貴的狀態切換的結果.
The behavior that you are seeing is the result of expensive state-switching.
請參閱 Agner Fog 手冊的第 102 頁:
See page 102 of Agner Fog's manual:
http://www.agner.org/optimize/microarchitecture.pdf
每次您在 SSE 和 AVX 指令之間不正確地來回切換時,您都將付出極高的 (~70) 周期損失.
Every time you improperly switch back and forth between SSE and AVX instructions, you will pay an extremely high (~70) cycle penalty.
當你在沒有 /arch:AVX
的情況下編譯時,VS2010 將生成 SSE 指令,但在你有 AVX 內在函數的任何地方仍然會使用 AVX.因此,您將獲得同時具有 SSE 和 AVX 指令的代碼 - 這將具有那些狀態切換懲罰.(VS2010 知道這一點,所以它會發出您看到的警告.)
When you compile without /arch:AVX
, VS2010 will generate SSE instructions, but will still use AVX wherever you have AVX intrinsics. Therefore, you'll get code that has both SSE and AVX instructions - which will have those state-switching penalties. (VS2010 knows this, so it emits that warning you're seeing.)
因此,您應該全部使用 SSE,或全部使用 AVX.指定 /arch:AVX
告訴編譯器使用所有 AVX.
Therefore, you should use either all SSE, or all AVX. Specifying /arch:AVX
tells the compiler to use all AVX.
聽起來您正在嘗試創建多個代碼路徑:一個用于 SSE,另一個用于 AVX.為此,我建議您將 SSE 和 AVX 代碼分成兩個不同的編譯單元.(一個用 /arch:AVX
編譯,一個不用)然后將它們鏈接在一起,讓調度程序根據運行的硬件進行選擇.
It sounds like you're trying to make multiple code paths: one for SSE, and one for AVX.
For this, I suggest you separate your SSE and AVX code into two different compilation units. (one compiled with /arch:AVX
and one without) Then link them together and make a dispatcher to choose based on the what hardware it's running on.
如果您需要混合 SSE 和 AVX,請務必使用 _mm256_zeroupper()
或 _mm256_zeroall()
> 適當地避免狀態轉換懲罰.
If you need to mix SSE and AVX, be sure to use _mm256_zeroupper()
or _mm256_zeroall()
appropriately to avoid the state-switching penalties.
這篇關于使用 AVX CPU 指令:沒有“/arch:AVX"的性能不佳的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!