cudamemcpyasync 和流行为理解

2024-01-04

我有下面所示的简单代码,它什么也不做,只是使用流将一些数据从主机复制到设备。但在运行 nvprof 后我很困惑,因为 cudamemcpyasync 确实是异步的并且对流的理解。

#include <stdio.h>

#define NUM_STREAMS 4
cudaError_t memcpyUsingStreams (float           *fDest,
                                float           *fSrc,
                                int             iBytes,
                                cudaMemcpyKind  eDirection,
                                cudaStream_t    *pCuStream)
{
    int             iIndex = 0 ;
    cudaError_t     cuError = cudaSuccess ;
    int             iOffset = 0 ;

    iOffset = (iBytes / NUM_STREAMS) ;
    /*Creating streams if not present */
    if (NULL == pCuStream)
    {
            pCuStream = (cudaStream_t *) malloc(NUM_STREAMS * sizeof(cudaStream_t));
            for (iIndex = 0 ; iIndex < NUM_STREAMS; iIndex++)
            {
                    cuError = cudaStreamCreate (&pCuStream[iIndex]) ;
            }
    }

    if (cuError != cudaSuccess)
    {
            cuError = cudaMemcpy (fDest, fSrc, iBytes, eDirection) ;
    }
    else
    {
            for (iIndex = 0 ; iIndex < NUM_STREAMS; iIndex++)
            {
                    iOffset = iIndex * iOffset ;
                    cuError = cudaMemcpyAsync (fDest +  iOffset , fSrc + iOffset, iBytes / NUM_STREAMS , eDirection, pCuStream[iIndex]) ;
            }
    }

    if (NULL != pCuStream)
    {
            for (iIndex = 0 ; iIndex < NUM_STREAMS; iIndex++)
            {
                    cuError = cudaStreamDestroy (pCuStream[iIndex]) ;
            }
            free (pCuStream) ;
    }
    return cuError ;
}


int main()
{
    float *hdata = NULL ;
    float *ddata = NULL ;
    int i, j, k, index ;
    cudaStream_t *abc = NULL ;

    hdata = (float *) malloc (sizeof (float) * 256 * 256 * 256) ;

    cudaMalloc ((void **) &ddata, sizeof (float) * 256 * 256 * 256) ;

    for (i=0 ; i< 256 ; i++)
    {
        for (j=0; j< 256; j++)
        {
            for (k=0; k< 256 ; k++)
            {
                index = (((i * 256) + j) * 256) + k;
                hdata [index] = index ;
            }
        }
    }

    memcpyUsingStreams (ddata, hdata, sizeof (float) * 256 * 256 * 256,  cudaMemcpyHostToDevice, abc) ;

    cudaFree (ddata) ;
    free (hdata) ;

    return 0;
}

nvprof 结果如下。

    Start  Duration           Grid Size     Block Size     Regs*    SSMem*    DSMem*      Size  Throughput    Device   Context    Stream  Name
 104.35ms   10.38ms                   -              -         -         -         -   16.78MB    1.62GB/s         0         1         7  [CUDA memcpy HtoD]
 114.73ms   10.41ms                   -              -         -         -         -   16.78MB    1.61GB/s         0         1         8  [CUDA memcpy HtoD]
 125.14ms   10.46ms                   -              -         -         -         -   16.78MB    1.60GB/s         0         1         9  [CUDA memcpy HtoD]
 135.61ms   10.39ms                   -              -         -         -         -   16.78MB    1.61GB/s         0         1        10  [CUDA memcpy HtoD]

所以由于开始时间的原因,我不明白在这里使用流的意义。对我来说它看起来是连续的。请帮助我理解我在这里做错了什么。我正在使用特斯拉 K20c 卡。


将 GPU 连接到系统的 PCI Express 链路只有一个通往卡的通道和一个来自卡的通道。这意味着最多可以有一个 cudaMemcpy(Async) 操作,该操作实际上在每个方向的任何给定时间执行(即最多一个 DtoH 和一个 HtoD)。所有其他 cudaMemcpy(Async) 操作都将排队,等待前面的操作完成。

您不能同时进行同一方向的两项操作。每个方向一次一个。

正如 @JackOLantern 所说,流的主要好处是重叠内存副本和计算,或者允许多个内核同时执行。它也是允许一个 DtoH 副本与一个 HtoD 副本同时运行 http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#concurrent-data-transfers.

