【发布时间】:2020-04-05 20:07:23
【问题描述】:
我注意到,使用动态索引会将 CUDA 代码的速度降低 12 倍 - 请参见以下示例:
__global__ void static3Ops(int start, int end, const float* p, const int* prog_dont_use, float* c)
{
int i = threadIdx.x;
float buf[5];
buf[0] = 1.0e7;
buf[1] = c[i];
const int prog[] = { 0,1,2,3,4,5 };
for (long j = start; j < end; j++) {
buf[2] = p[j];
buf[3] = buf[prog[0]] + buf[prog[1]];
buf[4] = buf[prog[2]] - buf[prog[3]];
buf[1] = buf[prog[4]] * buf[prog[5]];
}
c[i] = buf[1];
}
比
快 12 倍__global__ void static3Ops(int start, int end, const float* p, const int* prog, float* c)
{
int i = threadIdx.x;
float buf[5];
buf[0] = 1.0e7;
buf[1] = c[i];
for (long j = start; j < end; j++) {
buf[2] = p[j];
buf[3] = buf[prog[0]] + buf[prog[1]];
buf[4] = buf[prog[2]] - buf[prog[3]];
buf[1] = buf[prog[4]] * buf[prog[5]];
}
c[i] = buf[1];
}
任何提示如何最小化该开销?动态特性是我的代码的核心特性......所以没有它我几乎无法解决......
请注意,CPU 的开销仅为 20% 左右。
【问题讨论】:
-
prog 真的只是一个大小为 6 的数组吗?
-
这是预期的。在第一种情况下,编译器很可能只是对索引的值进行硬编码,因为您在内核中定义了数组,它在编译时是已知的,允许编译器执行读取所需的所有操作
buff尽可能快(例如同时加载多个变量,或者知道您实际上正在索引所有buff,而不是重复相同的变量等)。在第二种情况下,编译器需要灵活处理任意prog,因此生成的代码会有所不同。 -
取决于您需要的灵活性,也许模板或其他一些技巧可以让您优化它,但这是特定于问题的,因此您需要描述问题
-
buf[prog[5]]时出现溢出。