メニエスの名のもとに

プログラミング関係を中心としたぐだぐだブログ

メルセンヌ・ツイスターの小ネタ:自動ベクトル化

なんとなく時間が半端に余ったので、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だったかも。バージョンとかいろいろ適当。