CUDA编程优化(存储器访问优化,指令优化,参数优化,)

简介:

Chapter 1. 存储器访问优化

1、使用Pinned Memory

Pinned Memory又称页锁定存储器(Page-locked memory)。Pinned Memory由于“禁止”了系统的页交换功能,所以可以更快的在hostdevice之间传输。与一般GPU变量的空间分配不同,Pinned Memory通过特定的cudaHostAlloc函数分配的空间。如果想将已经分配的变量变成Pinned Memory,则需要通过cudaHostRegister函数。

通过Pinned Memory我们可以实现CUDA提供的多种高效的功能,其中对性能优化最有帮助的就是异步传输。Pinned Memory允许实现hostdevice之间数据的异步传输,这样程序将可以并行的处理计算与传输。在程序中以流水线(stream 流)作为实现方式,如下面这段程序:

 

size=N*sizeof(float)/nStreams;

for (i=0; i<nStreams; i++) {

offset = i*N/nStreams;

cudaMemcpyAsync(a_d+offset, a_h+offset, size, dir, stream[i]);

kernel<<<N/(nThreads*nStreams), nThreads, 0, stream[i]>>>(a_d+offset);

}

 

程序将需要计算的内容分为nStreams个部分,每个部分通过一个流来实现数据传输与计算。通过多个流的重叠,使得不同流之间的传输与计算可以重叠。

当然,Pinned Memory也是有缺点的,由于受到系统资源的限制,过多创建Pinned Memory会导致系统资源对其他程序不足,从而影响系统整体性能。

 

2global memory的访存优化

对属于计算密集型的CUDA程序,访存global memory的访存优化是十分必要的,但是在实际的实施过程中需要耗费较多的工作量,所以从实际角度出发,优化过程可以归结为:序号连续的线程应近可能访问地址连续的存储空间(即连续的数组元素)。

 

3shared memory的访存优化

Shared memory有多个等大小的内存模块组成,这些模块被称为bank。这些bank可以被同时访问。当若干个线程同时访问一个bank时,这些访存指令将会串行执行,这种情况被称为bank冲突。 计算能力1.X的设备Shared memory被分为16bank,计算能力2.X及以上的设备被分为32bank。下面以2.X设备为例介绍共享存储器的优化。假设有数组__shared__ float a[32][32],则数据在bank中的存储为:


e2a83f6d0d841961b6c9f4edf87c0a2538482113

warp中的线程以连续或者以交错而没有交集的方式读取一行数据,则这些访存指令不存在冲突。当这些线程按照如图所示的方式读取同属于bank 0的一列数据,则这些访存指令会串行执行。在发生冲突的情况下有一种特例,那就是当warp中所有线程同时访问同一个bank中的同一个元素时,会被自动优化成广播(broadcast)。在计算能力2.X以上的设备将这种情况进一步优化为,当warp中若干个线程访问同一个bank中的同一个元素时,这些访存指令只需进行一次,就可以使其他需要相同元素的线程也获得这个元素,这个过程称为多播(multicast)。

 

Chapter 2. 指令优化

1、如果程序对双精度没有要求,则应该使用单精度数(float)常量、变量和单精度计算函数。通过在编译时加入-use_fast_math选项,可以将核函数中使用的单精度计算函数替换为CUDA内部实现的高速版本(但是会影响计算精度)。

2、确保warp内的线程执行相同的指令,尽量减少在程序中使用分支语句。在线程执行时,同一个warp内的线程如果需要执行不同的指令,那么线程将顺序的执行所有的指令,并将线程中不需要执行的那一侧分支指令设置为无效。但是,不同warp之间执行不同的分支并不会使线程执行所有的指令。

3、在循环中不要使用__syncthreads()

 

Chapter 3. 参数设置

核函数参数的设置决定的运行时执行的方式和可以获得的资源。NVIDIA提供了如下参考规则以供。

1)每个block的线程数应该是warp的倍数。这样可以避免计算资源的浪费,同时有助于合并访存。

