关于 cudaMemcpyAsync 函数

2023-11-22

我有一些疑问。

最近在用CUDA做一个程序。

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

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

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

这些都是我的节目安排。

  1. cudaMemcpy( ... , cudaMemcpyHostToDevice)
  2. 内核函数(只有将必要的数据复制到GPU全局内存时才能完成内核函数)
  3. cudaMemcpy( ... , cudaMemcpyDeviceToHost)
  4. 重复1~3步骤1000次(对于另一个数据(向量))

但我想减少处理时间。

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

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

但我的程序正在使用 std::map,所以我无法将此 std::map 数据固定到内存中。

因此,我没有使用它,而是制作了一个缓冲区数组类型的固定内存,并且该缓冲区始终可以处理复制向量的所有情况。

最后我的程序就这样运行了。

  1. Memcpy(使用循环将数据从 std::map 复制到缓冲区,直到将整个数据复制到缓冲区)
  2. cudaMemcpyAsync( ... , cudaMemcpyHostToDevice)
  3. kernel(只有当整个数据复制到GPU全局内存时才能执行内核函数)
  4. cudaMemcpyAsync( ... , cudaMemcpyDeviceToHost)
  5. 重复1~4步骤1000次(对于另一个数据(向量))

我的程序变得比之前的情况快得多。

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

我尝试以类似的方式制作另一个程序。

  1. Memcpy(仅针对一个向量将数据从 std::map 复制到缓冲区)
  2. cudaMemcpyAsync( ... , cudaMemcpyHostToDevice)
  3. 循环1~2,直到全部数据复制到GPU全局内存
  4. kernel(只有当必要的数据复制到GPU全局内存时才能执行内核函数)
  5. cudaMemcpyAsync( ... , cudaMemcpyDeviceToHost)
  6. 重复 1~5 步骤 1000 次(对于另一个数据(向量))

该方法比上面讨论的方法快约 10%。

但我不知道为什么。

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

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

抱歉我的问题很长,但我真的很想知道为什么。

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


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

正如您所看到和演示的,主机活动和数据复制或内核活动可以以相对简单的方式相互重叠:内核启动立即返回到主机,cudaMemcpyAsync 也是如此。然而,为了获得数据复制和内核活动之间的最佳重叠机会,有必要使用一些额外的概念。为了获得最佳重叠机会,我们需要:

  1. 固定的主机内存缓冲区,例如通过 cudaHostAlloc()
  2. 使用 cuda 流来分离各种类型的活动(数据复制和内核计算)
  3. 使用 cudaMemcpyAsync (而不是 cudaMemcpy)

当然,你的工作也需要以可分离的方式分解。这通常意味着,如果您的内核正在执行特定功能,您可能需要多次调用该内核,以便每次调用都可以处理单独的数据。例如,这允许我们在第一次内核调用正在处理数据块 A 时将数据块 B 复制到设备。这样我们就有机会将数据块 B 的副本与数据块 A 的内核处理重叠。

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

  1. 它可以在任何流中发出(它需要一个流参数)
  2. 通常,它将控制权返回给主机立即地(就像内核调用一样)而不是等待数据复制完成。

第 1 项是必要的功能,以便数据复制可以与内核计算重叠。第 2 项是必要的功能,以便数据复制可以与主机活动重叠。

尽管复制/计算重叠的概念非常简单,但在实践中实现需要一些工作。如需其他参考,请参阅:

  1. 重叠复制/计算部分CUDA 最佳实践指南。
  2. 示例代码显示复制/计算重叠的基本实现.
  3. 显示完整的示例代码多/并发内核复制/计算重叠场景.

