【发布时间】:2011-07-02 05:01:08
【问题描述】:
在每次内核调用之后,我需要将一个布尔值或整数值从设备复制到主机(我在 for 循环中调用同一个内核)。也就是说,在每次内核调用之后,我需要将一个整数或布尔值发送回主机。最好的方法是什么?
我应该将值直接写入 RAM 吗?还是我应该使用 cudaMemcpy()?或者有没有其他方法可以做到这一点?每次内核启动后只复制 1 个整数会减慢我的程序吗?
【问题讨论】:
标签: cuda
在每次内核调用之后,我需要将一个布尔值或整数值从设备复制到主机(我在 for 循环中调用同一个内核)。也就是说,在每次内核调用之后,我需要将一个整数或布尔值发送回主机。最好的方法是什么?
我应该将值直接写入 RAM 吗?还是我应该使用 cudaMemcpy()?或者有没有其他方法可以做到这一点?每次内核启动后只复制 1 个整数会减慢我的程序吗?
【问题讨论】:
标签: cuda
让我先回答你的最后一个问题:
每次内核启动后只复制 1 个整数会减慢我的程序吗?
有点——是的。发出命令、等待 GPU 响应等等……在这种情况下,数据量(1 个整数与 100 个整数)可能并不重要。但是,您仍然可以达到每秒数千次内存传输的速度。很可能,您的内核会比单次内存传输慢(否则,在 CPU 上完成整个任务可能会更好)
最好的方法是什么?
好吧,我建议您自己尝试一下。正如您所说:您可以使用映射固定内存并将值直接存储到 RAM 中,或者使用 cudaMemcpy。如果您的内核在发回整数后仍有一些工作要做,那么第一个可能会更好。在这种情况下,将其发送到主机的延迟可能会被内核的执行隐藏。
如果您使用第一种方法,则必须调用cudaThreadsynchronize() 以确保内核结束执行。内核调用是异步的。
您可以使用同样是异步的cudaMemcpyAsync,但GPU 不能让内核运行并让cudaMemcpyAsync 并行执行,除非您使用流。
我实际上从未尝试过,但如果循环执行次数过多,您的程序不会崩溃,您可能尝试忽略同步并让它迭代,直到在 RAM 中看到特殊值.在该解决方案中,内存传输可能完全隐藏,您只需要在最后支付开销。但是,您需要以某种方式防止循环迭代太多次,CUDA 事件可能会有所帮助。
【讨论】:
cudaMemcpyFromSymbol 可以将数据复制到全局设备变量(或常量)或从全局设备变量(或常量)复制数据。我不认为它实际上比 cudaMemcpy 快多少,但我没有做过任何测试。
为什么不使用固定内存?如果您的系统支持 - 请参阅 CUDA C 编程指南的固定内存部分。
【讨论】:
将数据复制到 GPU 和从 GPU 复制数据将比从 CPU 访问数据慢得多。如果您没有为此值运行大量线程,那么这将导致性能非常低,请不要这样做。
您所描述的内容听起来像是一个串行算法,您的算法需要并行化才能使其值得使用 CUDA。如果你不能将你的算法改写成单次写多数据到GPU,多线程,单次写多数据回CPU;那么你的算法应该在 CPU 上完成。
【讨论】:
如果您需要在上一个内核调用中计算的值来启动下一个内核调用,那么将被序列化,您的选择是 cudaMemcpy(dst,src, size =1, ...);
如果所有内核启动参数不依赖于上一次启动,那么您可以将每次内核调用的所有结果存储在 GPU 内存中,然后一次下载所有结果。
【讨论】: