CUDA流任务并行

2023-11-20

       CUDA流表示一个GPU操作队列,并且该队列中的操作将以指定的顺序执行。可以将每个流视为GPU的一个任务,并且这些任务可以并行执行,即相同流顺序执行,不同流并行执行;不同流并行执行时不同流所要执行的任务要没有依赖关系;当不手动创建流时,cuda将会默认一个流操作。

       在硬件选择上,这里有一个概念,支持设备重叠功能,支持设备重叠功能的 GPU 能够在执行一个 CUDA C 核函数的同时,还能在设备和主机之间执行复制操作;这在流并行过程中很重要,我们假设有流A和流B,设备重叠就会允许流A在复制过程中同时流B进行核函数计算,这会大大加快速度;

cudaDeviceProp   prop;
int  whichDevice;
cudaGetDevice(&whichDevice);
cudaGetDevice(&prop, whichDevice);
if(prop.deviceOverlap){
   std::cout<<"the device  will handle overlaps"<<std::endl;
}

        我们知道cudaMemcpy与CPU操作是同步的,为了实现设备重叠,cuda提供了cudaMemcpyAsync用于数据拷贝操作,它是异步的,不会等待复制完成就会执行程序的下一步;

        但注意,cudaMemcpyAsync仅对分页锁定的主存储器有效,如果传入指向可分页存储器的指针,那么将返回一个错误;

        页锁定的主机内存由cudaHostAlloc()分配。页锁定的主机内存也称为固定内存或不可分页内存,它的重要属性就是:操作系统将不会对这块内存分页并交换到磁盘上,从而确保了该内存始终驻留在物理内存中。因此,操作系统能够安全的使用应用程序访问该内存的物理地址,因为这块内存将不会被破坏或者重新定位。事实上,当使用可分页内存进行复制时,复制操作将执行两遍,第一遍从可分页内存复制到一块“临时的”页锁定内存,然后再从这个页锁定内存复制到GPU上。因此,当在GPU和主机间复制数据时,这种差异会使也锁定主机内存的性能比标准可分页内存的性能要高大约2倍。然而,我们也不能进入另一个极端:查找每一个malloc调用并将其替换为cudaHostAlloc调用。固定内存是一把双刃剑,当使用固定内存是,你将失去虚拟内存的所用功能。特别是,应用程序中使用每个页锁定内存时都需要分配物理内存,因为这些内存不能交换到磁盘上。这意味着,与使用标准的malloc调用相比,系统将更快的耗尽内存(概念选自《GPU高性能编程CUDA实战》)

        从上,页锁定内存不仅在主机与设备之间复制数据快,而且在流并行中扮演着重要的作用;

多个CUDA流宽度优先而非深度优先      

     深度优先就是程序按顺序把一个流的操作添加之后再添加下一个流操作,如下:

for(int i =0; i< FULL_DATA_SIZE; i+= 2*N){
    cudaMemcpyAsync(dev_a0, host_a + i, N*sizeof(int),cudaMemcpyHostToDevice, stream0);
    cudamemcpyAsync(dev_b0, host_b + i, N*sizeof(int),cudaMemcpyHostToDevice, stream0);
    kernel<<<N/256,256,0,stream0>>>(dev_a0, dev_b0,dev_c0);
    cudaMemcpyAsync(host_c + i, dev_c0, N*sizeof(int),cudaMemcpyDeviceToHost, stream0);
    cudaMemcpyAsync(dev_a1, host_a + i + N, N*sizeof(int),cudaMemcpyHostToDevice, stream1);
    cudamemcpyAsync(dev_b1, host_b + i + N, N*sizeof(int),cudaMemcpyHostToDevice, stream1);
    kernel<<<N/256,256,0,stream1>>>(dev_a1, dev_b1,dev_c1);
    cudaMemcpyAsync(host_c + i + N, dev_c1, N*sizeof(int),cudaMemcpyDeviceToHost, stream1);
}

