我从Setup()
内核生成 1个256线程块,以设置具有256个CURAND状态的数组RNGstates
:
__global__ void Setup(curandState *RNGstates, long seed) {
int tid = threadIdx.x;
curand_init(seed, tid, 0, &RNGstates[tid]);
}
现在,我从Generate()
内核中生成 1000个256个线程的块,用256,000个随机数填充数组result
。但是,我只使用RNGstates
的256个状态,这样每个状态将被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()
会以某种方式更新状态,所以我假设正在进行一些写操作。
当映射到256个CURAND状态中的每一个的1000个线程尝试通过curand_uniform()
隐式更新状态时,我应该担心会发生数据争用吗?这是否会影响我的随机数的质量(例如,获得频繁的重复值)?
非常感谢。
答案 0 :(得分:3)
我认为分享国家肯定会影响质量。重复值是共享状态的最佳情况。数据竞争可能完全破坏各州。
你可以为每个线程保留一个状态。
使用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;
}
要减少多个块的内存要求,可以将#block限制为一个小数字,并为每个线程生成多个随机数,而不是每个线程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;
}
有关如何处理多个块的完整示例,请参阅cuRAND参考手册中的Device API Examples部分。
答案 1 :(得分:2)
您也可以使用curandStateMtgp32_t,每个块只需要一个(如果每个块最多256个线程)http://docs.nvidia.com/cuda/curand/device-api-overview.html#bit-generation-1