由于您的程序执行所有 HtoD 副本,因此它们都会串行执行。每个副本都必须等待其前面的副本完成。

即使同时执行 HtoD 和 DtoH memcopy 也需要具有多个复制引擎的设备;您可以使用 deviceQuery 发现有关您设备的信息。

我还应该指出,要启用并发行为,您应该使用cudaHostAlloc, not malloc,用于主机端缓冲区。

EDIT:上面的答案考虑的是最多有 2 个复制引擎(每个方向一个)的 GPU,并且对于此类 GPU 来说仍然是正确的。然而,存在一些较新的 Pascal 和 Volta 系列成员 GPU,它们具有 2 个以上的复制引擎。在这种情况下,每个方向有 2 个(或更多)复制引擎,理论上可以在该方向上有 2 个(或更多)“飞行中”传输。然而,这不会改变 PCIE(或 NVLink)总线本身的特性。您仍然受到可用带宽的限制,并且在大多数情况下,确切的低级行为(无论此类传输是否显示为“序列化”,或者是否显示为同时运行,但由于共享带宽而需要更长的时间)应该无关紧要。

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

cudamemcpyasync 和流行为理解 的相关文章

  • Ubuntu 11.10/12.04 上的 CUDA“无兼容设备”错误

    一段时间以来 我一直在尝试在我的笔记本电脑上设置 Ubuntu 环境来进行 CUDA 编程 我目前双启动 Windows 8 和 Ubuntu 12 04 并想在 Ubuntu 上安装 CUDA 5 该笔记本电脑配有 GeForce GT
  • 是否可以在设备函数中调用cufft库调用?

    我在主机代码中使用 cuFFT 库调用 它们工作正常 但我想从内核调用 cuFFT 库 早期版本的 CUDA 没有这种支持 但是有了动态并行性 这可能吗 如果有任何关于如何实现这一目标的示例 那就太好了 尽管在 Kepler cc 3 5
  • 用于类型比较的 Boost 静态断言

    以下问题给我编译器错误 我不知道如何正确编写它 struct FalseType enum value false struct TrueType enum value true template
  • 当我有表面声明时,如何为 sm_1X 和 sm_2X 编译 CUDA 程序

    我正在编写一个使用表面 重新采样并写入纹理 来提高性能的库 surface
  • cuda cpu功能-gpu内核重叠

    我在尝试开发以练习 CUDA 的 CUDA 应用程序时遇到并发问题 我想通过使用 cudaMemecpyAsync 和 CUDA 内核的异步行为来共享 GPU 和 CPU 之间的工作 但我无法成功重叠 CPU 执行和 GPU 执行 它与主机
  • cuda 共享内存 - 结果不一致

    我正在尝试并行缩减以对 CUDA 中的数组求和 目前我传递一个数组来存储每个块中元素的总和 这是我的代码 include
  • 传递给 CUDA 的结构中的指针

    我已经搞砸了一段时间了 但似乎无法正确处理 我正在尝试将包含数组的对象复制到 CUDA 设备内存中 然后再复制回来 但当我遇到它时我会跨过那座桥 struct MyData float data int dataLen void copyT
  • MPI+CUDA 与纯 MPI 相比有何优势?

    加速应用程序的常用方法是使用 MPI 或更高级别的库 例如在幕后使用 MPI 的 PETSc 并行化应用程序 然而 现在每个人似乎都对使用 CUDA 来并行化他们的应用程序或使用 MPI 和 CUDA 的混合来解决更雄心勃勃 更大的问题感兴
  • 如何在 Visual Studio 2010 中设置 CUDA 编译器标志?

    经过坚持不懈的得到error identifier atomicAdd is undefined 我找到了编译的解决方案 arch sm 20旗帜 但是如何在 VS 2010 中传递这个编译器标志呢 我已经尝试过如下Project gt P
  • 运行时 API 应用程序中的 cuda 上下文创建和资源关联

    我想了解如何在 cuda 运行时 API 应用程序中创建 cuda 上下文并与内核关联 我知道这是由驱动程序 API 在幕后完成的 但我想了解一下创作的时间线 首先 我知道 cudaRegisterFatBinary 是第一个 cuda a
  • CUDA Visual Studio 2010 Express 构建错误

    我正在尝试在 64 位 Windows 7 上使用 Visual Studio 2010 Express 在 Windows 上开始 CUDA 编程 我花了一段时间来设置环境 然后我刚刚编写了我的第一个程序 helloWorld cu 目前
  • CUDA 估计 2D 网格数据的每块线程数和块数

    首先我要说的是 我已经仔细阅读了所有类似的问题 确定每个块的线程和每个网格的块 https stackoverflow com questions 4391162 cuda determining threads per block blo
  • 如何在 CUDA 中执行多个矩阵乘法?

    我有一个方阵数组int M 10 以便M i 定位第一个元素i th 矩阵 我想将所有矩阵相乘M i 通过另一个矩阵N 这样我就收到了方阵数组int P 10 作为输出 我看到有不同的可能性 分配不同元素的计算M i 到不同的线程 例如 我
  • 设置最大 CUDA 资源

    我想知道是否可以设置 CUDA 应用程序的最大 GPU 资源 例如 如果我有一个 4GB GPU 但希望给定的应用程序只能访问 2GB 如果它尝试分配更多 就会失败 理想情况下 这可以在进程级别或 CUDA 上下文级别上设置 不 目前没有允
  • 加速Cuda程序

    要更改哪一部分来加速此代码 代码到底在做什么 global void mat Matrix a Matrix b int tempData new int 2 tempData 0 threadIdx x tempData 1 blockI
  • 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 矩阵加法时序,按行与按行比较按栏目

    我目前正在学习 CUDA 并正在做一些练习 其中之一是实现以 3 种不同方式添加矩阵的内核 每个元素 1 个线程 每行 1 个线程和每列 1 个线程 矩阵是方阵 并被实现为一维向量 我只需用以下命令对其进行索引 A N row col 直觉
  • 在 cudaFree() 之前需要 cudaDeviceSynchronize() 吗?

    CUDA 版本 10 1 帕斯卡 GPU 所有命令都发送到默认流 void ptr cudaMalloc ptr launch kernel lt lt lt gt gt gt ptr cudaDeviceSynchronize Is th
  • CUDA、NPP 滤波器

    CUDA NPP 库支持使用 nppiFilter 8u C1R 命令过滤图像 但不断出现错误 我可以毫无问题地启动并运行 boxFilterNPP 示例代码 eStatusNPP nppiFilterBox 8u C1R oDeviceS
  • cudaMemcpy() 与 cudaMemcpyFromSymbol()

    我试图找出原因cudaMemcpyFromSymbol 存在 似乎 symbol func 可以做的所有事情 nonSymbol cmd 也可以做 symbol func 似乎可以轻松移动数组或索引的一部分 但这也可以使用 nonSymbo