先添加stream0再添加stream1操作,按流模型来说,因为这里的拷贝操作还是核函数都是异步的,stream0和stream1并行计算,速度应该比用单个流提了不少,但是却不然,为什么呢?这就涉及到GPU的硬件调度:

 在硬件中并没有流的概念,而是包含一个或多个引擎(主机到设备,设备到主机可能是分开的两个引擎)来执行内存复制操作,以及一个引擎来执行核函数。这些引擎彼此独立的对操作进行排队;

也就是说内存复制和核函数在GPU上是不同的引擎在执行,那么在同一流上核函数和复制操作相邻时,就会发生一个现象:两个操作在不同的引擎上,但是流模型又要保证同一流上两个程序执行的先后顺序,那么怎么办?cuda驱动程序为了保证硬件的执行单元不破坏流之间的依赖性,将前一个操作阻塞,等待完成后,再继续执行后一个

所以为了高效利用CUDA流,提出了流宽度优先的概念,即将两个流之间的操作交叉添加:

for(int i =0; i< FULL_DATA_SIZE; i+= 2*N){
    cudaMemcpyAsync(dev_a0, host_a + i, N*sizeof(int),cudaMemcpyHostToDevice, stream0);
    cudaMemcpyAsync(dev_a1, host_a + i + N, N*sizeof(int),cudaMemcpyHostToDevice, stream1);
    cudamemcpyAsync(dev_b0, host_b + i, N*sizeof(int),cudaMemcpyHostToDevice, stream0);
    cudamemcpyAsync(dev_b1, host_b + i + N, N*sizeof(int),cudaMemcpyHostToDevice, stream1);
    kernel<<<N/256,256,0,stream0>>>(dev_a0, dev_b0,dev_c0);
    kernel<<<N/256,256,0,stream1>>>(dev_a1, dev_b1,dev_c1);
    cudaMemcpyAsync(host_c + i, dev_c0, N*sizeof(int),cudaMemcpyDeviceToHost, stream0);
    cudaMemcpyAsync(host_c + i + N, dev_c1, N*sizeof(int),cudaMemcpyDeviceToHost, stream1);
}

   http://www.mamicode.com/info-detail-1770665.html  

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

CUDA流任务并行 的相关文章

