GPGPU OpenCL/CUDA 高性能编程的10大注意事项
副标题#e#
1.展开轮回
假如提前知道了轮回的次数,可以举办轮回展开,这样省去了轮回条件的较量次数。可是同时也不能使得kernel代码太大。
轮回展开代码例子:
#include<iostream> using namespace std; int main(){ int sum=0; for(int i=1;i<=100;i++){ sum+=i; } sum=0; for(int i=1;i<=100;i=i+5){ sum+=i; sum+=i+1; sum+=i+2; sum+=i+3; sum+=i+4; } return 0; }
2.制止处理惩罚非尺度化数字
OpenCL中非尺度化数字,是指数值小于最小能暗示的正常值。由于计较机的位数有限,暗示数据的范畴和精度都不行能是无限的。(详细可以查察IEEE 754尺度,http://zh.wikipedia.org/zh-cn/IEEE_754)
在OpenCL中利用非尺度化数字,大概会呈现“除0操纵”,处理惩罚很耗时间。
假如在kernel中“除0”操纵影响不大的话,可以在编译选项中插手-cl-denorms-are-zero,如:
clBuildProgram(program, 0, NULL, "-cl-denorms-are-zero", NULL, NULL);
3.通过编译器选项传输常量根基范例数据到kernel,而不是利用private memory
假如措施中需要给kernel 传输常量根基范例数据,最好是利用编译器选项,好比宏界说。而不是,每个work-item都界说一个private memory变量。这样编译器在编译时,会直接举办变量替换,不会界说新的变量,节减空间。
如下面代码所示(Dmacro.cpp):
#include<stdio.h> int main() { int a=SIZE; printf("a=%d, SIZE=%d\n",a,SIZE); return 0; }
编译:
g++ -DSIZE=128 -o A Dmacro.cpp
4.假如共享不重要的话,生存一部门变量在private memory而不是local memory
work-item会见private memory速度快于local memory,因此可以把一部门变量数据生存在private memory中。虽然,当private memory容量满时,GPU硬件会自动将数据转存到local memory中。
5.会见local memory应制止bank conflicts
local memory被组织为一个一个的只能被单独会见的bank,bank之间交错存储数据,以便持续的32bit被生存在持续的bank中。如下图所示:
(1)假如多个work-item会见持续的local memory数据,他们就能最大限度的实现并行读写。
(2)假如多个work-item会见同一个bank中的数据,他们就必需顺序执行,严重低落数据读取的并行性。因此,要公道布置数据在local memory中的机关。
(3)非凡环境,假如一个wave/warp中的线程同时读取一个local memory中的一个地点,这时将举办广播,不属于bank 斗嘴。
#p#副标题#e#
6.制止利用”%“操纵
"%"操纵在GPU可能其他OpenCL设备上需要大量的处理惩罚时间,假如大概的话只管制止利用模操纵。
7.kernel中重用(Reuse) private memory,为同一变量界说差异的宏
假如kernel中有两个可能以上的private variable在代码中利用(好比一个在代码段A,一个在代码段B中),可是他们可以被数值沟通。
也就是当一个变量用作差异的目标时,为了制止代码中的定名狐疑,可以利用宏。在一个变量上界说差异的宏。
如下面代码所示:
#include<stdio.h> int main(){ int i=4; #define EXP i printf("EXP=%d\n",EXP); #define COUNT i printf("COUNT=%d\n",COUNT); getchar(); return 0; }
8.对付(a*b+c)操纵,只管利用 fma function
假如界说了“FP_FAST_FMAF”宏,就可以利用函数fma(a,b,c)准确的计较a*b+c。函数fma(a,b,c)的执行时间小于或便是计较a*b+c。
9.在program file 文件中对非kernel的函数利用inline
inline修饰符汇报编译器在挪用inline函数的处所,利用函数体替换函数挪用。固然会使得编译后的代码占用memory增加,可是省去了函数挪用时上下、函数挪用栈的切换操纵,节减时间。
10.制止分支预测处罚,应该只管使得条件判定为真的大概性大
现代处理惩罚器一般城市举办“分支预测”,以便更好的提前“预取”下一条要执行的指令,使得“取指令、译码阐明、执行、生存”尽大概的并行。
在“分支预测”堕落时,提前取到的指令,不是要执行的指令,就需要按照跳转指令,举办从头取指令,就是“分支预测处罚”。
看如下的代码:
#include<stdio.h> int main() { int i=1; int b=0; if(i == 1) b=1; else b=0; return 1; }
对应的汇编代码:
(movl 赋值,cmpl 较量,jne 不便是跳转,jmp 无条件跳转)
#p#分页标题#e#
从上面的汇编指令代码看出,假如较量(<main+24>)功效相等,则执行<main+26>也就是较量指令的下一条指令,对应b=1顺序执行;假如较量(<main+24>)功效不相等,则执行跳转到<main+35>,不是顺序执行。
虽然,有的处理惩罚器大概会按照以往“顺序执行”与“跳转执行”的比例来举办分支预测,可是这也是需要积聚的进程。何况并不是,每个处理惩罚器多能这样只能。
本文:http://www.cnblogs.com/xudong-bupt/p/3630952.html