随机推荐

  • 如何在保存 Sitecore 项目时显示弹出窗口?

    保存 Sitecore 项目时 我尝试显示一个弹出窗口以与用户交互 根据他们更改的数据 我可能会显示一系列 1 或 2 个弹出窗口 询问他们是否要继续 我已经弄清楚如何利用 OnItemSaving 管道 这很简单 我不知道如何显示弹出窗口
  • 保留提交的JSP表单数据

    我有一个网络表单 JSP 它将数据提交到托管在不同服务器上的不同应用程序 提交表单数据后 该应用程序重定向回同一 JSP 页面 现在 我想保存输入的数据 以网络形式保留提交的数据有哪些不同的方法 我不喜欢将数据存储在数据库或任何文件中 PS
  • 当我在终端中调用 Emacs 错误“无法初始化颜色列表解档器”时

    我刚刚在 MacBook Pro 上安装了 emacs 但是当我在终端中输入 emacs 时 出现以下错误 Emacs x86 64 10 10 5647 247335 无法初始化颜色列表解档器 错误域 NSCocoaErrorDomain
  • AngularJS ui-router $state.go('^') 仅更改地址栏中的 URL,但不加载控制器

    我正在尝试使用 angularjs 创建一个 Todo App ui router 它有 2 列 第一栏 待办事项列表 第 2 列 Todo 详细信息或 Todo 编辑表单 在保存待办事项后的编辑和创建控制器中 我想重新加载列表以显示适当的
  • portaudio.h:没有这样的文件或目录

    我在 ubuntu 16 04 中尝试使用 pip3 安装 pyaudio 时出现以下错误 Collecting pyaudio Downloading PyAudio 0 2 11 tar gz Installing collected
  • python 3.4 谷歌浏览器历史

    我真的被我想做的事情困住了 我想制作一个非常简单的脚本来显示 Google Chrome 的历史记录 当我使用以下代码行时 f open C Users joey AppData Local Google Chrome User Data
  • 使用 ckeditor 整理 html

    您好 我在 ckeditor 方面遇到了一个小问题 基本上我需要让编辑器运行它的 html 清理命令 有什么办法可以做到这一点吗 目前 在我在源代码中输入一些内容然后按保存后 它似乎没有运行我希望它像在 正常 编辑器视图中那样整理 html
  • 给定一个 Android 音乐播放列表名称,如何找到播放列表中的歌曲?

    可以通过查询找到播放列表名称MediaStore Audio Playlists EXTERNAL CONTENT URI然后看看MediaStore Audio PlaylistsColumns NAME柱子 还有一个数据列 MediaS
  • REST Auth 的 Cocoa Base 64 实现

    我可以使用干净 有效的 Base64 实现来通过 HTTP 对 REST 协议进行授权 有人可以帮助我或为我指明方向吗 Thanks 您应该完全没有必要这样做 在较高的层面上 Cocoa 提供了 NSURLConnection 来进行 HT
  • 使用 dlsym 加载已命名的未导出符号?

    是否可以使用以下方式从框架加载命名的未导出符号dlsym 我尝试导入的符号有一个在框架内引用的名称 这是我需要调用的函数 我试着像往常一样做dlopen dlsym方式 但是当我尝试加载未导出的符号时 dlsym返回一个NULL指针 dls
  • 蓝兹编程

    我正在使用 USB 蓝牙适配器在 Raspberry Pi 上使用 BlueZ 进行编程 我需要能够以编程方式连接到 Arduino BT 问题是 Arduino 的蓝牙模块仍在使用传统配对 因此每当我尝试打开设备的套接字时 我都会收到Pe
  • 如何在Python中计算mod b?

    Python中有取模函数吗math图书馆 Isn t 15 4 3 但15 mod 4是1 对吗 有的是 符号 它不仅仅是求余数 而是求模运算
  • 尽管提供了 Twitter Api,回调 URL 仍未获得批准

    在 Twitter 控制台中 我有一个来自 firebase 的回调 url 链接 然而 当我尝试使用 twitter 进行身份验证时 出现错误 Request failed forbidden 403 UserInfo NSLocaliz
  • Gradle eclipse classpath - 在快照和项目依赖之间切换

    我们的 Java 项目中有多个模块 每个模块都会将 SNAPSHOT jar 文件发布到 Nexus 存储库 所有子模块都直接依赖于 SNAPSHOT jar 文件 在开发过程中 我们希望依赖 Eclipse 项目而不是 SNAPSHOT
  • boost::flat_map 及其与 map 和 unordered_map 相比的性能

    编程中的常识是 由于缓存命中 内存局部性可以大大提高性能 我最近发现boost flat map这是基于矢量的地图实现 它似乎并不像典型的那样受欢迎map unordered map所以我没能找到任何性能比较 它的比较如何 它的最佳用例是什
  • 递归地从 XML 中删除空节点

    我想从 XML 元素中删除空节点 该 xml 是由供应商生成的 我无法控制 xml 的生成 但由于 XML 几乎没有空节点 我需要递归删除这些空节点 这个 xml 是从 OMElement 获取的 我使用 XMLUtils 1 从这个对象获
  • 在 Java 中转换 StAX 源

    我有一些代码 例如 XMLInputFactory xif XMLInputFactory newInstance TransformerFactory tf TransformerFactory newInstance org apach
  • 使用 ffmpeg 合并视频

    我尝试过这个命令 ffmpeg i concat 10 mov 11 mov codec copy out mov输出文件 out mov 仅显示第一部电影 10 mov 中的内容 谷歌搜索了几个小时并尝试了很多东西但没有任何效果 我希望在
  • spring boot cloud eureka windows 10 eureka 在最新的 docker 升级后返回 host.docker.internal 作为客户端主机名

    Spring Boot Cloud Disovery 问题 在 Windows 10 上进行 docker 升级后 Eureka 主机名出现问题 注意 docker 不托管 spring 服务 仅托管 mariadb rabbitmq 和
  • cudamemcpyasync 和流行为理解

    我有下面所示的简单代码 它什么也不做 只是使用流将一些数据从主机复制到设备 但在运行 nvprof 后我很困惑 因为 cudamemcpyasync 确实是异步的并且对流的理解 include