请注意,上面的一些讨论是基于具有计算能力 2.0 或更高的设备(例如并发内核)。此外,不同的设备可能有 1 个或 2 个复制引擎,这意味着同时复制到设备并复制从设备仅在某些设备上可行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于 cudaMemcpyAsync 函数 的相关文章

  • 无法在 CUDA 中执行设备内核

    我正在尝试在全局内核中调用设备内核 我的全局内核是矩阵乘法 我的设备内核正在查找乘积矩阵每列中的最大值和索引 以下是代码 device void MaxFunction float Pd float max int x threadIdx
  • Cuda 6.5 找不到 - libGLU。 (在 ubuntu 14.04 64 位上)

    我已经在我的ubuntu上安装了cuda 6 5 我的显卡是 GTX titan 当我想要制作 cuda 样本之一时 模拟 粒子 我收到这条消息 gt gt gt WARNING libGLU so not found refer to C
  • 尝试构建我的 CUDA 程序时出现错误 MSB4062

    当我尝试构建我的第一个 GPU 程序时 出现以下错误 有什么建议可能会出什么问题吗 错误 1 错误 MSB4062 Nvda Build CudaTasks SanitizePaths 任务 无法从程序集 C Program 加载 文件 M
  • 如何在cmake中添加cuda源代码的定义

    我使用的是 Visual Studio 2013 Windows 10 CMake 3 5 1 一切都可以使用标准 C 正确编译 例如 CMakeLists txt project Test add definitions D WINDOW
  • 有没有一种有效的方法来优化我的序列化代码?

    这个问题缺乏细节 因此 我决定创建另一个问题而不是编辑这个问题 新问题在这里 我可以并行化我的代码吗 还是不值得 https stackoverflow com questions 17937438 can i parallelize my
  • __device__ __constant__ 常量

    有什么区别吗 在 CUDA 程序中定义设备常量的最佳方法是什么 在 C 主机 设备程序中 如果我想将常量定义在设备常量内存中 我可以这样做 device constant float a 5 constant float a 5 问题 1
  • CUDA、NPP 滤波器

    CUDA NPP 库支持使用 nppiFilter 8u C1R 命令过滤图像 但不断出现错误 我可以毫无问题地启动并运行 boxFilterNPP 示例代码 eStatusNPP nppiFilterBox 8u C1R oDeviceS
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • 内联 PTX 汇编代码强大吗?

    我看到一些代码示例 人们在 C 代码中使用内联 PTX 汇编代码 CUDA工具包中的文档提到PTX很强大 为什么会这样呢 如果我们在 C 代码中使用这样的代码 我们会得到什么好处 内联 PTX 使您可以访问未通过 CUDA 内在函数公开的指
  • “gld/st_throughput”和“dram_read/write_throughput”指标之间有什么区别?

    在 CUDA 可视化分析器版本 5 中 我知道 gld st requested throughput 是应用程序请求的内存吞吐量 然而 当我试图找到硬件的实际吞吐量时 我很困惑 因为有两对似乎合格的指标 它们是 gld st throug
  • cuda-gdb 错误消息

    我尝试使用 cuda gdb 调试我的 CUDA 应用程序 但遇到了一些奇怪的错误 我设置了选项 g G O0构建我的应用程序 我可以在没有 cuda gdb 的情况下运行我的程序 但没有得到正确的结果 因此我决定使用 cuda gdb 但
  • CUDA:获取数组中的最大值及其索引

    我有几个块 每个块在整数数组的单独部分上执行 举个例子 块一从 array 0 到 array 9 块二从 array 10 到 array 20 我可以获得每个块的数组最大值的索引的最佳方法是什么 示例块一 a 0 到 a 10 具有以下
  • CUDA 5.0错误LNK2001:cuda方法无法解析的外部符号

    我的链接器有错误 1 gt ManifestResourceCompile 1 gt All outputs are up to date 1 gt kernel cu obj error LNK2001 unresolved extern
  • OpenCV 2.4.3rc 和 CUDA 4.2:“OpenCV 错误:没有 GPU 支持”

    我在这张专辑中上传了几张截图 https i stack imgur com TELST jpg https i stack imgur com TELST jpg 我正在尝试在 Visual Studio 2008 中的 OpenCV 中
  • CUDA Thrust 库中counting_iterators 的用途和用法

    我很难理解counting iterator在 CUDA 的推力库中 它的目的是什么以及如何使用 它在其他编程语言 例如 C 中也可用吗 计数迭代器只是一个迭代器 它从每次迭代器递增时前进的序列中返回下一个值 最简单的例子是这样的 incl
  • 摆脱异步 cuda 流执行期间的忙等待

    我正在寻找一种方法 如何摆脱以下代码中主机线程中的忙等待 不要复制该代码 它仅显示我的问题的想法 它有许多基本错误 cudaStream t steams S N for int i 0 i lt S N i cudaStreamCreat
  • GPU上动态分配内存

    是否可以在内核内的 GPU 全局内存上动态分配内存 我不知道我的答案有多大 因此我需要一种方法为答案的每个部分分配内存 CUDA 4 0 允许我们使用 RAM 这是一个好主意还是会降低速度 可以在内核中使用 malloc 检查以下内容 摘自
  • 我们如何在每次运行时使用不同的种子在 CUDA C 中生成随机数?

    我正在研究一个随机过程 我想在每次运行程序时在 CUDA 内核中生成不同的系列随机数 这类似于我们在 C 中声明 种子 时间 空 接下来是 srand 种子 和兰特 我可以通过内核将种子从主机传递到设备 但是 这样做的问题是我必须将整个种子
  • 对 CUDA 操作进行计时

    我需要计算 CUDA 内核执行的时间 最佳实践指南说我们可以使用事件或标准计时函数 例如clock 在Windows中 我的问题是使用这两个函数给出了完全不同的结果 事实上 与实践中的实际速度相比 事件给出的结果似乎是巨大的 我实际上需要这
  • 如何从C++头文件调用CUDA文件?

    我知道从 c 文件调用 cu 文件的方法 但现在我想从 C 头文件调用 cu 文件 有可能做到吗 如果是这样 我应该如何设置我的项目 请帮忙 这是一个有效的例子 file1 h int hello file2 h include

随机推荐