Welcome

首页 / 软件开发 / C++ / GPGPU OpenCL/CUDA 高性能编程的10大注意事项

GPGPU OpenCL/CUDA 高性能编程的10大注意事项2015-05-071.展开循环

如果提前知道了循环的次数,可以进行循环展开,这样省去了循环条件的比较次数。但是同时也不能使得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
",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 冲突。