web-dev-qa-db-ja.com

AVX CPU命令の使用:「/ Arch:AVX」なしのパフォーマンスの低下

私のC++コードはSSEを使用していますが、AVXが使用可能になったときにサポートするように改善したいと考えています。 VS2010 SP1およびAVXを搭載したCPU。

AVXを使用するには、これを含める必要があります。

#include "immintrin.h"

その後、_mm256_mul_ps_mm256_add_psなどの組み込みAVX関数を使用できます。問題は、デフォルトでは、VS2010が非常にゆっくり動作し、警告を表示するコードを生成することです。

警告C4752:Intel(R)Advanced Vector Extensionsが見つかりました。/Arch:AVXの使用を検討してください

VS2010は実際にはAVX命令を使用しないようですが、代わりにそれらをエミュレートします。 /Arch:AVXをコンパイラオプションに追加し、良い結果を得ました。ただし、このオプションは、可能な場合はどこでもAVXコマンドを使用するようコンパイラーに指示します。したがって、AVXをサポートしていないCPUでコードがクラッシュする可能性があります!

ですから、AVXコンパイラを作成してAVXコードを生成する方法ですが、AVX組み込み関数を直接指定する場合にのみ問題になります。 SSEそれが機能するために、私はSSE組み込み関数を使用し、/Arch:SSEのようなコンパイラオプションなしでSSEコードを生成します。しかし、AVXでは何らかの理由で機能しません。

49
Mike

表示されている動作は、高価な状態切り替えの結果です。

Agner Fogのマニュアルの102ページを参照してください。

http://www.agner.org/optimize/microarchitecture.pdf

SSE命令とAVX命令を不適切に切り替えるたびに、非常に高い(〜70)サイクルペナルティが発生します。

_/Arch:AVX_なしでコンパイルすると、VS2010はSSE命令を生成しますが、AVX組み込み関数がある場合は常にAVXを使用します。したがって、SSE命令とAVX命令の両方を含むコードを取得します。これらの状態切り替えペナルティが発生します。 (VS2010はこれを認識しているため、表示されている警告を発します。)

したがって、すべてSSEまたはAVXを使用する必要があります。 _/Arch:AVX_を指定すると、すべてのAVXを使用するようコンパイラーに指示します。

複数のコードパスを作成しようとしているようです。1つはSSE用、もう1つはAVX用です。このため、SSEとAVXコードを2つの異なるコンパイル単位に分けることをお勧めします。 (1つは_/Arch:AVX_でコンパイルされ、もう1つはコンパイルされません)次に、それらをリンクし、実行しているハードウェアに基づいて選択するディスパッチャーを作成します。

needSSEとAVXを混在させる場合は、必ず_mm256_zeroupper()を使用してくださいまたは_mm256_zeroall()適切に状態切り替えペナルティを回避します。

81
Mysticial