単純なバイナリ引き算のためのSSEによる理論上の最大スピードアップとは何ですか?
-
13-09-2019 - |
質問
私のコードの内部ループは、ハードウェア設計の障壁または私の部分のバリア上の理解の欠如に当たっているかどうかを把握しようとは。そこもう少しそれにだが、次のように私は答えることを考え出すことができる最も簡単な質問があります:
私は、次のコードをお持ちの場合:
float px[32768],py[32768],pz[32768];
float xref, yref, zref, deltax, deltay, deltaz;
initialize_with_random(px);
initialize_with_random(py);
initialize_with_random(pz);
for(i=0;i<32768-1;i++) {
xref=px[i];
yref=py[i];
zref=pz[i];
for(j=0;j<32768-1;j++ {
deltx=xref-px[j];
delty=yref-py[j];
deltz=zref-pz[j];
} }
理論上の最大速度がアップし、どのようなタイプの私は、私は完全なコードを制御(アセンブリ、組み込み関数、何でも)が、建築以外のランタイム環境を制御すること持っている状況でSSE命令に行くことによって見ることができるであろう(すなわち、それはですマルチユーザー環境ので、私は、OSのカーネルが私の特定のプロセスに時間を割り当てる方法について何もすることはできません)。
私はSSEを使用して考えていた時に今、私は私の3倍のスピードアップよりもはるかに多くのベクトルの深さを与えるだろう、私のコードで3回のスピードアップを見ている(示され、おそらく3倍のスピードアップが私に語った私が持っています4倍の理論上の最大スループット)。私はインテルのCコンパイラを使用しています(私は、このようなdeltx / delty / deltzコンパイラた場合の配列とするとようなものは、それらを自動宣伝十分にスマートではなかったが、私はまだ唯一の3倍のスピードアップを参照してください。試してみました)ベクトル化のための適切なコンパイラフラグが、明らかに無組み込みます。
解決
これは、CPUに依存します。しかし、理論上の最大値は4倍を超える取得することはできません。私はそれがのほとんどではサイクルごとに4つの値を計算することができることを意味し、クロックサイクルごとに複数のSSE命令を実行できるCPUを知りません。
この場合、あなたは4倍の高速化の理論上の最大値を参照してくださいねので、ほとんどのCPUのは、サイクルごとにの少なくともの1つの浮動小数点スカラ命令を行うことができます。
しかし、もしあなたが実行しているCPUのための特定の命令スループットをルックアップする必要があります。
3倍の実用的な速度向上はもかなり良いです。
他のヒント
私は、あなたはおそらく何らかの形で内側のループをインターリーブする必要があるだろうと思います。 3成分ベクトルを一度に行うなっているが、それは一度のみ3の操作です。 4に取得するには、その後、2と2、というように、3つの最初のベクトルから構成し、次から1にしてください。あなたがロードするキューのいくつかの種類を確立し、一度にデータを4つの要素を処理した場合は、うまくいくかもしれないこと、後にそれを分離します。
編集:あなたは、(配列のサイズは常に4の倍数であると仮定した場合)、反復ごとに4つのベクトルを行うための内部ループをアンロールことができます。それは私が上記の言ったことを実現するでしょう。
考えてみましょう:フロートがどのように広いのですか? SSEx命令がどのように広いのですか?比率はあなたの合理的な上限のいくつかの種類を与える必要がありますする必要があります。
これは、アウトオブオーダーのパイプがスピードアップの良い推定値を得ることでハボックを果たしていることが注目に値します。
あなたはループタイリングを検討すべきである - あなたは内側のループ内の値にアクセスしている方法ですおそらく、L1データキャッシュにスラッシングの多くの原因となります。すべてはおそらくまだ384キロバイトのL2に収まるが、そこにL1キャッシュヒットとL2キャッシュヒット間の大きさの差のために容易であるので、これはあなたのための大きな違いを生む可能性があるため、それは、あまりにも悪くはない。