CUDA C/C++ 流和并发
bigegpt 2024-12-02 15:23 5 浏览
一、并发
1、同时执行多个CUDA操作的能力(超越多线程并行)
CUDA Kernel <<<>>>
cudaMemcpyAsync(HostToDevice)
cudaMemcpyAsync(DeviceToHost)
CPU上的操作
2、Fermi 体系结构可以同时支持(计算能力2.0+)
GPU上最多16个CUDA内核
2个cudaMemcpyAsyncs(必须在不同方向)
CPU上的计算
二、流
1、流
在GPU上按发布顺序执行的一系列操作
2、用于影响并发的编程模型
不同流中的CUDA操作可以同时运行
来自不同流的CUDA操作可以交织
三、并发示例
1、串行:将数据从CPU传输到GPU,GPU核函数执行计算操作,将计算结果从GPU传输到CPU上。
2、并行:重叠内核和设备到主机的内存拷贝,即内核执行的同时,可以将GPU上的数据拷贝到CPU上。
四、并发量
?1、串行:1倍的性能
2、2路并发:最多2倍的性能提升
3、3路并发:最多3倍的性能提升
4、4路并发:最多3倍多性能提升
5、多路并发
五、举例 - Tiled DGEMM
1、CPU(4 core Westmere x5670 @2.93GHZ,MKL)
43 Gflops
2、GPU(C2070)
串行:125 Gflops(2.9x)
2-路并行:177 Gflops(4.1x)
3-路并行:262 Gflops(6.1x)
3、GPU + CPU
4-路并行:282 Gflops (6.6x)
对于更高级的显卡,最大可以达到 330 Gflops
4、通过利用并发性获得最大性能
5、所有通信隐藏 - 有效地消除设备内存大小限制
?六、默认的流(流 ‘0’ )
1、未指定流时使用默认的流。
2、完全同步的w.r.t.主机和设备:好像在每次CUDA操作前后都插入了cudaDeviceSynchronize()
3、异常:异步w.r.t.主机
(1)内核在默认流中启动
(2)cudaMemcpy*Async
(3)cudaMemset*Async
(4)同一设备中使用cudaMemcpy
(5)小于或等于64KB的H2D(主机到设备) cudaMemcpy
七、并发性要求
1、CUDA操作必须位于不同的非0流中
2、来自“固定”内存的主机与cudaMemcpyAsync
分页锁定的内存
使用cudaMallocHost()或cudaHostAlloc()分配内存
3、必须有足够的资源
在不同的方向使用cudaMemcpyAsyncs
设备资源(SMEM,registers,blocks,etc.)
八、简单的例子:同步
完全的同步操作
cudaMalloc(&dev1,size); // 给GPU分配空间
double* host1 = (double*)malloc(&host1,size); // 给CPU分配空间
...
cudaMemcpy(dev1,host1,size,H2D); // 从CPU上拷数据到GPU
kernel2 <<< grid,block,0 >>>(...,dev2,...); // GPU上做计算操作
kernel3 <<< grid,block,0 >>>(...,dev3,...); // GPU上做计算操作
cudaMemcpy(host4,dev4,size,D2H); // 将计算结果从GPU上拷贝到CPU上
...
默认流中的所有CUDA操作都是同步的。
九、简单的例子:异步,不使用流
默认情况下,GPU内核与主机异步。
cudaMalloc(&dev1,size); // 给GPU分配空间
double* host1 = (double*)malloc(&host1,size); // 给CPU分配空间
...
cudaMemcpy(dev1,host1,size,H2D); // 从CPU上拷数据到GPU
kernel2 <<< grid,block,0 >>>(...,dev2,...); // GPU上做计算操作
some_CPU_method(); // 这一行与上一行存在潜在的并行
kernel3 <<< grid,block,0 >>>(...,dev3,...); // GPU上做计算操作
cudaMemcpy(host4,dev4,size,D2H); // 将计算结果从GPU上拷贝到CPU上
...
十、简单的例子:异步,使用流
完全异步/并发
并发操作使用的数据应该是独立的
cudaStream_t stream1,stream2,stream3,stream4;
cudaStreamCreate(&stream1);
...
cudaMalloc(&dev1,size); // 给GPU分配空间
cudaMallocHost(&host1,size);
...
cudaMemcpyAsunc(dev1,host1,size,H2D,stream1); // 从CPU上拷数据到GPU
kernel2 <<< grid,block,0,stream2 >>>(...,dev2,...); // GPU上做计算操作
kernel3 <<< grid,block,0,stream3 >>>(...,dev3,...); // GPU上做计算操作
cudaMemcpyAsync(host4,dev4,size,D2H,stream4); // 将计算结果从GPU上拷贝到CPU上
some_CPU_method();
...
十一、显式同步
1、同步一切
cudaDeviceSunchronize()
阻止主机,直到所有发出的CUDA调用完成。
2、同步w.r.t. 特定的流
cudaStreamSynchronize(streamid)
阻止主机,直到streamid中的所有CUDA调用完成
3、使用事件同步
在流中创建特定的“事件”以用于同步
cudaEventRecord(event,streamid)
cudaEventSynchronize(event)
cudaStreamWiatEvent(stream,event)
cudaEventQuery(event)
4、显示同步示例
使用事件解决
{
cudaEvent_t event;
cudaEventCreate(&event);
cudaMemcpyAsync(d_in,in,size,H2D,stream1);
cudaEventRecord(event,stream1);
cudaMemcpyAsync(out,d_out,size,D2H,stream2);
cudaStreamWaitEvent(stream2,event);
kernel<<<,,,stream2>>>(d_in,d_out);
asynchronousCPUmethod(...);
}
十二、隐式同步
1、这些操作隐式同步所有其他CUDA操作
(1)分页锁定的内存分配
cudaMallocHost
cudaHostAlloc
(2)设备内存分配
cudaMalloc
(3)非异步版本的内存操作
cudaMemcpy* (no Async suffix)
cudaMemset* (no Async suffix)
(4)更改为L1 /shared 内存配置
cudaDeviceSetCacheConfig
十三、流调度
1、Fermi硬件有三个队列
(1)1个计算引擎队列
(2)2个复制引擎队列–一个用于H2D,一个用于D2H
2、CUDA操作按其发出的顺序分派给硬件
(1)放在相关队列中
(2)引擎队列之间的流依赖关系得到维护,但在引擎队列中丢失
3、在以下情况下,将从引擎队列中调度CUDA操作:
(1)同一流中的先前调用已完成
(2)已调度同一队列中的先前调用,并且
(3)资源可用
4、如果CUDA内核位于不同的流中,则可以同时执行
如果前面内核的所有线程块都已调度,并且仍有可用的SM资源,则会调度给定内核的线程块
5、请注意,被阻止的操作会阻止队列中的所有其他操作,即使在其他流中也是如此
十四、示例–阻塞队列
1、两个流,流1首先发布
(1)Stream 1::HDa1,HDb1,K1,DH1(首先发出)
(2)Stream 2:DH2(完全独立于流1)
?2、两个流,流2首先发布- issue order matters
(1)Stream 1:HDa1,HDb1,K1,DH1
(2)Stream 2:DH2(issued first)
?十五、示例-阻塞内核 - issue order matters
1、两个流–仅发布CUDA内核
(1)Stream 1:Ka1,Kb1
(2)Stream 2:Ka2,Kb2
(3)内核大小一样,占SM资源的?
2、发行深度优先
?3、发行广度优先
?十六、示例-最佳并发性取决于内核执行时间
1、两个流-仅发布CUDA内核-但是内核的“大小”不同
issue order matters! execution time matters!
(1)Stream 1 : Ka1 {2}, Kb1 {1}
(2)Stream 2 : Kc2 {1}, Kd2 {2}
(3)内核占SM资源的一半
2、深度优先
?3、广度优先
?4、自定义
?十七、并发内核调度
1、并发内核调度是一种特殊的调度方法
2、通常,在操作之后,将信号插入队列,以在同一流中启动下一个操作
3、对于计算引擎队列,要启用并发内核,当按顺序发布计算内核时,该信号将延迟到最后一个按顺序计算内核之后
4、在某些情况下,这种信号延迟会阻塞其他队列
十八、示例–并发内核和阻塞
1、三个流,分别为(HD,K,DH)
2、广度优先,顺序发出的内核延迟信号并阻塞cudaMemcpy(D2H)
?3、深度优先,“通常”最适合Fermi体系架构,即执行GPU的过程中,同时可以将GPU中计算的结果传输到CPU上
?十九、以前的架构
1、计算能力1.0+
支持GPU / CPU并发
2、计算能力1.1+(即C1060)
增加了对异步内存复制的支持(单引擎),(某些异常–使用asyncEngineCount设备属性检查)
3、计算能力2.0+(即C2050)
添加对并发GPU内核的支持,(某些异常–使用concurrentKernels设备属性检查)
添加第二个复制引擎以支持双向存储,(某些异常–使用asyncEngineCount设备属性检查
二十、额外细节
1、很难同时运行四个以上的内核
2、可以使用环境变量禁用并发:CUDA_LAUNCH_BLOCKING
3、cudaStreamQuery可用于分离顺序内核并防止延迟信号
4、使用8个以上纹理的内核不能同时运行
5、切换 L1 / Shared 配置将破坏并发性
6、要同时运行,CUDA操作必须具有不超过62个中间CUDA操作,也就是说,按照“发出顺序”,它们之间不能相隔超过62个其他问题;进一步的操作被序列化。
7、cudaEvent_t is useful for timing, but for performance use
cudaEventCreateWithFlags ( &event, cudaEventDisableTiming )
二十一、并发准则
1、代码到编程模型–流
未来的设备将不断改善流模型的硬件表示
2、注意发布顺序
可能会有所不同
3、注意可能破坏并发性的资源和操作
(1)默认流中的所有内容
(2)事件和同步
(3)流查询
(4)L1 /Shared 配置更改
(5)8种以上的纹理
4、使用工具(Visual Profiler,Parallel Ensight)可视化并发,但这些当前不显示并发内核。
二十二、问题
1、验证Stream-0中的cudaMemcpyAsync()后跟Kernel <<< >>>,该memcpy将阻止内核,但都不会阻止主机。
2、下列操作(或类似操作)是否对 64 'out-ofissue-order' 限制有所贡献?
cudaStreamQuery
cudaWaitEvent
3、我知道'query'操作cudaStreamQuery()可以放在引擎或复制队列中,任何查询实际进入的队列都很难确定,并且这可能导致某些阻塞。
相关推荐
- 悠悠万事,吃饭为大(悠悠万事吃饭为大,什么意思)
-
新媒体编辑:杜岷赵蕾初审:程秀娟审核:汤小俊审签:周星...
- 高铁扒门事件升级版!婚宴上‘冲喜’老人团:我们抢的是社会资源
-
凌晨两点改方案时,突然收到婚庆团队发来的视频——胶东某酒店宴会厅,三个穿大红棉袄的中年妇女跟敢死队似的往前冲,眼瞅着就要扑到新娘的高额钻石项链上。要不是门口小伙及时阻拦,这婚礼造型团队熬了三个月的方案...
- 微服务架构实战:商家管理后台与sso设计,SSO客户端设计
-
SSO客户端设计下面通过模块merchant-security对SSO客户端安全认证部分的实现进行封装,以便各个接入SSO的客户端应用进行引用。安全认证的项目管理配置SSO客户端安全认证的项目管理使...
- 还在为 Spring Boot 配置类加载机制困惑?一文为你彻底解惑
-
在当今微服务架构盛行、项目复杂度不断攀升的开发环境下,SpringBoot作为Java后端开发的主流框架,无疑是我们手中的得力武器。然而,当我们在享受其自动配置带来的便捷时,是否曾被配置类加载...
- Seata源码—6.Seata AT模式的数据源代理二
-
大纲1.Seata的Resource资源接口源码2.Seata数据源连接池代理的实现源码3.Client向Server发起注册RM的源码4.Client向Server注册RM时的交互源码5.数据源连接...
- 30分钟了解K8S(30分钟了解微积分)
-
微服务演进方向o面向分布式设计(Distribution):容器、微服务、API驱动的开发;o面向配置设计(Configuration):一个镜像,多个环境配置;o面向韧性设计(Resista...
- SpringBoot条件化配置(@Conditional)全面解析与实战指南
-
一、条件化配置基础概念1.1什么是条件化配置条件化配置是Spring框架提供的一种基于特定条件来决定是否注册Bean或加载配置的机制。在SpringBoot中,这一机制通过@Conditional...
- 一招解决所有依赖冲突(克服依赖)
-
背景介绍最近遇到了这样一个问题,我们有一个jar包common-tool,作为基础工具包,被各个项目在引用。突然某一天发现日志很多报错。一看是NoSuchMethodError,意思是Dis...
- 你读过Mybatis的源码?说说它用到了几种设计模式
-
学习设计模式时,很多人都有类似的困扰——明明概念背得滚瓜烂熟,一到写代码就完全想不起来怎么用。就像学了一堆游泳技巧,却从没下过水实践,很难真正掌握。其实理解一个知识点,就像看立体模型,单角度观察总...
- golang对接阿里云私有Bucket上传图片、授权访问图片
-
1、为什么要设置私有bucket公共读写:互联网上任何用户都可以对该Bucket内的文件进行访问,并且向该Bucket写入数据。这有可能造成您数据的外泄以及费用激增,若被人恶意写入违法信息还可...
- spring中的资源的加载(spring加载原理)
-
最近在网上看到有人问@ContextConfiguration("classpath:/bean.xml")中除了classpath这种还有其他的写法么,看他的意思是想从本地文件...
- Android资源使用(android资源文件)
-
Android资源管理机制在Android的开发中,需要使用到各式各样的资源,这些资源往往是一些静态资源,比如位图,颜色,布局定义,用户界面使用到的字符串,动画等。这些资源统统放在项目的res/独立子...
- 如何深度理解mybatis?(如何深度理解康乐服务质量管理的5个维度)
-
深度自定义mybatis回顾mybatis的操作的核心步骤编写核心类SqlSessionFacotryBuild进行解析配置文件深度分析解析SqlSessionFacotryBuild干的核心工作编写...
- @Autowired与@Resource原理知识点详解
-
springIOCAOP的不多做赘述了,说下IOC:SpringIOC解决的是对象管理和对象依赖的问题,IOC容器可以理解为一个对象工厂,我们都把该对象交给工厂,工厂管理这些对象的创建以及依赖关系...
- java的redis连接工具篇(java redis client)
-
在Java里,有不少用于连接Redis的工具,下面为你介绍一些主流的工具及其特点:JedisJedis是Redis官方推荐的Java连接工具,它提供了全面的Redis命令支持,且...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- resize函数 (64)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- mybatis大于等于 (64)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- logstashinput (65)
- hadoop端口 (65)
- vue阻止冒泡 (67)
- oracle时间戳转换日期 (64)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)