2011-05-31 94 views
4

我需要一個可重複的僞隨機函數,從[0,1]中的浮點數到[0,1]中的浮點數。即給定一個32位的IEEE浮點數,返回一個「不同的」(儘可能隨機,給定24位尾數)。它必須是可重複的,所以保持大量的內部狀態。不幸的是,它只能使用32位整數和單浮點數學運算(沒有雙精度,甚至不是32x32 = 64位乘法,儘管我可以根據需要模擬它 - 基本上它需要在較早的CUDA硬件上工作)。當然,隨機性越好越好,在這些嚴重的限制之內。有人有主意嗎? (我已經通過Park-Miller,需要64位int數學,需要雙打的Park-Miller的CUDA版本,擁有很多內部狀態的Mersenne Twisters,以及其他幾個不需要的東西沒有工作。)爭奪一個浮點數?

+1

_Tons並不意味着_not reproducible_。你是否嚴格需要一個函數來返回一個'float'給定的'float',並且兩者之間的相關性很難被發現?還是你真的在尋找一個具有有限計算能力的好的僞隨機數發生器? – sarnold 2011-05-31 22:58:16

+0

函數應該是可逆的還是不可以?它需要密碼強大嗎? – caf 2011-06-01 03:57:30

+0

Invertible?號密碼強?不,我是爲了圖形目的而做的,所以我需要合理分佈的結果。基本上給了一個(x,y)作爲浮點數,我希望我的函數只返回一個新的僞隨機(x,y)點作爲原始x,y的函數。或者1維相同:給定x,返回x',其中x'「看起來」隨機。我的意思是可重複的結果必須純粹是輸入的函數。 – GaryO 2011-06-01 13:42:25

回答

3

最好我理解需求,哈希完成所需的功能。將float輸入重新解釋爲一個整數,應用散列函數生成一個近似均勻分佈在[0,2^32)中的整數,然後將該整數乘以2^-32將生成的整數大致均勻地轉換回浮點數分佈在[0,1]。一個不需要乘法的散列函數是Bob Jenkin的mix(),它可以在這裏找到:http://www.burtleburtle.net/bob/hash/doobs.html

要將float的位重新解釋爲整數,反之亦然,在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); 

因此,作爲一個獨立的功能,整個過程可能是這個樣子:

內部STATE_的
/* 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; 
} 
+0

酷!絕對不是我以前的想法,但是正確的目標。 – GaryO 2011-06-02 23:25:51

+1

事實證明,這是一個很好的方向。我在http://home.comcast上找到了詹金斯的兩個不同但很好的混合函數(單輸入32位不碰撞)。 net /〜bretm/hash/3.html這是太大,不能粘貼在這裏,並給出了很好的結果。 – GaryO 2011-06-04 10:45:20

2

爲什麼不使用標準C函數庫rand()函數並將結果除以RAND_MAX

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

在調用'rand'之前,不要忘記用'srand'種子。 – 2011-06-01 00:40:27

+0

不幸的是,在CUDA上不起作用。但在CPU上,至少你是對的,你可以將浮點數轉換爲int i = *(int *)&f;然後用它來種子。 – GaryO 2011-06-01 13:37:23

3

的NVIDIA CUDA工具包包括一個名爲CURAND庫,我相信符合您的要求:它會產生重複的結果(假設你開始使用相同的種子),工作於GPU,支持32位浮點和整數,並應該在較早的GPU上工作。它還支持多種僞隨機和準隨機生成算法和分佈。 (注意:使用C庫rand()函數的問題(除了它不能在CUDA中運行)在Windows上,rand()只返回一個16位的值,因此由RAND_MAX劃分的任何浮點數只有16個隨機位的精度。更重要的是,在linux/mac上它返回一個32位的值,所以使用它的代碼在數字上並不便攜。]

+0

您的回答是正確的,因爲我提出了問題 - 謝謝。不幸的是我遺漏了一項要求;在CPU上運行時,我需要與GPU上相同的值,因此只有CUDA的庫不適用於我。這就是爲什麼我一直試圖自己做,所以我可以得到便攜式(GPU/CPU)代碼。 – GaryO 2011-06-01 13:38:35

+0

curand_kernel.h中的curand設備API的實現非常清晰 - 你可以非常平凡地移植到CPU上。作爲開始,您可以嘗試更改該文件中的#define QUALIFIERS,以便代替'#define QUALIFIERS static inline __device__',而不是'#define QUALIFIERS static inline __device__ __host__'。這應該使您從設備內核調用的所有功能都可以從主機代碼中調用。 (可能還有其他問題,我沒有嘗試過)。 – harrism 2011-06-02 04:58:47

+0

或者,您可以使用curand主機API在GPU上生成一個隨機值數組,然後將該數組複製回主機以用於CPU代碼。 – harrism 2011-06-02 04:59:15