__m128
の値で動作するコードがあります。私はこれらの値にx86-64 SSE組み込み関数を使用しています。値がメモリ内でアライメントされていないとクラッシュします。これは私のコンパイラ(この例ではclang)が整列したロード命令だけを生成するためです。コンパイラに__m128のアライメントされていないロードを生成させる方法
グローバルに、または特定の値(おそらく種類のアノテーションを含む)の代わりに、アライメントされていないロードを生成するようにコンパイラに指示できますか?
なぜなら、最初に値の境界が整列していないのは、メモリを節約しようとしているからです。私は、これらの構造体の配列を作成してい
#pragma pack(push, 4)
struct Foobar {
__m128 a;
__m128 b;
int c;
};
#pragma pack(pop)
次のように私は大体struct
を持っています。配列の2番目の要素は36バイトから始まり、16の倍数ではありません。
私は配列表現の構造に切り替えることができ、またはパッキングプラグマを削除することができます。 36バイトから48バイトの構造体)。しかし、私はまた、アライメントの合っていない負荷は、最近は高価ではないことを知って、それを最初に試してみたいと思います。
inline Vector4 add(const Vector4& a, const Vector4 &b) {
return Vector4(_mm_add_ps(a.data, b.data));
}
inline Vector4 subtract(const Vector4& a, const Vector4& b) {
return Vector4(_mm_sub_ps(a.data, b.data));
}
// etc..
:
struct Vector4 {
__m128 data;
Vector4(__m128 v) : data(v) {}
};
struct Foobar {
Vector4 a;
Vector4 b;
int c;
}
私は、その後のようないくつかのユーティリティ機能を持っている:
私の実際のコードはこれに近かった:
アップデートは以下のコメントのいくつかに答えるために
私はこれらのユーティリティを頻繁に組み合わせて使用します。フェイク例:「Z Bozon」さんを見ているときに私のコードは、効果的に変更答える
Foobar myArray[1000];
myArray[i+1].b = sub(add(myArray[i].a, myArray[i].b), myArray[i+1].a);
:
struct Vector4 {
float data[4];
};
inline Vector4 add(const Vector4& a, const Vector4 &b) {
Vector4 result;
_mm_storeu_ps(result.data, _mm_add_ps(_mm_loadu_ps(a.data), _mm_loadu_ps(b.data)));
return result;
}
私の懸念があることユーティリティ機能は、上記のように組み合わせて使用したとき、ということでした生成されたコードに冗長なロード/ストア命令がある可能性があります。それは問題ではないことが判明しました。私はコンパイラ(clang)をテストし、それらをすべて削除しました。私はZ Bozonの答えを受け入れます。
構造体に '__m128'を使用しないでください。例えば 'float a [4]'を使い、明示的に '_mm_loadu_ps'と' _mm_storeu_ps'を使ってロードとストアを行います。 –
OPは明示的な組み込み関数を使用するだけでなく、場合によっては自動ベクトル化のためにclangによって生成されたSIMDコードを取得するように聞こえますか? –
@PaulRの場合、OPはその情報を彼の質問に加えるべきです。 –