このコードは
float a = ...;
__m256 b = _mm_broadcast_ss(&a)
このコードよりも常に速い
float a = ...;
_mm_set1_ps(a)
?
ではなくa
として定義された場合はどうなりますか?static const float a = ...
float a = ...
このコードは
float a = ...;
__m256 b = _mm_broadcast_ss(&a)
このコードよりも常に速い
float a = ...;
_mm_set1_ps(a)
?
ではなくa
として定義された場合はどうなりますか?static const float a = ...
float a = ...
_mm_broadcast_ssには、 mmSSEAPIによって大部分が隠されているアーキテクチャによって課せられる弱点があります。最も重要な違いは次のとおりです。
これが意味するのは、ソースがメモリにない状況で_mm_broadcast_ssを明示的に使用すると、結果は_mm_set1_psを使用する場合よりも効率が低下する可能性が高いということです。この種の状況は通常、即値(定数)をロードするとき、または最近の計算の結果を使用するときに発生します。そのような状況では、結果はコンパイラーによってレジスターにマップされます。ブロードキャストに値を使用するには、コンパイラは値をメモリにダンプして戻す必要があります。または、代わりにpshufdを使用してレジスタから直接スプラットすることもできます。
_mm_set1_psは、特定の基礎となるCPU操作(命令)にマップされるのではなく、実装によって定義されます。つまり、スプラットを実行するためにいくつかのSSE命令の1つを使用する可能性があります。AVXサポートが有効になっているスマートコンパイラは、必要に応じて内部でvbroadcastssを確実に使用する必要がありますが、コンパイラオプティマイザのAVX実装状態によって異なります。
データの配列を反復処理するなど、メモリからロードしていると確信している場合は、ブロードキャストを直接使用することで問題ありません。ただし、疑問がある場合は、_mm_set1_psを使用することをお勧めします。
また、の特定のケースではstatic const float
、_mm_broadcast_ss()の使用を絶対に避けたいと思います。
AVX命令セットをターゲットにする場合、gccはVBROADCASTSSを使用して_mm_set1_ps組み込みを実装します。ただし、Clangは2つの命令(VMOVSS + VPSHUFD)を使用します。
mm_broadcast_ssは、mm_set1_psよりも高速である可能性があります。前者は単一の命令(VBROADCASTSS)に変換され、後者は複数の命令(おそらく、MOVSSの後にシャッフルが続く)を使用してエミュレートされます。ただし、mm_broadcast_ssにはAVX命令セットが必要ですが、mm_set1_psにはSSEのみが必要です。