あなたが望むのはこれだと思います:
double i0[2];
double i1[2];
__m128d x1 = _mm_load_pd(i0);
__m128d x2 = _mm_load_pd(i1);
__m128d sum = _mm_add_pd(x1, x2);
// do whatever you want to with "sum" now
を実行する_mm_load_pd
と、最初の double がレジスタの下位 64 ビットに配置され、2 番目の double が上位 64 ビットに配置されます。したがって、上記のロードの後、 はと(および も同様) の 2 つの値をx1
保持します。への呼び出しは、およびの対応する要素を垂直方向に追加するため、追加後、下位 64 ビットと上位 64 ビットが保持されます。double
i0[0]
i0[1]
x2
_mm_add_pd
x1
x2
sum
i0[0] + i1[0]
i0[1] + i1[1]
編集:_mm_load_pd
の代わりに使用する利点がないことを指摘する必要があり_mm_load_ps
ます。関数名が示すように、このバージョンpd
は 2 つのパックド double を明示的にロードし、ps
バージョンは 4 つのパックド単精度浮動小数点数をロードします。これらは純粋にビット単位のメモリ移動であり、どちらも SSE 浮動小数点ユニットを使用するため、データ_mm_load_ps
のロードに使用してもペナルティはありません。double
また、 には利点があり_mm_load_ps
ます。その命令エンコーディングは よりも 1 バイト短い_mm_load_pd
ため、命令キャッシュの意味からより効率的です (また、命令のデコードも可能です。私は最新の x86 プロセッサのすべての複雑さの専門家ではありません)。上記のコードを使用_mm_load_ps
すると、次のようになります。
double i0[2];
double i1[2];
__m128d x1 = (__m128d) _mm_load_ps((float *) i0);
__m128d x2 = (__m128d) _mm_load_ps((float *) i1);
__m128d sum = _mm_add_pd(x1, x2);
// do whatever you want to with "sum" now
キャストによって暗示される機能はありません。コンパイラが SSE レジスタの内容を float ではなく double を保持するものとして再解釈し、倍精度算術関数に渡すことができるようにするだけ_mm_add_pd
です。