Random 单用PRNG可连续播种

Random 单用PRNG可连续播种,random,Random,我需要制作一个具有特定扭曲度的伪随机数生成器。我需要一个从连续的种子序列并行生成的伪随机数序列,而不是像通常那样使用前一代的种子为新一代的随机数连续生成数字 它是这样工作的,并行执行,每个线程只产生一个数字,线程之间没有共享或存储任何内容: thread #0: my_prng(1000) -> 1455191155 -> array[0] thread #1: my_prng(1001) -> 2432152707 -> array[1] thread #2: my_p

我需要制作一个具有特定扭曲度的伪随机数生成器。我需要一个从连续的种子序列并行生成的伪随机数序列,而不是像通常那样使用前一代的种子为新一代的随机数连续生成数字

它是这样工作的,并行执行,每个线程只产生一个数字,线程之间没有共享或存储任何内容:

thread #0: my_prng(1000) -> 1455191155 -> array[0]
thread #1: my_prng(1001) -> 2432152707 -> array[1]
thread #2: my_prng(1002) -> 185188134 -> array[2]
它用于从GPU(使用OpenCL)并行生成图像噪声,因此:

  • 它应该运行得足够快,就像只使用几个操作一样
  • 它不应该是加密安全的,它只是为了图形,它只需要看看随机的
  • 低潮期也可以,即使是2^24也可以
  • 它只需要生成32位整数
  • 它不应该使用任何内存,不应该使用缓冲区,也不应该将结果以外的任何内容存储在变量中(如果有结果,则生成的新种子将不会被使用)
  • 它不能依赖于对rand()的调用,因为它在OpenCL中不可用,也不能依赖于任何库
  • 它不应该循环使用serialness(例如,循环60次只是为了生成第60个数字)
  • 实际上,它只需要从一个种子(如1000)中生成一个好的伪随机数,而这个种子与相邻种子生成的数字没有相同的模式

我尝试过的典型PRNG算法中,没有一种能够从相邻的种子中生成看起来甚至是非常随机的序列,它们不应该以这种方式进行播种和使用。

如果您想要32位->32位RNG,那么周期将是232,并且每个流中有224个,则限制为28个流

话虽如此,您可能希望了解以下情况:如F.Brown“任意步长随机数生成”中所述,实现快速向前跳。是Nucl。Soc。(1994年11月)

因此,您从seed
1开始,随后的每个seed将沿着直线跳过224

int32_t stream = 1 << 24;

rng.set_seed(int32_t seed) {
   rng.skip_ahead(seed*stream)
}

int32_t stream=1如果您想要32位->32位RNG,那么周期将是232,并且每个流中有224个,您被限制为28个流

话虽如此,您可能希望了解以下情况:如F.Brown“任意步长随机数生成”中所述,实现快速向前跳。是Nucl。Soc。(1994年11月)

因此,您从seed
1开始,随后的每个seed将沿着直线跳过224

int32_t stream = 1 << 24;

rng.set_seed(int32_t seed) {
   rng.skip_ahead(seed*stream)
}

int32_t stream=1继Severin Pappadeux之后,我研究了LCG的快速跳转,发现使用简单的

MINSTD为
MINSTD(n+1)=16807*MINSTD(n)mod 2147483647
我们得到
MINSTD(n+1)=16807^n mod 2147483647

以下是我在OpenCL中生成的算法:

int pow_mod(int base, uint expon, uint mod)
{
    int x = 1, power = base % mod;

    for (; expon > 0; expon >>= 1)
    {
        if (expon & 1)
            x = (x * power) % mod;

        power = (power * power) % mod;
    }

    return x;
}

uint rand16(uint pos)
{
    return pow_mod(16807, pos, 2147483647) >> 13 & 0xFFFF;
}

uint rand32(uint pos)
{
    return rand16(pos) << 16 | rand16(pos + 0x80000000);
}
int-pow\u-mod(int-base、uint-expon、uint-mod)
{
整数x=1,功率=基准%mod;
对于(;expon>0;expon>>=1)
{
如果(expon&1)
x=(x*功率)%mod;
功率=(功率*功率)%mod;
}
返回x;
}
单元16(单元位置)
{
返回功率模块(16807,位置2147483647)>>13&0xFFFF;
}
uint rand32(uint位置)
{

return rand16(pos)继Severin Pappadeux之后,我研究了LCG的快速跳过,发现使用简单的

MINSTD为
MINSTD(n+1)=16807*MINSTD(n)mod 2147483647
我们得到
MINSTD(n+1)=16807^n mod 2147483647

以下是我在OpenCL中生成的算法:

int pow_mod(int base, uint expon, uint mod)
{
    int x = 1, power = base % mod;

    for (; expon > 0; expon >>= 1)
    {
        if (expon & 1)
            x = (x * power) % mod;

        power = (power * power) % mod;
    }

    return x;
}

uint rand16(uint pos)
{
    return pow_mod(16807, pos, 2147483647) >> 13 & 0xFFFF;
}

uint rand32(uint pos)
{
    return rand16(pos) << 16 | rand16(pos + 0x80000000);
}
int-pow\u-mod(int-base、uint-expon、uint-mod)
{
整数x=1,功率=基准%mod;
对于(;expon>0;expon>>=1)
{
如果(expon&1)
x=(x*功率)%mod;
功率=(功率*功率)%mod;
}
返回x;
}
单元16(单元位置)
{
返回功率模块(16807,位置2147483647)>>13&0xFFFF;
}
uint rand32(uint位置)
{

返回rand16(pos)你有64位的数学吗?是的,但是它可能慢得多,所以如果可能的话最好避免。你有64位的数学吗?是的,但是它可能慢得多,所以如果可能的话最好避免。谢谢你的指点,下面是我的结论。1
和1是什么关系?我知道这是什么,我的意思是w你用
*stream
做什么?你不想每一个线程用
stream
随机数吗?也许我误解了这个问题…谢谢你的指点,下面是我的结论。1
有什么用?1
有什么用我知道,我的意思是你用
*stream
做什么用?你不想
吗>每个线程随机数的流
?可能我误解了这个问题。。。