随机推荐

  • QT二维码生成和解析&Demo

    目录 一 前言 二 相关知识 三 效果展示 四 主要源码简析 五 源码Demo 一 前言 本文主要介绍二维码生成和解析的相关知识和例程 二 相关知识 二维码生成 主要用到的是开源的二维码QR码编码库qrencode 需要使用到的库文件为下面
  • 七段码(建图+搜索+并查集)

    思路 step1 邻接表建图 相邻为1 不相邻为0 题目就等价为在图中求连通子图的个数 step2 深度搜索每条边 并存储下来 step3 对选择的边用并查集保存下来 然后看father i i的个数 等于1 表示连通 否则表示不连通 易错
  • 【SpringCloud】整合Consul+OpenFeign实现微服务+负载均衡(下)

    一 代码 由于篇幅有限 代码见上一篇文章 https blog csdn net forest long article details 129287941 分别启动Consul Service provider Service consu
  • QString::arg() 函数

    例 setWindowTitle tr 1 2 arg shownName arg tr Spreadsheet QString arg 函数用第一个arg 调用会替换 1 第2个arg 调用会替换 2 上面的例子其实可以写作 setWin
  • H5.小程序都适用的瀑布流做法

    1 HTML代码 div style display flex padding top 0 2rem div class card main left div div
  • 常用设计模式及例子(五)

    13 策略模式 strategy 策略模式定义了一系列算法 并将每个算法封装起来 使他们可以相互替换 且算法的变化不会影响到使用算法的客户 需要设计一个接口 为一系列实现类提供统一的方法 多个实现类实现该接口 设计一个抽象类 可有可无 属于
  • java实现音频文件的播放

    实现思路 1 首先获取音频文件的地址 然后通过IO流读取音频文件 加缓冲区 实现Player类的对象 2 Player类主要用于播放器的初始化 以及通过它来实现一些音视频文件的播放 这个类需要手动去网上下载 然后添加路径到我们Eclipse
  • 关于.net连接字符串

    今天在看David Sceppa的 ADO NET 技术内幕 里面对 net连接字符串的描述很简单 让人一看就懂 一看能理解 连接字符串是什么 连接字符串是由一系列用分号隔开的 name value 组合 strConn Setting1
  • centos 通过yum安装nginx

    通过yum安装nginx 菜鸟一枚 不知道为什么nginx这个东西不在初始话的yum镜像里面 也不想通过编译方式安装nginx 看着闹心 那么怎么通过yum方式安装nginx呢 添加nginx包镜像地址 rpm ivh http nginx
  • python---函数名的使用

    函数名的多种用法 函数名当作变量名赋值 函数名当作函数的实参 函数名当作函数的返回值 函数名当作容器类型的元素 函数名当作变量名赋值 def index print from function index print index res i
  • android调用系统指纹设置页面录入指纹

    在做指纹登录时 有时候会遇到设备并未录入指纹 需要提示用户去开启 如果需要自动跳转到系统的指纹设置页面 录入指纹 那就需要调用系统组件 由于google加入指纹支持是在6 0 而国内很多厂商很早便加入了指纹支持 所以在这方面碎片化很严重 需
  • 火影手游为什么服务器维护,火影忍者手游安装失败解决方法 游戏闪退进不去怎么办...

    本文4399阿尔法将告诉大家火影忍者手游安装失败的原因以及解决方法 还会告诉大家游戏闪退进不去怎么办等等 下面就跟着小编一起来看看吧 gt gt gt gt gt 更多游戏攻略 进入4399火影忍者手游专区 lt lt lt lt lt 问
  • 65nm芯片流片费用_每年流片超40款客户芯片,国内第一的IP供应商芯原科创板上市获受理...

    文 Lee 图源 网络 集微网消息 9月20日 上交所受理了芯原微电子 上海 股份有限公司 以下简称 芯原 科创板上市申请 芯原选择的上市标准为 科创板上市规则 2 1 2中的第 四 项 预计市值不低于人民币30亿元 且最近一年营业收入不低
  • vscode配置clangd和clang-format

    vscode安装和配置 如何安装和配置vscode以搭建c 开发环境 可以查看我的另一篇博客 Windows上最轻量的vscode C 开发环境搭建 在这篇博客中 详细介绍了如何安装vscode以及应该安装哪些插件 这里不再赘述 vscod
  • 第14届蓝桥杯C++B组省赛

    文章目录 A 日期统计 B 01 串的熵 C 冶炼金属 D 飞机降落 E 接龙数列 F 岛屿个数 G 子串简写 H 整数删除 I 景区导游 J 砍树 今年比去年难好多 Update 2023 4 10 反转了 炼金二分没写错 可以AC了 U
  • 1051. 复数乘法 (15)

    复数可以写成 A Bi 的常规形式 其中A是实部 B是虚部 i是虚数单位 满足i2 1 也可以写成极坐标下的指数形式 R e Pi 其中R是复数模 P是辐角 i是虚数单位 其等价于三角形式 R cos P isin P 现给定两个复数的R和
  • 【机器学习】【逻辑回归】Logistic函数/Sigmoid函数的详细公式推导

    sigmoid函数的数学公式 sigmoid函数的因变量x取值范围是 到 但是sigmoid函数的值域是 0 1 不管x取什么值其对应的sigmoid函数值一定会落到 0 1 范围内 漂亮的logistic 曲线 sigmoid函数对应的图
  • Python timeit模块的使用

    Python timeit模块的使用 Python 中的 timeit 模块可以用来测试一段代码的执行耗时 如一个变量赋值语句的执行时间 一个函数的运行时间等 timeit 模块是 Python 标准库中的模块 无需安装 直接导入就可以使用
  • java readvalue_Java XmlMapper.readValue方法代碼示例

    本文整理匯總了Java中com fasterxml jackson dataformat xml XmlMapper readValue方法的典型用法代碼示例 如果您正苦於以下問題 Java XmlMapper readValue方法的具體
  • CUDA流任务并行

    CUDA流表示一个GPU操作队列 并且该队列中的操作将以指定的顺序执行 可以将每个流视为GPU的一个任务 并且这些任务可以并行执行 即相同流顺序执行 不同流并行执行 不同流并行执行时不同流所要执行的任务要没有依赖关系 当不手动创建流时 cu