GCCのvector extensionsは、hardware specific intrinsics(または自動ベクトル化)に頼らずに、異なるハードウェアアーキテクチャ上のいくつかのSIMD命令にアクセスするうえで便利で便利な方法を提供します。GCCのベクトル拡張のデータを読み込む
実際の使用例では、単純な加算チェックサムを計算しています。明らかでない1つのことは、安全にデータをベクトルにロードする方法です。ベクトル型へのポインタをキャスト
typedef char v16qi __attribute__ ((vector_size(16)));
static uint8_t checksum(uint8_t *buf, size_t size)
{
assert(size%16 == 0);
uint8_t sum = 0;
vec16qi vec = {0};
for (size_t i=0; i<(size/16); i++)
{
// XXX: Yuck! Is there a better way?
vec += *((v16qi*) buf+i*16);
}
// Sum up the vector
sum = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5] + vec[6] + vec[7] + vec[8] + vec[9] + vec[10] + vec[11] + vec[12] + vec[13] + vec[14] + vec[15];
return sum;
}
が動作しているように見えますが、私は、SIMDハードウェアがベクトル型が正しく整列されることを想定した場合、これは恐ろしい方法で爆発する可能性が心配です。
私が考えた唯一の他の選択肢は、一時ベクトルを使用して明示的に(memcpyまたは要素ごとの割り当てによって)値をロードすることですが、この反作用のテストではほとんどの高速化がSIMD命令の使用を得ました。理想的には、これは汎用の__builtin_load()
のようなものだと思いますが、存在しないようです。
アライメントの問題を起こす可能性のあるベクターにデータをロードするより安全な方法は何ですか?
GCC x86_64での非整列メモリ上でこれを実行すると発生しますCPUがソートされていないメモリをSSEレジスタにロードしようとすると、SIGSEGV。 1つの合理的なオプションは、チェックサムアライメントされたメモリだけであるか、通常のループを使用して最初の16バイト境界までバイトを合計します。 – dcoles
現在のコードでは、データのロードはコンパイラが入力を知っていれば(実際は問題ありません)、実際にはうまくコンパイルされます:https://godbolt.org/g/DeR3Qv。 https:// godboltという入力を知らなくてもそれほど素晴らしいことではありません。org/g/LxEkhp – ZachB