メルセンヌ・ツイスターの小ネタ:自動ベクトル化
なんとなく時間が半端に余ったので、1年位前に気づいたような気がするが、今はどうなっているか知らない小ネタをひとつ。
MersenneTwister をやや今風(あるいは俺流)に書くとこんな感じなんだけど
#define MATA UINT32_C(0x9908b0df) #if defined(NOT_USE_MAG_ARRAY) const uint32_t mata32 = MATA; #else const uint32_t mag[2] = {0, MATA}; #endif static inline uint32_t recursion32(uint32_t x, uint32_t y, uint32_t z) { x = (x & UPPER_MASK) | (y & LOWER_MASK); #if defined(NOT_USE_MAG_ARRAY) return z ^ (x >> 1) ^ static_cast<uint32_t>((-static_cast<int32_t>(x & 1)) & mata32); #else return z ^ (x >> 1) ^ mag[x & 1]; #endif } void fillState32(uint32_t * state) { int i = 0; for (; i + pos < size; i++) { state[i] = recursion32(state[i], state[i + 1], state[i + pos]); } for (; i < size - 1; i++) { state[i] = recursion32(state[i], state[i + 1], state[i + pos - size]); } state[size - 1] = recursion32(state[size - 1], state[0], state[pos - 1]); }
ヘッダーインクルードとか出力関数とかいろいろ省略してある。
これでNOT_USE_MAG_ARRAY を定義すると、配列参照ではなくて、ちょっとトリッキーなことをしてパラメータを入れるようになる。やってることは同じで、最下位ビットが1ならパラメータをXORする。
NOT_USE_MAG_ARRAYを定義して、clang++ で -O2 でコンパイルすると自動ベクトル化される。g++ では自動ベクトル化されなかった。-03だったかも。バージョンとかいろいろ適当。