、 次のサンプルコードは、自動ベクトル化(assembly here)を-std=c99
、-O3
、及び-mavx2
を使用してGCC 5.2でコンパイル:GCCでストライドされた書き込みを自動ベクトル化する方法は?
#include <stdint.h>
void test(uint32_t *restrict a,
uint32_t *restrict b) {
uint32_t *a_aligned = __builtin_assume_aligned(a, 32);
uint32_t *b_aligned = __builtin_assume_aligned(b, 32);
for (int i = 0; i < (1L << 10); i += 2) {
a_aligned[i] = 42 * b_aligned[i];
a_aligned[i+1] = 3 * a_aligned[i+1];
}
}
しかし、以下のサンプルコードは、自動ベクトル化(assembly here)ない:
#include <stdint.h>
void test(uint32_t *restrict a,
uint32_t *restrict b) {
uint32_t *a_aligned = __builtin_assume_aligned(a, 32);
uint32_t *b_aligned = __builtin_assume_aligned(b, 32);
for (int i = 0; i < (1L << 10); i += 2) {
a_aligned[i] = 42 * b_aligned[i];
a_aligned[i+1] = a_aligned[i+1];
}
}
サンプル間の唯一の違いは、倍率がa_aligned[i+1]
になることです。
これは、GCC 4.8,4.9、および5.1の場合も同様です。 をa_aligned
の宣言に追加すると、自動ベクトル化は完全に禁止されます。最初のサンプルは一貫して2番目のサンプルよりも速く実行され、小さいタイプの場合はさらに高速化されました(たとえば、uint32_t
の代わりにuint8_t
)。
2番目のコードサンプルをGCCで自動ベクトル化する方法はありますか?
唯一の違いは倍率(3対何もない)ですか?スケーリング係数として1を明示的に追加してみてください。それが解決すれば、それはコンパイラのバグです。 – Jeff
また、文 'a_aligned [i + 1] = a_aligned [i + 1]'をコメントアウトするか、 'a_aligned [i + 1] * = 1'として書き直してみてください。コンパイラは、あなたが何を言っているかを正確に行う以外に、あなたのノーオペレーションの自己割り当てで何をすべきかを知らないかもしれません。 –
@ Jeff実際、唯一の違いは倍率です。明示的な1を追加しても、2番目のコードサンプルは自動ベクトル化されません([assembly here](https://goo.gl/dnjSaQ))。 –