【问题标题】:Copying an integer from GPU to CPU将整数从 GPU 复制到 CPU
【发布时间】:2011-07-02 05:01:08
【问题描述】:

在每次内核调用之后,我需要将一个布尔值或整数值从设备复制到主机(我在 for 循环中调用同一个内核)。也就是说,在每次内核调用之后,我需要将一个整数或布尔值发送回主机。最好的方法是什么?

我应该将值直接写入 RAM 吗?还是我应该使用 cudaMemcpy()?或者有没有其他方法可以做到这一点?每次内核启动后只复制 1 个整数会减慢我的程序吗?

【问题讨论】:

    标签: cuda


    【解决方案1】:

    让我先回答你的最后一个问题:

    每次内核启动后只复制 1 个整数会减慢我的程序吗?

    有点——是的。发出命令、等待 GPU 响应等等……在这种情况下,数据量(1 个整数与 100 个整数)可能并不重要。但是,您仍然可以达到每秒数千次内存传输的速度。很可能,您的内核会比单次内存传输慢(否则,在 CPU 上完成整个任务可能会更好)

    最好的方法是什么?

    好吧,我建议您自己尝试一下。正如您所说:您可以使用映射固定内存并将值直接存储到 RAM 中,或者使用 cudaMemcpy。如果您的内核在发回整数后仍有一些工作要做,那么第一个可能会更好。在这种情况下,将其发送到主机的延迟可能会被内核的执行隐藏。

    如果您使用第一种方法,则必须调用cudaThreadsynchronize() 以确保内核结束执行。内核调用是异步的。

    您可以使用同样是异步的cudaMemcpyAsync,但GPU 不能让内核运行并让cudaMemcpyAsync 并行执行,除非您使用流。

    我实际上从未尝试过,但如果循环执行次数过多,您的程序不会崩溃,您可能尝试忽略同步并让它迭代,直到在 RAM 中看到特殊值.在该解决方案中,内存传输可能完全隐藏,您只需要在最后支付开销。但是,您需要以某种方式防止循环迭代太多次,CUDA 事件可能会有所帮助。

    【讨论】:

    • 对于复制单个变量,我建议使用cudaMemcpyFromSymbol
    • 同意,cudaMemcpyFromSymbol 可以将数据复制到全局设备变量(或常量)或从全局设备变量(或常量)复制数据。我不认为它实际上比 cudaMemcpy 快多少,但我没有做过任何测试。
    【解决方案2】:

    为什么不使用固定内存?如果您的系统支持 - 请参阅 CUDA C 编程指南的固定内存部分。

    【讨论】:

      【解决方案3】:

      将数据复制到 GPU 和从 GPU 复制数据将比从 CPU 访问数据慢得多。如果您没有为此值运行大量线程,那么这将导致性能非常低,请不要这样做。

      您所描述的内容听起来像是一个串行算法,您的算法需要并行化才能使其值得使用 CUDA。如果你不能将你的算法改写成单次写多数据到GPU,多线程,单次写多数据回CPU;那么你的算法应该在 CPU 上完成。

      【讨论】:

      • 我认为它可以是一个串行算法,内部包含复杂的并行块。
      • @CygnusX1 如果您阅读了我的回答,您会发现它可以容纳这种可能性。
      • 第一段,是的。但是然后你说“你所描述的听起来像一个串行算法”——尽管我的程序是高度并行的,但我多次遇到与问题作者类似的问题。因此我的评论。
      • @CynusX1 如果你读过我的第二段,你会看到“..single write, multiple threads,..”。我们都遇到过这个问题。
      【解决方案4】:

      如果您需要在上一个内核调用中计算的值来启动下一个内核调用,那么将被序列化,您的选择是 cudaMemcpy(dst,src, size =1, ...);

      如果所有内核启动参数不依赖于上一次启动,那么您可以将每次内核调用的所有结果存储在 GPU 内存中,然后一次下载所有结果。

      【讨论】:

        猜你喜欢
        • 2012-10-31
        • 2012-07-29
        • 1970-01-01
        • 1970-01-01
        • 2022-01-26
        • 2018-10-22
        • 2017-04-10
        • 2018-03-24
        • 2012-07-03
        相关资源
        最近更新 更多