1

SSE を使用してコードを高速化しようとしていますが、次のコードはうまく機能します。基本的に、__m128一度に 4 つの操作を実行するには、変数は連続して 4 つの float を指す必要があります。

このコードはfrom toで計算c[i]=a[i]+b[i]するのと同じです。i03

float *data1,*data2,*data3
// ... code ... allocating data1-2-3 which are very long.
__m128* a = (__m128*) (data1);
__m128* b = (__m128*) (data2);
__m128* c = (__m128*) (data3);
*c = _mm_add_ps(*a, *b);

しかし、使用するデータ (以下を参照) を少しシフトしたい場合、from toで計算c[i]=a[i+1]+b[i]するために、実行時にクラッシュします。i03

__m128* a = (__m128*) (data1+1); // <-- +1
__m128* b = (__m128*) (data2);
__m128* c = (__m128*) (data3);
*c = _mm_add_ps(*a, *b);

私の推測では、それ__m128は 128 ビットであり、floatデータが 32 ビットであるという事実に関連しているということです。したがって、128 ビットのポインターが 128 で割り切れないアドレスを指すことは不可能な場合があります。

とにかく、何が問題なのか、どうすればそれを回避できるのか知っていますか?

4

2 に答える 2

6

次のように、暗黙的にアラインされたロード/ストアを使用する代わりに:

__m128* a = (__m128*) (data1+1); // <-- +1
__m128* b = (__m128*) (data2);
__m128* c = (__m128*) (data3);
*c = _mm_add_ps(*a, *b);

必要に応じて、明示的なアライン/アラインなしロード/ストアを使用します。例:

__m128 va = _mm_loadu_ps(data1+1); // <-- +1 (NB: use unaligned load)
__m128 vb = _mm_load_ps(data2);
__m128 vc = _mm_add_ps(va, vb);
_mm_store_ps(data3, vc);

同じ量のコード (つまり、同じ数の命令) ですが、クラッシュすることはなく、どのロード/ストアが整列され、どのロード/ストアが整列されていないかを明示的に制御できます。

最近の CPU では、アライメントされていないロードに対するペナルティが比較的小さいことに注意してください。ただし、古い CPU では、2 倍以上のヒットが発生する可能性があります。

于 2013-10-15T10:02:57.417 に答える