在我的程序中,我需要在大型2d阵列的每个项目上运行一次内核。该程序适用于小范围 - 最高约50x50,有时高达100x100。
但是对于较大的数据集,调用内核会导致视频卡驱动程序崩溃。
我在两台具有不同AMD卡的计算机上测试了这个程序,它们表现出完全相同的行为。其他一维内核可以正常工作,即使对于大约10 000 x 10000个项目的大型数据集也是如此。
此外,从i
表达式中删除matrix[i + (N + 1) * j]
变量会导致内核正常工作。
我是否错误地设置了范围,在内核中出错,或者问题可能在其他地方?
排队范围:
cl::EnqueueArgs args(queue,cl::NDRange(offset, offset+1),cl::NDRange(N+1, N),cl::NullRange);
内核:
void kernel sub(global float* matrix, global const float* vec, int N, int offset) {
int i = get_global_id(0);
int j = get_global_id(1);
matrix[i + (N + 1) * j] -= matrix[i + (N + 1) * offset] * vec[j];
}
答案 0 :(得分:0)
可能的原因之一 - 如果您的内核运行时间太长,驱动程序可能会丢弃它。将问题区域划分为更小的块。
答案 1 :(得分:0)
考虑到这一点,对于100x100输入数组,你将使用N = 100,因此你的内核中i的最大值将是100,因为在enqueue args中使用了N + 1,而j的最大值将是99我假设偏移= 0.因此i +(N + 1)* j = 100 + 101 * 99 = 10099,它在2D数组之外。
当offset = 1时,i和j的最小值分别为1和2,而最大值为101和100.因此i +(N + 1)* j = 101 + 101 * 100 = 10201。 / p>
根据我的经验,GPU在访问全局内存时不能很好地捕获分段错误。您有意创建一个卡片的尝试可能会在某些卡片上有效但无法保证。
答案 2 :(得分:0)
问题可能是由本地工作规模和全球工作规模造成的。使用二维数组来正确计算它们很重要。对于大值,您的global_id(0)可能大于您在clEnqueueNDRangeKernel()中指定的值。