目录

1、CUDA 中的异步命令

2、默认流

3、Multistream多流示例


异构计算是指高效地使用系统中的所有处理器,包括 CPU 和 GPU 。为此,应用程序必须在多个处理器上并发执行函数。 CUDA 应用程序通过在 streams 中执行异步命令来管理并发性,这些命令是按顺序执行的。不同的流可以并发地执行它们的命令,也可以彼此无序地执行它们的命令。在不指定流的情况下执行异步 CUDA 命令时,运行时使用默认流。在 CUDA 7 之前,默认流是一个特殊流,它隐式地与设备上的所有其他流同步。CUDA7引入了大量强大的新功能,包括一个新的选项,可以为每个主机线程使用独立的默认流,这避免了传统默认流的序列化。本文将展示如何在 CUDA 程序中简化实现内核和数据副本之间的并发。

1、CUDA 中的异步命令

如 CUDA C 编程指南所述,异步命令在设备完成请求的任务之前将控制权返回给调用主机线程(它们是非阻塞的)。这些命令是:

  • 内核启动;
  • 存储器在两个地址之间复制到同一设备存储器;
  • 从主机到设备的 64kb 或更少内存块的内存拷贝;
  • 由后缀为 Async 的函数执行的内存复制;
  • 内存设置函数调用。

为内核启动或主机设备内存复制指定流是可选的;可以调用 CUDA 命令而不指定流(或通过将 stream 参数设置为零)。下面两行代码都在默认流上启动内核。

  kernel<<< blocks, threads, bytes >>>();    // default streamkernel<<< blocks, threads, bytes, 0 >>>(); // stream 0

2、默认流

在并发性对性能不重要的情况下,默认流很有用。在 CUDA 7 之前,每个设备都有一个用于所有主机线程的默认流,这会导致隐式同步。正如 CUDA C 编程指南中的“隐式同步”一节所述,如果主机线程向它们之间的默认流发出任何 CUDA 命令,来自不同流的两个命令就不能并发运行。CUDA 7 引入了一个新选项, 每线程默认流 ,它有两个效果。首先,它为每个主机线程提供自己的默认流。这意味着不同主机线程向默认流发出的命令可以并发运行。其次,这些默认流是常规流。这意味着默认流中的命令可以与非默认流中的命令同时运行。要在 nvcc 7 及更高版本中启用每线程默认流,可以在包含 CUDA 头( cuda.h 或 cuda_runtime.h )之前,使用 nvcc 命令行选项 CUDA 或 #define 编译 CUDA_API_PER_THREAD_DEFAULT_STREAM 预处理器宏。需要注意的是:当代码由 nvcc 编译时,不能使用 #define CUDA_API_PER_THREAD_DEFAULT_STREAM 在. cu 文件中启用此行为,因为 nvcc 在翻译单元的顶部隐式包含了 cuda_runtime.h 。

3、Multistream多流示例

看一个小例子。下面的代码简单地在八个流上启动一个简单内核的八个副本。只为每个网格启动一个线程块,这样就有足够的资源同时运行多个线程块。作为遗留默认流如何导致序列化的示例,在默认流上添加不起作用的虚拟内核启动

