【发布时间】:2013-08-27 07:17:34
【问题描述】:
问题
在设备全局内存中移动许多随机(非合并)值时,哪种方式最有效?
注意:许多值都在 > 500 中。
上下文
我从事 GPU 的遗传算法实现已经有一段时间了,我一直在努力在我的框架的灵活性和 GPU 架构的微优化之间挣扎。 GA 数据始终驻留在 GPU 中。只有最佳代解决方案被复制到主机内存中。
详细场景
我正在优化迁移功能。这里基本上很少有数据在设备全局内存中被洗牌。但是我的数据顺序以这种方式合并为 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 会提高性能吗?
有没有更好的方式,或者至少更优雅的方式来做这样的内存操作?
【问题讨论】:
-
您的基因组载体的长度是多少?您需要洗牌多少对基因组?当您改组一对基因组向量时,应该交换向量中的多少元素?这些元素是如何选择的? (随机还是范围?)您的基因组是如何存储在全局内存中的?能否提供更具体的代码示例?
-
只复制 1 个浮点数和 1 个
cudaMemcpy()调用显然是一种非常低效的方法 -
我正在实现框架,并且我的目标是灵活性。 GPU 实现的本质要求使用大量岛屿、大量人口和高维基因组进行 GA 设置,因此使用 GPU 而不是 CPU 是有意义的。因此,您要求的这些细节会有所不同。但通常我使用以下:基因组向量将在 10-50 范围内,要洗牌的基因组很可能是每个岛一个,~16(但可能是更大的数字),整个向量将是在每个迁移操作中交换(通常在一定数量的代之后)。
-
如果您仍然一次复制一个浮点数,则不会有太大差异。一般
cudaMemcpy()/cmdaMemcpyAsync()会在数据大小> 100 KBbytes时达到其最大速度,如此处D2D复制速度所示stackoverflow.com/questions/17729351/… -
cudaMemcpyDeviceToDevice可能比编写内核来执行相同操作要慢,请参阅CUDA Device To Device transfer expensive。您的代码对我来说不是很清楚:genomes_buffer和src未定义,needed_genome_idx声称是随机的,但设置为0。您能否更清楚地了解“迁移”对您意味着什么?
标签: c++ c cuda parallel-processing gpgpu