小智 14
Fisher-Yates shuffle可以并行化.例如,4个并发工作者只需要3次迭代来混洗8个元素的向量.在第一次迭代时,它们交换0 < - > 1,2 < - > 3,4 < - > 5,6 - 7; 在第二次迭代0 < - > 2,1 < - > 3,4 - 5,6 - 7; 并且在最后一次迭代0 - 4,1 - 5,2 - 6,3 - 7.

这可以很容易地实现为CUDA __device__代码(受标准最小/最大缩减的启发):
const int id = threadIdx.x;
__shared__ int perm_shared[2 * BLOCK_SIZE];
perm_shared[2 * id] = 2 * id;
perm_shared[2 * id + 1] = 2 * id + 1;
__syncthreads();
unsigned int shift = 1;
unsigned int pos = id * 2;
while(shift <= BLOCK_SIZE)
{
if (curand(&curand_state) & 1) swap(perm_shared, pos, pos + shift);
shift = shift << 1;
pos = (pos & ~shift) | ((pos & shift) >> 1);
__syncthreads();
}
Run Code Online (Sandbox Code Playgroud)
这里省略了curand初始化代码,并且方法swap(int *p, int i, int j)交换值p[i]和p[j].
请注意,上面的代码有以下假设:
__shared__CUDA设备的内存为了生成多个排列,我建议使用不同的CUDA块.如果目标是对7个元素进行排列(正如在原始问题中提到的那样),那么我相信在单个线程中执行它会更快.
| 归档时间: |
|
| 查看次数: |
3222 次 |
| 最近记录: |