CUDA优化策略【转载】

原文地址

CUDA程序优化应该考虑的点:

精度:只在关键步骤使用双精度,其他部分仍然使用单精度浮点以获得指令吞吐量和精度的平衡。

 延迟:需要首先缓冲一部分数据,缓冲的大小应该可以保证每个内核程序处理的一批数据能够让GPU慢负荷工作。

计算量:计算量太小的程序使用CUDA很不合算;当需要计算的问题的计算密集度很低的时候,执行计算的时间远远比IO花费的时间短,整个程序的瓶颈出现在PCI-E带宽上。

优秀的CUDA程序特征:

Active warp的数量能够让SM满载,并且active block的数量大于2,能够有效地隐藏访存延迟;

当瓶颈出现在运算指令时,指令流的效率已经过了充分优化;

当瓶颈出现在访问IO时,程序已经选用了恰当的存储器来储存数据,并使用了适当的存储器访问方式,以获得最大带宽;

UDA的编写与优化需要解决的问题:

确定任务中的串行和并行的部分,选择合适的算法;

按照算法确定数据和任务的划分方式,将每个需要实现的步骤映射为一个满足CUDA两层并行模型的内核函数,让每个SM上至少有6个活动warp和至少2个活动block;

优化显存访问:合并采用相同block和grid的kernel;尽力避免将线程私有变量分配到local memory;

优化指令流:在误差可接受的情况下,使用CUDA算术指令集中的快速指令;避免多余的同步;在只需要少量线程进行操作的情况下,使用类似“if threaded<N”的方式,避免多个线程同时运行占用更长时间或者产生错误结果;

优化指令流:在误差可接受的情况下,使用CUDA算术指令集中的快速指令;避免多余的同步;在只需要少量线程进行操作的情况下,使用类似“if threaded<N”的方式,避免多个线程同时运行占用更长时间或者产生错误结果;

资源均衡:调整每个线程处理的数据量,shared memory和register和使用量;通过调整block大小,修改算法和指令以及动态分配shared memory,都可以提高shred的使用效率;register的多少是由内核程序中使用寄存器最多的时刻的用量决定的,因此减小register的使用相对困难;

节约register方法:使用shared memory存储变量;使用括号明确地表示每个变量的生存周期;使用占用寄存器较小的等效指令代替原有指令;

与主机通信优化:尽量减少CPU与GPU间的传输:使用cudaMallocHost分配主机端存储器,可以获得更大带宽;一次缓存较多的数据后再一次传输,可以获得较高的贷款;需要将结果显示到屏幕的时候,直接使用与图形学API互操作的功能;使用流和异步处理隐藏与主机的通信时间;使用zero-memory技术和Write-Combined memory提高可用带宽;

Grid和Block的维度设计:

首先考虑block的尺寸,grid的尺寸一般越大越好;

每个SM中至少要有6个active warp用于隐藏流水线延迟,并且拥有至少2个active block;

计算每个SM上active warp和active block的数量:

确定每个SM使用的资源数量:使用nvcc的—keep编译选项,或者在.cu编译规则(cuda build rule)中选择保留中间文件,得到.cubin文件,用写字板打开后可以看到imem 和reg分别代表内核函数中每个线程使用的local memory和register数量

根据硬件确定SM上的可用资源:可以用SDK中的deviceQuery 获得每个SM中的资源;根据内核不同,SM上的warp总数上限,block总数上限,寄存器数量,shared memory数量都不同;

每个block中的线程数量不能超过512;

计算每个block使用的资源,并确定active block和active warp数量:

     e.g. 每个block中有64个线程,每个block使用256 Byte shared memory,8个寄存器文件,

           那么:每个人block使用的shared memory: 256 Byte;

                      每个block使用的寄存器文件数量: 8*64 = 512;

                      每个block中使用的warp数量:64/32 = 2;

                      如果在G80/92 GPU中运行这个内核程序:

                      由shared memory数量限制的active block数量: 16384/256  = 64;

                      由寄存器数量限制active block数量:8192/512 = 16;

                      由warp数量限制的active block数量 24/2 = 12;

                      每个SM中的最大active block数量:8;

这些计算可以由NVIDIA在CUDA SDK中提供的 CUDA occupancy calculator完成;

计算grid中各个维度上block的数量:grid在x轴上的block数量 = (问题在x轴上的尺寸+每个block在x轴上的尺寸-1)/每个block在x轴上的尺寸;

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值