本博客已遷往http://coredumper.cn
CUDA Runtime API 沒有提供用於生成隨機數的接口,但是CURAND這個庫提供了通過GPU生成隨機數的接口,詳細內容可參考http://docs.nvidia.com/cuda/curand/index.html。
下面給出了通過GPU生成0.0到1.0之間(不包括0.0,包括1.0)服從均勻分佈的單精度浮點僞隨機數的CUDA程序。
#include <cuda.h>
#include <curand.h>
#define ERROR_EXIT -1
/* Check the return value of CUDA Runtime API */
#define CHECK_CUDA(err) do{\
if((err) != cudaSuccess){\
fprintf(stderr, "CUDA Runtime API error %d at file %s line %d: %s.\n",\
(int)(err), __FILE__, __LINE__, cudaGetErrorString((err)));\
exit(ERROR_EXIT);\
}}while(0)
/* Check the return value of CURAND api. */
#define CHECK_CURAND(err) do{\
if( (err) != CURAND_STATUS_SUCCESS ){\
fprintf(stderr, "CURAND error %d at file %s line %d.\n", (int)(err), __FILE__, __LINE__);\
exit(ERROR_EXIT);\
}}while(0)
/* Function: produce random float data by GPU
* Input: dataHost: the memory to store data produced
* number: the number of data to produce
* seed: the seed for random generator
* Output: void
*/
extern "C"
void randomGenerator(float *dataHost, int number, unsigned long long seed)
{
float *dataDev;
CHECK_CUDA( cudaMalloc( (void **) &dataDev, number * sizeof(float) ) );
curandGenerator_t gen;
CHECK_CURAND( curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT) );
CHECK_CURAND( curandSetPseudoRandomGeneratorSeed(gen, seed) );
CHECK_CURAND( curandGenerateUniform(gen, dataDev, number) );
CHECK_CURAND( curandDestroyGenerator(gen) );
CHECK_CUDA( cudaMemcpy(dataHost, dataDev, number * sizeof(float), cudaMemcpyDeviceToHost) );
CHECK_CUDA( cudaFree(dataDev) );
return;
}
使用CURAND生成隨機數需要注意以下幾個問題:
1. 函數curandCreateGenerator()的第二個參數指定的是隨機數生成器的類型,共有7種類型,分爲僞隨機數生成器和準隨機數生成器兩類。
2. 函數curandSetPseudoRandomGeneratorSeed()的第二個參數爲隨機數生成器指定種子,相同的種子將會生成相同的隨機數序列。
3. 函數curandGenerateUniform()用於生成0.0到1.0之間(不包括0.0,包括1.0)服從均勻分佈的單精度浮點數,共有8個類似的函數,分別用於生成服從不同分佈的不同類型的隨機數。另外一個比較常用的函數是curandGenerate(),用於生成unsigned int類型的隨機數。
4. 在編譯包含CURAND接口的文件時,需要添加指定鏈接庫的編譯選項-lcurand。