我有以下代码(将the xorshift128+ code from Wikipedia修改为使用 vector 类型):

#include <immintrin.h>
#include <climits>

__v8si rand_si() {
    static auto s0 = __v4du{4, 8, 15, 16},
        s1 = __v4du{23, 34, 42, 69};
    auto x = s0, y = s1;
    s0 = y;
    x ^= x << 23;
    s1 = x ^ y ^ (x >> 17) ^ (y >> 26);
    return (__v8si)(s1 + y);
}

#include <iostream>
#include <iomanip>
void foo() {
    //Shuffle a bit. The result is much worse without this.
    rand_si(); rand_si(); rand_si(); rand_si();
    auto val = rand_si();

    for (auto it = reinterpret_cast<int*>(&val);
         it != reinterpret_cast<int*>(&val + 1);
         ++it)
        std::cout << std::hex << std::setfill('0') << std::setw(8) << *it << ' ';
    std::cout << '\n';
}

哪个输出
09e2a657 000b8020 1504cc3b 00110040 1360ff2b 00150078 2a9998b7 00228080

每隔一个很小的数字,并且没有一个前导位设置。另一方面,使用xorshift *代替:
__v8si rand_si() {
    static auto x = __v4du{4, 8, 15, 16};
    x ^= x >> 12;
    x ^= x << 25;
    x ^= x >> 27;
    return x * (__v4du)_mm256_set1_epi64x(0x2545F4914F6CDD1D);
}

我得到更好的输出
0889632e a938b990 1e8b2f79 832e26bd 11280868 2a22d676 275ca4b8 10954ef9

但是根据Wikipedia的说法,xorshift +是一种不错的PRNG,并且比xorshift *具有更好的伪随机性。那么,我的RNG代码中是否有错误,还是我使用错误?

最佳答案

我认为您不应该通过查看生成的8个数字来判断随机生成器。此外,生成器通常需要好的种子(您的种子可能被认为是不好的-您的种子几乎以所有零位开头。仅几次调用rand_si()不足以使这些位“散布”)。

因此,我建议您使用适当的种子(例如,一个简单的解决方案是多次调用rand_si())。
xorshift*由于最终的乘法看起来表现更好,因此由于种子不足,它不易发现不良行为。

提示:将代码生成的数字与原始实现进行比较。这样,您可以确保实现正确。

07-28 10:49