关于cudaMemcpyAsync功能

时间:2012-12-06 11:51:52

标签: cuda

我有一些问题。

最近我正在使用CUDA创建一个程序。

在我的程序中,主机上有一个大数据用std :: map编程(string,vector(int))。

通过使用这些数据,一些vector(int)被复制到GPU全局内存并在GPU上进行处理

处理完成后,会在GPU上生成一些结果,并将这些结果复制到CPU中。

这些都是我的节目安排。

  1. cudaMemcpy(...,cudaMemcpyHostToDevice)
  2. 内核函数(只有在必要的数据被复制到GPU全局内存时才能完成内核函数)
  3. cudaMemcpy(...,cudaMemcpyDeviceToHost)
  4. 重复1~3步1000次(对于另一个数据(向量))
  5. 但我希望减少处理时间。

    所以我决定在我的程序中使用cudaMemcpyAsync函数。

    在搜索了一些文档和网页后,我意识到要使用cudaMemcpyAsync函数主机内存,其中有数据要复制到GPU全局内存必须分配为固定内存。

    但是我的程序正在使用std :: map,所以我无法将这个std :: map数据转换为固定内存。

    因此,我没有使用它,而是制作了一个缓冲数组类型的固定内存,这个缓冲区可以随时处理所有复制矢量的情况。

    最后,我的程序就像这样工作。

    1. Memcpy(使用循环将数据从std :: map复制到缓冲区,直到整个数据被复制到缓冲区)
    2. cudaMemcpyAsync(...,cudaMemcpyHostToDevice)
    3. 内核(只有在将整个数据复制到GPU全局内存时才能执行内核函数)
    4. cudaMemcpyAsync(...,cudaMemcpyDeviceToHost)
    5. 重复1~4步1000次(对于另一个数据(向量))
    6. 我的程序变得比前一个案例快得多。

      但问题(我的好奇心)正是在这一点上。

      我试图以类似的方式制作另一个节目。

      1. Memcpy(将数据从std :: map复制到缓冲区仅用于一个向量)
      2. cudaMemcpyAsync(...,cudaMemcpyHostToDevice)
      3. 循环1~2,直到将整个数据复制到GPU全局内存
      4. 内核(只有在必要的数据被复制到GPU全局内存时才能执行内核功能)
      5. cudaMemcpyAsync(...,cudaMemcpyDeviceToHost)
      6. 重复1~5步1000次(对于另一个数据(向量))
      7. 这种方法比上面讨论的方法快10%左右。

        但我不知道为什么。

        我认为cudaMemcpyAsync只能与内核函数重叠。

        但我的情况我认为不是。而不是它看起来可以在cudaMemcpyAsync函数之间重叠。

        很抱歉我的问题很长,但我真的很想知道原因。

        有人可以教我或解释一下“cudaMemcpyAsync”的确切设施是什么,以及哪些功能可以与“cudaMemcpyAsync”重叠?

1 个答案:

答案 0 :(得分:12)

cudaMemcpyAsync(以及内核活动)的复制活动可以与任何主机代码重叠。此外,与设备之间的数据复制(通过cudaMemcpyAsync)可以与内核活动重叠。所有3个活动:主机活动,数据复制活动和内核活动,可以彼此异步完成,并且可以相互重叠。

正如您所见并证明的那样,主机活动和数据复制或内核活动可以相对简单的方式相互重叠:内核启动会立即返回主机,cudaMemcpyAsync也是如此。但是,要在数据副本和内核活动之间获得最佳重叠机会,必须使用一些其他概念。为了获得最佳重叠机会,我们需要:

  1. 固定的主机内存缓冲区,例如通过cudaHostAlloc()
  2. 使用cuda流来分离各种类型的活动(数据复制和内核计算)
  3. 使用cudaMemcpyAsync(而不是cudaMemcpy)
  4. 当然,你的工作也需要以可分离的方式分解。这通常意味着如果您的内核正在执行特定的功能,您可能需要对此内核进行多次调用,以便每次调用都可以处理单独的数据。例如,这允许我们在第一次内核调用处理数据块A时将数据块B复制到设备。在这样做时,我们有机会将数据块B的副本与数据块A的内核处理重叠。

    与cudaMemcpyAsync(与cudaMemcpy相比)的主要区别在于:

    1. 可以在任何流中发布(它需要一个流参数)
    2. 通常,它会立即将控制权返回给主机 (就像内核调用一样),而不是等待数据副本完成。
    3. 项目1是必要的特征,因此数据复制可以与内核计算重叠。第2项是必要的功能,因此数据副本可以与主机活动重叠。

      虽然复制/计算重叠的概念非常简单,但实际上实现需要一些工作。有关其他参考,请参阅:

      1. Overlap copy/compute section CUDA最佳做法指南。
      2. 示例代码显示basic implementation of copy/compute overlap
      3. 示例代码显示完整的multi/concurrent kernel copy/compute overlap scenario
      4. 请注意,上面的一些讨论是基于具有计算能力2.0或更高版本的设备(例如并发内核)。此外,不同的设备可能有一个或两个复制引擎,这意味着只能在某些设备上同时复制到设备并从设备复制