3

FANN Lib(Cで書かれたニューロンネットワーク)からSSE2にコードを移植しようとしました。しかし、SSE2のパフォーマンスは通常のコードよりも悪くなりました。私のSSE2実装の実行では、1回の実行に5.20分なしで5.50分かかります。

SSE2は通常の実行よりもどのように遅くなる可能性がありますか?それは?のせい_mm_set_psでしょうか?Apple LLVMコンパイラ(XCode 4)を使用してコードをコンパイルします(すべてのSSE拡張フラグがオンで、最適化レベルはです-Os)。

SSE2なしのコード

                neuron_sum +=
                fann_mult(weights[i], neurons[i].value) +
                fann_mult(weights[i + 1], neurons[i + 1].value) +
                fann_mult(weights[i + 2], neurons[i + 2].value) +
                fann_mult(weights[i + 3], neurons[i + 3].value);

SSE2コード

                __m128 a_line=_mm_loadu_ps(&weights[i]);
                __m128 b_line=_mm_set_ps(neurons[i+3].value,neurons[i+2].value,neurons[i+1].value,neurons[i].value);
                __m128 c_line=_mm_mul_ps(a_line, b_line);
                neuron_sum+=c_line[0]+c_line[1]+c_line[2]+c_line[3];
4

1 に答える 1

5

ここでスピードアップを確認するには、次のことを行う必要があります。

  • weights[i]16 バイトにアラインされていることを確認してから、_mm_load_ps代わりに使用します_mm_loadu_ps
  • neurons[]AoS ではなく SoA になるように再編成し (さらに 16 バイトで整列)、一度に 4 つの値をロードするために使用し_mm_load_psます。
  • 水平方向の合計をループの外に移動します (ループがありますよね?) - ベクトルに 4 つの部分合計を保持vneurom_sumし、ループの後でこのベクトルに対して最後の水平方向の合計を 1 つ実行します。

それでも、2 回のロードと 1 回のストアに対して 1 つの算術演算しか実行していないため、大幅なスピードアップは見られません。最近のほとんどの x86 CPU には 2 つのスカラー FPU があるため、128 ビット浮動小数点 SIMD の理論上の 4 倍のスピードアップにはおそらく近づかないでしょう。

于 2012-03-26T20:37:55.947 に答える