我产卵的256个线程1块从我的Setup()
内核设置一个阵列RNGstates
256种CURAND状态:
__global__ void Setup(curandState *RNGstates, long seed) {
int tid = threadIdx.x;
curand_init(seed, tid, 0, &RNGstates[tid]);
}
现在,我产卵256个线程块1000从我的Generate()
内核,以填补阵列result
与256,000随机数。 然而,我这样做只使用的256个状态RNGstates
,使得每个状态将由1000个线程(一个来自每个块)来访问:
__global__ void Generate(curandState *RNGstates, float *result) {
int tid = blockIdx.x*blockDim.x + threadIdx.x;
float rnd = curand_uniform(&RNGstates[threadIdx.x]);
result[tid] = rnd;
}
我知道,调用curand_uniform()
莫名其妙地更新状态,所以我相信一些写操作发生。
所以,我应该担心数据的比赛,当1000个线程映射到每个256种CURAND状态存在的尝试,通过隐含更新状态curand_uniform()
这是否会影响我的随机数的质量(如经常得到重复的值)?
非常感谢。
我想分享的状态肯定会影响品质。 重复值是共享状态最好的情况。 数据竞争可能会完全毁掉的状态。
你可以保持一个状态为每个线程。
当使用1000块,都需要你的情况256,000状态。 该代码应该是这样的
__global__ void Setup(curandState *RNGstates, long seed) {
int tid = blockIdx.x*blockDim.x + threadIdx.x;
curand_init(seed, tid, 0, &RNGstates[tid]);
}
和
__global__ void Generate(curandState *RNGstates, float *result) {
int tid = blockIdx.x*blockDim.x + threadIdx.x;
float rnd = curand_uniform(&RNGstates[tid]);
result[tid] = rnd;
}
为了减少多块MEM的要求,你可以在你的#封锁限制在一个小数目,并产生每个线程多个随机数,而不是每个线程1张的随机数。
__global__ void generate_uniform_kernel(curandState *state,
unsigned int *result)
{
int id = threadIdx.x + blockIdx.x * 64;
unsigned int count = 0;
float x;
/* Copy state to local memory for efficiency */
curandState localState = state[id];
/* Generate pseudo-random uniforms */
for(int n = 0; n < 10000; n++) {
x = curand_uniform(&localState);
/* Check if > .5 */
if(x > .5) {
count++;
}
}
/* Copy state back to global memory */
state[id] = localState;
/* Store results */
result[id] += count;
}
请参阅部分设备API的例子在cuRAND参考手册,了解有关如何应对多发块完整的例子。
您还可以使用curandStateMtgp32_t,你只需要一个每块(如果块最多256个线程每个) http://docs.nvidia.com/cuda/curand/device-api-overview.html#bit-generation-1