我正在尝试在金属中创建一个伪随机数生成器(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;
}
}
}
框架完成并整齐地打包在这里:Link
我最终使用了@KenThomases的建议,我刚刚为RNG创建了一个类。我打包了代码并调用了RNG Loki
。 Here is the link to the repo如果有人想在将来使用它。