CUDA移植具有内部随机函数的结构

时间:2012-02-02 17:36:20

标签: c++ random cuda porting

我必须在GPU上移植一个广泛使用随机数的结构。一切都可以移植而没有很多问题,但随机生成器函数是它在该类的所有函数中被广泛调用的唯一事物。 我虽然可以简单地重新实现它作为类本身的内部设备功能。 下面我给出了我需要的玩具模型(考虑到我工作的班级更复杂)。 我还需要函数“rand”的每个调用给出一个不同的随机数(即使在同一个对象中)。 这里的玩具模型,但它产生了错误的结果。有人可以帮我纠正吗?

#include <cuda.h>
#include <iostream>
#include <curand_kernel.h>
using namespace std;

struct test{

float value;

curandState B;

void __device__ rand(){value=curand_uniform(&B);}
void __device__ foo(){rand();}
};

__global__ void setup_kernel(curandState *state)
{
const int id=blockIdx.x;
curand_init(id, id, 0, &state[id]);
}

__global__ void fill_mat(struct test *anobj, curandState *state)
{
 const int Idx=blockIdx.x;
 curandState localState = state[Idx];
 anobj[Idx].B=localState;
 anobj[Idx].foo();
}

int main()
{
int num=10;
curandState *devStates;
cudaMalloc(  (void **)&devStates, num*sizeof(curandState) );

struct test *results = (struct test*)malloc(num*sizeof(struct test));
struct test *to_device;
cudaMalloc ( (void **)&to_device, num*sizeof(to_device));

setup_kernel<<<num, 1>>>(devStates);

fill_mat<<<num,1>>>(to_device, devStates);

cudaMemcpy(results,to_device,num*sizeof(struct test),cudaMemcpyDeviceToHost);

for(int i=0;i<num;i++)
 cout<<results[i].value<<endl; 
return 0;
}

1 个答案:

答案 0 :(得分:3)

感谢伟大(完整)的例子。建成之后我发现了两个问题。

当您使用cudaMalloc to_device时,您希望分配num * sizeof(struct test)字节。

我假设您可能想要多次调用fill_mat,或者您可能有其他内核,并且您希望它们每次都能获得不同的数字。如果是这样,在fill_mat(或制作curandState副本的其他内核)的末尾,您需要将本地状态复制回curandState。这是因为每次生成数字时,curand都会提升状态。

最后(这不一定是个bug)我看到你在调用curand_init时使用线程id作为种子和序列。这是可以的,但是有一些(极不可能的)风险,curand的种子加扰算法会让你陷入与其他线程重叠的序列的一部分。 curand_init使用加扰版本的种子生成初始状态,然后应用序列的2 * 67倍的前导。通常,目的是所有线程都使用相同的种子,以保证每个线程在序列内与前一个线程相距2 * 67。

帕兹。