Metal - 一个线程本地的命名空间变量?

问题描述 投票:1回答:1

我正在尝试在金属中创建一个伪随机数生成器(PRNG),类似于thrust的RNG,每当你在一个线程中调用RNG时,它会产生一个给定特定种子的不同随机数,在这种情况下,它将是thread_position_in_grid。我把它设置得很完美,现在我使用我的代码得到一个很好的均匀随机图片。

但是,我的代码每个线程只能运行一次。我想实现一个next_rng()函数,它使用最后一个结果作为种子返回一个新的rng。但是,由于我的RNG是命名空间,因此我无法存储最后的结果,并且我只能将最后的结果存储在constant地址空间中,这是不可更新的。有没有办法绕过这个/重构我的代码以避免这种情况?

我能在网上找到的最好的帮助是this SO post,遗憾的是它并不适用于我,因为我不能像在解决方案中那样将变量声明为函数中的静态。

如果有帮助,我会以任何方式重组我的代码。我可以将它变成静态类或类或其他东西吗?毫无头绪,但我只想要一个PRNG

我的代码(简化)基本上与帖子的结构相同:

namespace metal_rng {

    thread unsigned* last_seed() {
        thread uint last_seed = 1; // Doesn't work because last-seed falls out of scope after the function quits

        // The following comment line doesn't even compile:
        // thread static uint last_seed = 1;

        return &last_seed;
    }

    unsigned TausStep(const unsigned z, const int s1, const int s2, const int s3, const unsigned M)
    {
        unsigned b=(((z << s1) ^ z) >> s2);
        return (((z & M) << s3) ^ b);
    }

    device float rng(const int initial_seed) {
        int seed = initial_seed * 1099087573UL;

        unsigned hashed = (1664525*(*last_seed()) + 1013904223UL);
        *last_seed() = hashed
        return (hashed) * 2.3283064365387e-10;
    }

    device float next_rng() {
          if (*last_seed() == 0) {
              return 0.0;
          } else {
              unsigned hashed = (1664525*(*last_seed()) + 1013904223UL);
              return (hashed) * 2.3283064365387e-10;
          }
    }
}

Edit:

框架完成并整齐地打包在这里:Link

c++ random gpu gpgpu metal
1个回答
0
投票

我最终使用了@KenThomases的建议,我刚刚为RNG创建了一个类。我打包了代码并调用了RNG LokiHere is the link to the repo如果有人想在将来使用它。

© www.soinside.com 2019 - 2024. All rights reserved.