const int N = 1 << 20;__global__ void kernel(float *x, int n)
{int tid = threadIdx.x + blockIdx.x * blockDim.x;for (int i = tid; i < n; i += blockDim.x * gridDim.x) {x[i] = sqrt(pow(3.14159,i));}
}int main()
{const int num_streams = 8;cudaStream_t streams[num_streams];float *data[num_streams];for (int i = 0; i < num_streams; i++) {cudaStreamCreate(&streams[i]);cudaMalloc(&data[i], N * sizeof(float));// launch one worker kernel per streamkernel<<<1, 64, 0, streams[i]>>>(data[i], N);// launch a dummy kernel on the default streamkernel<<<1, 1>>>(0, 0);}cudaDeviceReset();return 0;
}

首先让检查遗留行为,通过不带选项的编译:

nvcc ./stream_test.cu -o stream_legacy

可以在 NVIDIA visualprofiler ( nvvp )中运行该程序,以获得显示所有流和内核启动的时间轴。图 1 显示了 Macbook Pro 上生成的内核时间线,该 Macbook Pro 带有 NVIDIA GeForce GT 750M (一台开普勒 GPU )。可以看到默认流上虚拟内核的非常小的条,以及它们如何导致所有其他流序列化。

一个简单的多流示例在将任何交错内核发送到默认流时不会实现并发

现在尝试新的每线程默认流。

nvcc --default-stream per-thread ./stream_test.cu -o stream_per-thread

图 2 显示了来自 nvvp 的结果。在这里可以看到九个流之间的完全并发:默认流(在本例中映射到流 14 )和创建的其他八个流。请注意,虚拟内核运行得如此之快,以至于很难看到在这个图像中默认流上有八个调用。

图 2 :使用新的每线程默认流选项的多流示例,它支持完全并发执行

在为并发进行编程时,还需要记住以下几点。

  • 记住:对于每线程的默认流,每个线程中的默认流的行为与常规流相同,只要同步和并发就可以了。对于传统的默认流,这是不正确的。
  • --default-stream 选项是按编译单元应用的,确保将其应用于所有需要它的 nvcc 命令行。
  • cudaDeviceSynchronize() 继续同步设备上的所有内容,甚至使用新的每线程默认流选项。如果只想同步单个流,请使用 cudaStreamSynchronize(cudaStream_t stream) ,如的第二个示例所示。
  • 从 CUDA 7 开始,还可以使用句柄 cudaStreamPerThread 显式地访问每线程的默认流,也可以使用句柄 cudaStreamLegacy 访问旧的默认流。请注意, cudaStreamLegacy 仍然隐式地与每个线程的默认流同步,如果碰巧在一个程序中混合使用它们。
  • 可以通过将 cudaStreamCreate() 标志传递给 cudaStreamCreate() 来创建不与传统默认流同步的非堵塞流 。

参考文献:

CUDA 7 Stream流简化并发性 - 吴建明wujianming - 博客园

CUDA Stream流并发性相关推荐

  1. CUDA 7 流并发性优化

    CUDA 7 流并发性优化 异构计算是指高效地使用系统中的所有处理器,包括 CPU 和 GPU .为此,应用程序必须在多个处理器上并发执行函数. CUDA 应用程序通过在 streams 中执行异步命 ...

  2. Cuda Stream流 分析

    Cuda Stream流分析 Stream 一般来说,cuda c并行性表现在下面两个层面上: • Kernel level • Grid level Stream和event简介 Cuda stre ...

  3. CUDA 7流简化并发

    CUDA 7流简化并发 异构计算是指有效使用系统中的所有处理器,包括CPU和GPU.为此,应用程序必须在多个处理器上同时执行功能.CUDA应用程序通过在流(按顺序执行的命令序列)中,执行异步命令来管理 ...

  4. CUDA 7 Stream流简化并发性

    CUDA 7 Stream流简化并发性 异构计算是指高效地使用系统中的所有处理器,包括 CPU 和 GPU .为此,应用程序必须在多个处理器上并发执行函数. CUDA 应用程序通过在 streams ...

  5. stream 流的并发

    jdk  8  以后增加stream   接口: stream 流的 各个方法使用如下: package Test01;import java.util.ArrayList; import java. ...

  6. 【Stream】java8新特性Stream流总结

    一.什么是stream 在 java8 中增加了一个新的抽象接口 Stream API,使用 Stream 操作集合类似于使用 SQL 语句数据库查找数据类似,提供直观的方法进行操作. Stream ...

  7. Java8新特性——Stream流:不同于IO流的流,操作集合数据

    文章目录 Stream流 1.认识Stream流(源码说明) 1.1.Stream流和Collection的区别 1.2.流的获取方式 1.3.流操作和管道 1.4.并行性 1.5.不干扰内政 1.6 ...

  8. Java8 Stream流递归,几行代码搞定遍历树形结构

    欢迎关注方志朋的博客,回复"666"获面试宝典 可能平常会遇到一些需求,比如构建菜单,构建树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中 ...

  9. 【Java10】lambda表达式(函数式编程),Stream流,File类,字节/字符流,乱码,缓冲/转换/序列化/打印流,Properties

    文章目录 1.lambda表达式标准语法:()->{} 2.lambda表达式简略语法:可推导即可省略 3.lambda表达式原理:lambda效率比匿名内部类高 4.两个函数式接口:Consu ...

最新文章

  1. 动态路由协议RIP的基本原理与配置
  2. Android性能测试-分析工具
  3. 资源推荐—HTML5精品资源
  4. 哪个更好的选择:克隆或复制构造函数?
  5. 我是如何使用laydate日历插件更换掉老项目不好用的日历插件datepicker的
  6. 实现字符串的编码转换,用以解决字符串乱码问题
  7. [html] 如何解决input在Firefox和Chrome中高度不一致的问题?
  8. Gym - 100543L
  9. 第十二届 蓝桥杯 青少年C++组 10月比赛 第1题
  10. codevs——2152 滑雪
  11. 超全必读!事件抽取综述(上)
  12. java awt 教程_JAVA教程第五讲AWT图形用户界面设计
  13. u盘被写保护了无法格式化怎么办?
  14. 基于python的大米粒分割(本文适合两个凹点的粘连物体)
  15. 计算机桌面图标右上角出现双箭头符号,电脑桌面图标有箭头,如何消除小小障碍小编有绝招...
  16. 到底什么是阿里味?能否在不加入阿里的时候可以体验一下
  17. python 豆瓣电影top250_python 爬豆瓣电影top250
  18. html图片靠右浮动 文字左侧环绕,CSS 模拟float实现center文字左右环绕图片的效果...
  19. 故宫景点功课2:前三殿区
  20. 阿里为Linux内核调度器提出一个新的”组平衡器”概念

热门文章

  1. turnitin时间
  2. 申请英国学校最晚什么时候考出雅思呢?
  3. 【转】内存耗用:VSS/RSS/PSS/USS
  4. Linux rsync 命令参数详解
  5. 阿里云服务器Svn-Server无法连接,阿里云服务器SVNServer配置
  6. java多线程--AtomicReference
  7. Shell脚本入门基础
  8. 在rancher服务器页面添加Host
  9. web04--cookie
  10. Web认证及API的 使用TOKEN的一些思考