问题描述
考虑以下 OpenCL 内核。这是一个从长期的简化过程中产生的 MWE。当然拥有这样的内核是没有意义的,但这不是重点。保证MAX_ORDER >= num_fields
,特别是MAX_ORDER=15
(它通过clBuildProgram
作为编译时常量传递给-D
)。
__kernel void MWE_kernel(__global const double* const x,__global const double* alpha,const int num_fields,__global double* const restrict result,__local double* const restrict result_local)
{
const int id = get_global_id(0);
const int global_size = get_global_size(0);
double sum[MAX_ORDER];
for (unsigned int i = 0; i < num_fields; i++)
sum[i] = 0.0;
double sum_sc=0.0;
for (unsigned int id_mem = id; id_mem < 128 * num_fields; id_mem += global_size) {
const int alpha_idx = id_mem / 128;
//sum[0] += 3.0;
sum[alpha_idx] += 3.0;
sum_sc += 3.0;
/*
if (id == 8){
printf("sum[%d]=%f sum_sc=%f\n",alpha_idx,sum[alpha_idx],sum_sc);
}
*/
}
if(id == 8){
result[0] = sum[0];
result[1] = sum_sc;
}
}
我用 Intel(R) Gen9 HD Graphics NEO
和 local_size=64
以及 global_size=64
在 GPU 设备(设备名称:num_fields=1
)上排队。
我遇到的奇怪行为(我无法解释)是,如果我尝试使用 sum
作为索引填充 alpha_idx
私有数组,那么这对某些线程不起作用,在sum
条目没有增加的感觉。显示这种行为的第一个线程是数字 8,最后一个 if
-clause 设置 result[0] = 0
和 result[1]=6
,因为我可以在主机上检查。
我注意到调试的事实:
- 设置
MAX_ODER=1
(在本例中可能,因为num_fields=1
),使奇怪的行为消失(result[0]
变为 6)。但是,对于1<MAX_ORDER<21
没有任何变化。令人惊讶的是,MAX_ORDER>=22
更改了内核行为,我得到了result[0]=6
。 - 改变
local_size
和/或global_size
不会改变任何东西,除非local_size
减少到 8 或更少(见下一个项目符号)。 - 将用于将内核排入队列的
local_size
减少到 8 会使奇怪的行为消失(在上面的示例中很简单,因为不再有线程号 8,但是在更复杂的完整版本中,我得到了预期的结果)。 - 使用 this one 等在线工具没有发现任何问题。
问题:
- 您有什么想法可以解释我正在经历的行为吗?你能重现这种行为吗?
- 私有内存使用安全吗?或者
sum
数组声明在某种程度上很重要? - 如果我没有做错任何事,这种行为是否是 (GPU) 编译器错误!?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)