2)当运行包含多个block的核函数时,可以将线程数设置为64

3block中线程数的参考值是128256(实际依赖于具体物理硬件)。

4)对于调用__syncthreads()的核函数,可以将一个拥有较大线程数的block拆分成多个(34个)拥有较少线程的block

占有率是衡量参数设置正确与否的参考值,NVIDIATOOLKIT中提供了CUDA_Occupancy_Calculator.xls来计算占有率。但是高GPU占有率并不意味着核函数拥有最好的计算效率。


原文发布时间为:2016-6-24 10:21:58
原文由: NV开发者社区版主肖博士 发布,版权归属于原作者 
本文来自云栖社区合作伙伴NVIDIA,了解相关信息可以关注NVIDIA官方网站
目录
相关文章
|
SQL 算法 数据库
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
【SQL server】玩转SQL server数据库:第三章 关系数据库标准语言SQL(二)数据查询
770 6
|
机器学习/深度学习 人工智能 并行计算
Titans:谷歌新型神经记忆架构,突破 Transformer 长序列处理的瓶颈
Titans 是谷歌推出的新型神经网络架构,通过神经长期记忆模块突破 Transformer 在处理长序列数据时的瓶颈,支持并行计算,显著提升训练效率。
565 5
Titans:谷歌新型神经记忆架构,突破 Transformer 长序列处理的瓶颈
|
消息中间件 存储 监控
消息队列 MQ使用问题之客户端重启后仍然出现broker接收消息不均匀,该怎么办
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
机器学习/深度学习 人工智能 搜索推荐
AI在医疗诊断中的应用:精准医疗的加速发展
【9月更文挑战第16天】随着人工智能(AI)技术的不断进步,医疗领域正经历前所未有的变革。本文探讨了AI在医学影像分析、病历数据分析和病症诊断预测等方面的应用,展示了其在提高诊断准确性、推动个性化治疗和促进医疗资源均衡分布方面的巨大潜力。AI正加速精准医疗的发展,有望在未来实现更智能、个性化的医疗服务,全面提升医疗质量和效率。
642 12
|
监控 网络协议 安全
Socks5协议原理分析及实现对比与问题排查实践
这篇文章《socks5协议原理分析及实现对比与问题排查实践》将深入探讨Socks5协议的工作原理,并对其与其他网络协议的实现进行详细比较。作者还将分享在实际应用过程中所遇到的问题及排查方法。对于想要提高系统安全性和性能的开发人员,本文提供了丰富的案例分析与实践经验。 在这篇文章中,读者将了解Socks5协议的基本概念、工作原理、具体实现方式以及常见问题与解决方案。这不仅有助于开发人员更好地理解Socks5协议,还能增强他们在开发与部署中应对复杂网络环境的能力,让我们一同探讨这些关键技术。
933 0
Socks5协议原理分析及实现对比与问题排查实践
|
人工智能 监控 并行计算
NVIDIA智算中心“产品”上市问题之NVIDIA Megatron-LM的定义如何解决
NVIDIA智算中心“产品”上市问题之NVIDIA Megatron-LM的定义如何解决
|
程序员 Linux C语言
【cmake 项目依赖冲突】CMake进阶:优雅解决目标依赖和安装问题
【cmake 项目依赖冲突】CMake进阶:优雅解决目标依赖和安装问题
1903 0
|
SoC
深入理解AMBA总线(十六)AXI设计的关键问题(二)
深入理解AMBA总线(十六)AXI设计的关键问题(二)
1852 0
深入理解AMBA总线(十六)AXI设计的关键问题(二)
|
存储
如何解决网页中的pdf文件无法下载?pdf打印显示空白怎么办?
如何解决网页中的pdf文件无法下载?pdf打印显示空白怎么办?
1848 0
|
SQL 存储 关系型数据库
mysqldump+binlog+gtid 实现数据库的增量备份(上)
mysqldump+binlog+gtid 实现数据库的增量备份
1146 0