我正在执行像下面显示的基准
CHECK( context = clCreateContext(props, 1, &device, NULL, NULL, &_err); );
CHECK( queue = clCreateCommandQueue(context, device, 0, &_err); );
#define SYNC() clFinish(queue)
#define LAUNCH(glob, loc, kernel) OCL(clEnqueueNDRangeKernel(queue, kernel, 2,\
NULL, glob, loc,\
0, NULL, NULL))
/* Build program, set arguments over here */
START;
for (int i = 0; i < iter; i++) {
LAUNCH(global, local, plus_kernel);
}
SYNC();
STOP;
printf("Time taken (plus) : %lf\n", uSec / iter);
START;
for (int i = 0; i < iter; i++) {
LAUNCH(global, local, minus_kernel);
}
SYNC();
STOP;
printf("Time taken (minus): %lf\n", uSec / iter);
START;
for (int i = 0; i < iter; i++) {
LAUNCH(global, local, plus_kernel);
LAUNCH(global, local, minus_kernel);
}
SYNC();
STOP;
printf("Time taken (both) : %lf\n", uSec / iter);
结果看起来很奇怪:
Time taken (plus) : 31.450000
Time taken (minus): 28.120000
Time taken (both) : 2256.380000
START
和STOP
只是启动和停止计时器的宏。
以下是相关的宏。
我不确定为什么排队是因为内核正在减慢它们(并且仅在AMD GPU上)!
编辑我正在使用Radeon 7970
编辑两个内核都在独立内存上运行。这里还有系统信息。
操作系统:Ubuntu 11.10
fglrxinfo:
display: :0 screen: 0
OpenGL vendor string: Advanced Micro Devices, Inc.
OpenGL renderer string: AMD Radeon HD 7900 Series
OpenGL version string: 4.2.11762 Compatibility Profile Context
答案 0 :(得分:1)
我认为答案与在较新的GPU上缓存数据有关(特别是使用Graphics Compute Next (GCN)架构的Radeon 7970。
这种架构的一个优点是它的缓存功能(此时有点接近CPU缓存)。如果你执行这样的调用:
PLUS
PLUS
PLUS
....
然后驻留在GPU的内部缓存中的内存。另一方面,如果您拨打这样的电话:
PLUS
MINUS
PLUS
MINUS
...
如果两个内核具有与之关联的不同内存对象,则数据会从每个CU上的硬件设备中踢出,导致需要从非常缓慢的全局内存中引入它们。
两种简单的方法来测试是否是这种情况:
仅运行具有不同迭代次数的加号。随着迭代次数的增加,平均时间将减少,因为第一次运行(带来数据)的成本是摊销的。此外,您应该注意到第一个之后的所有呼叫应该相对相等。
使Plus和Minus内核在相同的内存对象上运行。如果减速的原因是由于内存对象的缓存,则整体运行时间应该是PLUS和MINUS的单独运行时间的平均值(可能取决于实验1)。
如果您发现实际情况确实如此,请告诉我们。