打乱浮点数?

发布于 2024-11-10 11:28:00 字数 366 浏览 5 评论 0原文

我需要一个可重复的伪随机函数,从 [0,1] 中的浮点数到 [0,1] 中的浮点数。即给定一个 32 位 IEEE 浮点数,返回一个“不同的”浮点数(给定 24 位尾数,尽可能随机)。它必须是可重复的,因此保留大量的内部状态是不可能的。不幸的是,它只能处理 32 位 int 和单浮点数学(没有双精度,甚至不能进行 32x32=64 位乘法,尽管我可以根据需要进行模拟——基本上它需要在较旧的 CUDA 硬件上工作)。当然,在这些相当严格的限制范围内,随机性越好。有人有什么想法吗?

(我已经了解了 Park-Miller,它需要 64 位 int 数学,以及 CUDA 版本的 Park-Miller,它需要双打,Mersenne Twisters 有很多内部状态,以及其他一些不起作用的东西。 )

I need a repeatable pseudo-random function from floats in [0,1] to floats in [0,1]. I.e. given a 32-bit IEEE float, return a "different" one (as random as possible, given the 24 bits of mantissa). It has to be repeatable, so keeping tons of internal state is out. And unfortunately it has to work with only 32-bit int and single-float math (no doubles and not even 32x32=64bit multiply, though I could emulate that if needed -- basically it needs to work on older CUDA hardware). The better the randomness the better, of course, within these rather severe limitations. Anyone have any ideas?

(I've been through Park-Miller, which requires 64-bit int math, and the CUDA version of Park-Miller which requires doubles, Mersenne Twisters which have lots of internal state, and a few other things which didn't work.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清晨说晚安 2024-11-17 11:28:00

据我了解,哈希可以完成所需的功能。将浮点输入重新解释为整数,应用哈希函数生成一个近似均匀分布在 [0,2^32) 中的整数,然后将该整数乘以 2^-32,将所得整数大致均匀地转换回浮点数分布在[0,1]。 Bob Jenkin 的 mix() 是一种不需要乘法的合适哈希函数,可以在此处找到:http://www.burtleburtle.net/bob/hash/doobs.html

要将浮点数重新解释为整数,反之亦然,CUDA 中有两种选择。使用内在函数,或者使用 C++ 风格的重新解释转换:

float f;
int i;
i = __float_as_int(f);
f = __int_as_float(i);
i = reinterpret_cast<int&>(f);
f = reinterpret_cast<float&>(i);

因此作为一个独立的函数,整个过程可能如下所示:

/* transform float in [0,1] into a different float in [0,1] */
float scramble_float (float f)
{
    unsigned int magic1 = 0x96f563ae; /* number of your choice */
    unsigned int magic2 = 0xb93c7563; /* number of your choice */
    unsigned int j;
    j = reinterpret_cast<unsigned int &>(f);
    mix (magic1, magic2, j);
    return 2.3283064365386963e-10f * j;
}

Best I understand the requirements, a hash accomplishes the desired functionality. Re-interprete the float input as an integer, apply the hash function to produce an integer approximately uniformly distributed in [0,2^32), then multiply this integer by 2^-32 to convert the resulting integer back to a float roughly uniformly distributed in [0,1]. One suitable hash function which does not require multiplication is Bob Jenkin's mix(), which can be found here: http://www.burtleburtle.net/bob/hash/doobs.html.

To re-interpret the bits of a float as an integer and vice versa, there are two choices in CUDA. Use intrinsics, or use C++-style reinterpretation casts:

float f;
int i;
i = __float_as_int(f);
f = __int_as_float(i);
i = reinterpret_cast<int&>(f);
f = reinterpret_cast<float&>(i);

So as a self-contained function, the entire process might look something like this:

/* transform float in [0,1] into a different float in [0,1] */
float scramble_float (float f)
{
    unsigned int magic1 = 0x96f563ae; /* number of your choice */
    unsigned int magic2 = 0xb93c7563; /* number of your choice */
    unsigned int j;
    j = reinterpret_cast<unsigned int &>(f);
    mix (magic1, magic2, j);
    return 2.3283064365386963e-10f * j;
}
作业与我同在 2024-11-17 11:28:00

NVIDIA CUDA 工具包包含一个名为 CURAND 的库我相信它符合您的要求:它产生可重复的结果(假设您从相同的种子开始),在 GPU 上工作,支持 32 位浮点数和整数,并且应该在较旧的 GPU 上工作。它还支持多种伪随机和准随机生成算法和分布。

[注意:使用 C 库 rand() 函数的一个问题(除了它不在设备上的 CUDA 中运行之外)是,在 Windows 上,rand() 仅返回 16 位值,因此由除以 RAND_MAX 仅有 16 个随机位精度。此外,在 linux/mac 上它返回一个 32 位值,因此使用它的代码不可在数值上移植。]

The NVIDIA CUDA Toolkit includes a library called CURAND that I believe fits your requirements: it produces repeatable results (assuming you start with the same seed), works on the GPU, supports 32-bit floats and ints, and should work on older GPUs. It also supports multiple pseudo- and quasi-random generation algorithms and distributions.

[Note: a problem with using the C library rand() function (other than that it does not run in CUDA on the device) is that on Windows, rand() only returns a 16-bit value, and thus any float created by division by RAND_MAX has only 16 random bits of precision. What's more, on linux/mac it returns a 32-bit value so code that uses it is not numerically portable.]

汹涌人海 2024-11-17 11:28:00

为什么不使用标准 C 库 rand() 函数并将结果除以 RAND_MAX

#include <stdlib.h>
float randf (void)
{
     return rand() / (float) RAND_MAX;
}

Why not use the standard C library rand() function and divide the result by RAND_MAX?

#include <stdlib.h>
float randf (void)
{
     return rand() / (float) RAND_MAX;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文