百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

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命令支持,且...