问题
在设备全局内存中移动许多随机(非合并)值时,最有效的方法是什么?
注意:许多值 > 500。
语境
我从事 GPU 的遗传算法实现已经有一段时间了,我一直在努力在我的框架的灵活性和 GPU 架构的微优化之间挣扎。GA 数据始终驻留在 GPU 中。只有最好的世代解决方案被复制到主机内存。
详细场景
我正在优化迁移功能。这里基本上很少有数据在设备 Global Memory中洗牌。但是我的数据顺序是这样的,它与 GA 操作符内核线程的内存访问方案合并,这使得洗牌一对“基因组”,一个跨步获取单个 FLOAT 值的问题,并将它们与另一个基因组交换同样大步时尚。
已知解决方案
问题不在于内存带宽,而是调用延迟和线程块停止进程的问题。
我写了几个设备内核,其功能只是在地址之间移动值。这将启动一个内核(具有非常低的占用率、不同的代码和随机内存访问......因此它运行的小代码将被序列化),但只需对设备进行两次内核调用即可完成工作。
- 第一个内核将值复制到缓冲区数组。
- 第二个内核交换值。
我知道我可以对每个值使用cudaMemcpy,但这需要多次调用cudaMemCpy,我认为这是同步调用。
简化代码示例:
int needed_genome_idx = 0; // Some random index.
for(int nth_gene = 0; nth_gene < num_genes; ++nthgene)
{
cudaMemcpy(genomes_buffer + nth_gene,
src + needed_genome_idx + nth_gene * stride_size, // stride_size being a big number, usually equal to the size of the GA population.
sizeof(float),
cudaMemCpyDeviceToDevice);
}
这是一个可行的解决方案吗?使用cudaMemCpyAsync会提高性能吗?
有没有更好的方法,或者至少更优雅的方法来做这样的内存操作?