私が何をしたいことは、このだと思う:
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
を行うと、それはレジスタの下位64ビット、上位への第二に最初の二重を置きます16ビット。したがって、上記の負荷の後で、x1
は、とi0[1]
の2つの値(x2
と同様)を保持します。 _mm_add_pd
を呼び出すと、x1
とx2
に対応する要素が垂直方向に追加されるため、加算後、sum
は、下位64ビットにi0[0] + i1[0]
、上位64ビットにi0[1] + i1[1]
を保持します。
編集:_mm_load_ps
の代わりに_mm_load_pd
を使用する利点はないことを指摘しておきます。関数名が示しているように、pd
のバラエティは2つのパックド・ダブルを明示的にロードし、ps
バージョンは4つのパックド単精度浮動小数点をロードします。これらは純粋にビット単位のメモリ移動であり、どちらもSSE浮動小数点ユニットを使用するため、_mm_load_ps
を使用してdouble
データにロードするとペナルティは発生しません。そして、_mm_load_ps
にはメリットがあります:その命令エンコーディングは_mm_load_pd
より1バイト短く、命令キャッシュの意味では効率的です(そして、命令デコードの可能性もありますが、現代の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レジスタの内容を浮動小数点の代わりにdoubleを保持するようにコンパイラに再解釈させるだけで、倍精度算術関数_mm_add_pd
に渡すことができます。
あなたは確かに '_mm_load_ps'を使用することができますが、シングルの間でドメイン・バイパス・ペナルティがあるような方法で設計された仮想的な将来のプロセッサ上のパフォーマンスの低下を危険にさらします倍精度浮動小数点演算をサポートしています。私はそのようなプロセッサーの計画がないことを知っていますが、それは今まで実装されていないと言っているわけではありません。そのため、個別のロード操作が行われます。確かに遠隔の可能性はありますが、なぜそれを危険にさらしますか? –
今後のプロセッサでパフォーマンスが低下する危険性があることに同意します。私は、アプリケーション特有の基準で「MOVPD」の代わりに「MOVPS」を使用することによって得られる性能上の利益を考慮する(すなわち測定する)ことを提案する。今日、それを使用する利点があり、そのためのペナルティを持っているような幻想的なアーキテクチャの兆候がない場合、私はそれをやります。このようなロードは、将来自動的に別の実装に切り替えるために簡単に抽象化することができます。 –