7

OpenCL スタイル ベクトル用の Clang の言語拡張に慣れるためのテスト プログラムを作成しています。コードを動作させることはできますが、コードの 1 つの側面をダウンさせるのに問題があります。私は、clang がスカラー配列からベクトルをうまくロードする方法を理解できないようです。

現時点では、次のようなことをしなければなりません:

byte16 va = (byte16){ argv[1][start], argv[1][start + 1], argv[1][start + 2], 
                      argv[1][start + 3], argv[1][start + 4], argv[1][start + 5], 
                      argv[1][start + 6], argv[1][start + 7], argv[1][start + 8],
                      argv[1][start + 9], argv[1][start + 10], argv[1][start + 11],
                      argv[1][start + 12], argv[1][start + 13], argv[1][start + 14],
                      argv[1][start + 15]};

私は理想的には次のようなものが欲しいです:

byte16 va = *(byte16 *)(&(argv[1][start]));

これは、ARM または x86 の適切な組み込み関数を使用して簡単に実行できます。しかし、そのコードはコンパイルしてもプログラムをクラッシュさせます。

4

1 に答える 1

5

x86 でクラッシュが発生する理由の 1 つは、アライメントの問題です。システムに問題を再現するためのclangはありませんが、GCCの例でそれを示すことができます.

次のようなことをすると:

/* Define a vector type of 16 characters.  */
typedef char __attribute__ ((vector_size (16))) byte16;

/* Global pointer.  */
char *  foo;

byte16 test ()
{
  return *(byte16 *)&foo[1];
}

ベクトル対応の x86 でコンパイルすると、次のようになります。

$  gcc -O3 -march=native -mtune=native   a.c

テスト用に次のアセンブリを取得します。

test:
    movq foo(%rip), %rax
    vmovdqa 1(%rax), %xmm0
    ret

移動は整列されていることに注意してください。これはもちろん間違っています。この関数をメインにインライン化すると、次のようになります。

int main ()
{
  foo = __builtin_malloc (22);
  byte16 x = *(byte16 *)&foo[1];
  return x[0];
}

あなたは大丈夫です、そしてあなたは調整されていない指示を受けます. これは一種のバグであり、新しいデータ構造の追加などを伴う手続き間の最適化が必要になるため、コンパイラにはあまり適切な修正がありません。

この問題の原因は、コンパイラがベクトル型が整列されていると想定しているため、整列されたベクトル型の配列を逆参照するときに、整列された移動を使用できることです。GCC の問題の回避策として、次のような位置合わせされていないベクトル型を定義できます。

typedef char __attribute__ ((vector_size (16),aligned (1))) unaligned_byte16;

そして、それを使用して、アライメントされていないメモリを逆参照します。

セットアップ内でこの問題が正確に発生しているかどうかはわかりませんが、コンパイラからのアセンブリ出力を調べて確認することをお勧めします。

于 2013-11-02T13:20:23.473 に答える