この小さなコード例では:
__m128i twos = _mm_set_epi32(2,3,1,2);
__m128i foo = _mm_set_epi32(128,128,128,128);
__m128i shifted = _mm_srl_epi32(foo,twos);
「shifted」はゼロでいっぱいですが、2つはそれぞれ値32、16、64、および32の4つの32ビット整数でいっぱいになると思います。私は本質的に間違ったものを使用していますか?
この小さなコード例では:
__m128i twos = _mm_set_epi32(2,3,1,2);
__m128i foo = _mm_set_epi32(128,128,128,128);
__m128i shifted = _mm_srl_epi32(foo,twos);
「shifted」はゼロでいっぱいですが、2つはそれぞれ値32、16、64、および32の4つの32ビット整数でいっぱいになると思います。私は本質的に間違ったものを使用していますか?
はい、間違って使用しています。2番目の引数_mm_srl_epi32()
は、最初の引数をシフトするビット数を指定しますが、期待どおりにベクトル化された引数ではないため、各32ビット整数を異なるビット数だけシフトできます。代わりに、128ビット引数は64ビットに切り捨てられ、結果のカウントはシフトするビット数を決定するために使用されます。最初の引数の4つの整数すべてに同じシフト量が使用されます。あなたの場合、下位64ビットは0x0000000100000010
であり、これは非常に大きな正の数に評価されます。これにより、すべてfoo
のビットがシフトアウトされるため、すべての要素がゼロにフラッシュされます。
そこにあるすべての命令の細部をすべて見つけるのに適した場所は、IntelのAVXプログラマーズリファレンスです。タイトルは多少誤称かもしれませんが、このドキュメントには、すべてのSSE / SSE2 / ... / AVX / AVX2命令の説明と、IntelのC ++コンパイラで利用可能な組み込み関数の説明が含まれています(通常gcc
、その他でも利用できます)。ドキュメントで検索する_mm_srl_epi32
と、指示が何をするかについての明確な説明が得られます。