Random CUDA中的随机数发生器

Random CUDA中的随机数发生器,random,cuda,prng,Random,Cuda,Prng,我一整天都在努力解决这个问题,我试图在CUDA代码中为线程创建一个随机数生成器。我浏览了所有的论坛,是的,这个话题提到了很多,但我花了几个小时试图解开各种各样的代码,但都没有用。如果有人知道一个简单的方法,可能是一个设备内核,它可以被调用以返回0到1之间的随机浮点,或者一个我可以转换的整数,我将非常感激 同样,我希望在内核中使用随机数,就像rand()一样 提前谢谢我不太明白你为什么需要什么特别的东西。任何传统的PRNG都应该或多或少地直接移植。A应该很好用。您是否有一些要建立的特殊属性?有一个

我一整天都在努力解决这个问题,我试图在CUDA代码中为线程创建一个随机数生成器。我浏览了所有的论坛,是的,这个话题提到了很多,但我花了几个小时试图解开各种各样的代码,但都没有用。如果有人知道一个简单的方法,可能是一个设备内核,它可以被调用以返回0到1之间的随机浮点,或者一个我可以转换的整数,我将非常感激

同样,我希望在内核中使用随机数,就像rand()一样


提前谢谢

我不太明白你为什么需要什么特别的东西。任何传统的PRNG都应该或多或少地直接移植。A应该很好用。您是否有一些要建立的特殊属性?

有一个MDGPU包(GPL),其中包含用于CUDA的GNU rand48()函数的实现


我发现它(很容易,使用谷歌,我假设你尝试:)-在英伟达论坛。< /P> < P>我还没有找到一个好的CUDA并行数生成器,然而,我在这里找到了一个基于学术研究的并行随机数生成器:

根据您的应用程序,您应该注意使用LCG,而不考虑流(每个线程一个流)是否会重叠。您可以使用LCG实现一个蛙跳,但是您需要有足够长的LCG周期,以确保序列不会重复

例如,蛙跳可以是:

template <typename ValueType>
__device__ void leapfrog(unsigned long &a, unsigned long &c, int leap)
{
    unsigned long an = a;
    for (int i = 1 ; i < leap ; i++)
        an *= a;
    c = c * ((an - 1) / (a - 1));
    a = an;
}

template <typename ValueType>
__device__ ValueType quickrand(unsigned long &seed, const unsigned long a, const unsigned long c)
{
    seed = seed * a;
    return seed;
}

template <typename ValueType>
__global__ void mykernel(
    unsigned long *d_seeds)
{
    // RNG parameters
    unsigned long a = 1664525L;
    unsigned long c = 1013904223L;
    unsigned long ainit = a;
    unsigned long cinit = c;
    unsigned long seed;

    // Generate local seed
    seed = d_seeds[bid];
    leapfrog<ValueType>(ainit, cinit, tid);
    quickrand<ValueType>(seed, ainit, cinit);
    leapfrog<ValueType>(a, c, blockDim.x);

    ...
}
模板
__设备无效跳转(无符号长&a、无符号长&c、整数跳转)
{
无符号长an=a;
for(int i=1;i
但在大多数情况下,发电机的周期可能不足

老实说,我会考虑使用第三方库,例如。SDK中也有一些批处理生成器,但在本例中,这可能不是您想要的

编辑


由于这是刚刚开始投票,我认为值得更新的是,正如最近对这个问题的回答所提到的,它是可用的,并提供了许多生成器和分发版。这绝对是最容易开始的地方。

对于任何感兴趣的人,您现在都可以通过。

最好的方法是编写自己的设备函数,下面就是一个

void RNG()
{   
    unsigned int m_w = 150;
    unsigned int m_z = 40;

    for(int i=0; i < 100; i++)
    {
        m_z = 36969 * (m_z & 65535) + (m_z >> 16);
        m_w = 18000 * (m_w & 65535) + (m_w >> 16);

        cout <<(m_z << 16) + m_w << endl;  /* 32-bit result */
    }
}
更改m_w和m_z起始值(在本例中为150和40)允许您每次获得不同的结果。您可以使用
threadIdx.x
作为其中之一,这将每次为您提供不同的伪随机序列


我想补充一点,它的运行速度比rand()函数快2倍,而且非常好;)

我认为关于这个问题的任何讨论都需要回答Zenna最初的请求,这是为了线程级的实现。特别是一个设备函数,可以从内核或线程中调用。对不起,如果我用粗体字的话说得太多了,但我真的认为到目前为止的答案并没有完全解决这里所寻求的问题

库兰图书馆是你最好的选择。我理解人们想要重新发明轮子(这让人更欣赏并更恰当地使用第三方库),但高性能高质量的数字生成器非常丰富,而且经过了良好的测试。我可以推荐的最佳信息是不同生成器上的GSL库文档:

对于任何严肃的代码,最好使用数学家/计算机科学家反复研究的主要算法之一来寻找系统的弱点。“mersenne twister”是一种周期(重复循环)约为10^6000(MT19997算法表示“mersenne twister 2^19997”)的产品,特别适合Nvidia使用线程id调用作为种子在同一经纱的线程级别上使用。见本文:。我实际上正在使用这个库实现一些东西,如果我让它正常工作,我会发布我的代码。Nvidia在其文档站点上提供了一些当前CUDA工具包的示例

注意:我没有为Nvidia工作过,但我承认他们为CUDA设计的文档和抽象设计给我留下了深刻的印象


你可以试试


它基于面向SIMD的快速梅森捻线器(SFMT),这是一种非常快速和可靠的随机数生成器。它通过了Marsaglias对随机数生成器的死硬测试。

如果您在Numba for Python中使用cuda.jit,这是很有用的。

我认为他正在寻找一个可以调用的库,而不是自己实现它。这仍然是一个很好的答案,可以为他指出一个解决方案。线性同余运算很容易实现。你可以通过在每个线程中有一个单独的PRNG和它自己的状态来实现CUDA。这让我有点困惑。每个线程都会说是从其线程id中播种的,但它们不会很快开始重叠吗?这些随机算法从x_n计算x_n+1,试图使用它们来创建并行随机数将导致具有非常独特模式的“随机”数。这是因为x_n+1是x_n的一个函数。alifeofzen:seeds中的linerar依赖性已经够糟糕了,的确(参见),也许您应该找到其他方法来对它们进行种子设定。丹尼:这是最简单的
((m_z << 16) + m_w)%1000