SSE組み込み関数を使用して、Intelx86Nehalemマイクロアーキテクチャ用にいくつかのコードを最適化しています。
私のプログラムの一部は4つの内積を計算し、各結果を配列の連続したチャンクの前の値に追加します。すなわち、
tmp0 = _mm_dp_ps(A_0m, B_0m, 0xF1);
tmp1 = _mm_dp_ps(A_1m, B_0m, 0xF2);
tmp2 = _mm_dp_ps(A_2m, B_0m, 0xF4);
tmp3 = _mm_dp_ps(A_3m, B_0m, 0xF8);
tmp0 = _mm_add_ps(tmp0, tmp1);
tmp0 = _mm_add_ps(tmp0, tmp2);
tmp0 = _mm_add_ps(tmp0, tmp3);
tmp0 = _mm_add_ps(tmp0, C_0n);
_mm_storeu_ps(C_2, tmp0);
各ドット積の結果を保持するために4つの一時xmmレジスタを使用してこれを実行していることに注意してください。各xmmレジスタでは、結果は他の一時的なxmmレジスタに対して一意の32ビットに配置され、最終結果は次のようになります。
tmp0=R0-ゼロ-ゼロ-ゼロ
tmp1=ゼロ-R1-ゼロ-ゼロ
tmp2=ゼロ-ゼロ-R2-ゼロ
tmp3=ゼロ-ゼロ-ゼロ-R3
次の手順でそれらを合計することにより、各tmp変数に含まれる値を1つのxmm変数に結合します。
tmp0 = _mm_add_ps(tmp0, tmp1);
tmp0 = _mm_add_ps(tmp0, tmp2);
tmp0 = _mm_add_ps(tmp0, tmp3);
最後に、ドット積の4つの結果すべてを含むレジスタを配列の連続部分に追加して、配列のインデックスがドット積によって増分されるようにします(C_0nは、更新される配列に現在ある4つの値です)。 ; C_2は、これら4つの値を指すアドレスです):
tmp0 = _mm_add_ps(tmp0, C_0n);
_mm_storeu_ps(C_2, tmp0);
ドット積の結果を取得して、それらを配列の連続するチャンクに追加するための、より回りくどく、より効率的な方法があるかどうかを知りたいです。このようにして、ゼロ以外の値が1つしかないレジスタ間で3つの加算を実行しています。これを回避するためのより効果的な方法があるはずです。
私はすべての助けに感謝します。ありがとうございました。