简体   繁体   English

打乱一个浮点数?

[英]Scramble a floating point number?

I need a repeatable pseudo-random function from floats in [0,1] to floats in [0,1].我需要一个可重复的伪随机 function 从 [0,1] 中的浮点数到 [0,1] 中的浮点数。 Ie given a 32-bit IEEE float, return a "different" one (as random as possible, given the 24 bits of mantissa).即给定一个 32 位 IEEE 浮点数,返回一个“不同”的浮点数(尽可能随机,给定 24 位尾数)。 It has to be repeatable, so keeping tons of internal state is out.它必须是可重复的,因此保留大量内部 state 已被淘汰。 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).不幸的是,它只能使用 32 位整数和单浮点数学(没有双精度,甚至没有 32x32=64 位乘法,尽管如果需要我可以模拟——基本上它需要在较旧的 CUDA 硬件上工作)。 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.) (我经历过需要 64 位整数数学的 Park-Miller,以及需要双打的 Park-Miller 的 CUDA 版本,Mersenne Twisters 有很多内部 state,以及其他一些不起作用的东西。 )

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. NVIDIA CUDA 工具包包含一个名为CURAND的库,我相信它符合您的要求:它产生可重复的结果(假设您从相同的种子开始),适用于 GPU,支持 32 位浮点数和整数,并且应该适用于较旧的 GPU。 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. [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除以 RAND_MAX 只有 16 个随机位的精度。 What's more, on linux/mac it returns a 32-bit value so code that uses it is not numerically portable.]更重要的是,在 linux/mac 上它返回一个 32 位的值,所以使用它的代码在数字上是不可移植的。]

Best I understand the requirements, a hash accomplishes the desired functionality.最好我了解要求,hash 可以完成所需的功能。 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]. 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分布在 [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 . 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.要将浮点数的位重新解释为 integer,反之亦然,在 CUDA 中有两种选择。 Use intrinsics, or use C++-style reinterpretation casts:使用内在函数,或使用 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);

So as a self-contained function, the entire process might look something like this:所以作为一个独立的 function,整个过程可能看起来像这样:

/* 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;
}

Why not use the standard C library rand() function and divide the result by RAND_MAX ?为什么不使用标准 C 库rand() function 并将结果除以RAND_MAX

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM