【问题标题】:Single-use PRNG seedable with consecutive seeds可连续种子播种的一次性 PRNG
【发布时间】:2016-06-03 04:13:46
【问题描述】:

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

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

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 中不可用或依赖于任何库
  • 它不应该循环使用连续性(例如循环 60 次只是为了得到第 60 个数字)
  • 实际上只需要从像 1000 这样的种子中生成一个良好的伪随机数,它与由相邻种子生成的数字不共享模式

我尝试过的任何典型 PRNG 算法都不能从相邻的种子中生成序列,这些序列看起来甚至很随机,它们不应该以这种方式播种和使用。

【问题讨论】:

  • 你有 64 位数学吗?
  • 是的,但是它可能会慢得多,所以如果可能的话最好避免。

标签: random


【解决方案1】:

如果您想要 32 位->32 位 RNG,则周期为 232,每个流中的 224 限制为 28 流。

话虽如此,您可能希望通过以下方式研究LCG RNG:如 F. Brown,“任意步长的随机数生成”中所述实现快速跳过。是。核。社会党。 (1994 年 11 月)。

因此,您从种子 1 开始,每个后续种子将沿线跳过 224

int32_t stream = 1 << 24;

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

因此,您将保证在整个期间获得不重叠的流

实现63位生成器idea的代码是here

更新

F.Brown 假设的向前跳过在 N 中是对数的,O(log2N)。

【讨论】:

  • 感谢您的指点,这就是我遵循stackoverflow.com/a/35612914/1675589 的结果。 1
  • What's with the 1&lt;&lt;24 thing though? 左移得到 2^24
  • 我知道那是做什么的,我的意思是你用*stream做什么?
  • 你不想stream 一个线程的随机数吗?也许我误解了这个问题......
【解决方案2】:

按照 Severin Pappadeux 的 answer,我研究了 LCG 的快速跳过,发现使用简单的 modular exponentiation 来适应 MINSTD 算法实际上非常简单。

将 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);
}

MINSTD 产生 31 位(但没有 2^31-1 值),但是我在 11 个最低有效位中发现了错误模式,因此我从 20 个有效位中取出 16 个并生成一个好的 32 位随机数其中两个。

pos 将是一个种子加上一个偏移量,表示 MINSTD 输出序列中的一个位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多