OpenCL在大2d范围内崩溃

OpenCL crash on big 2d range

本文关键字:崩溃 范围内 2d 在大 OpenCL      更新时间:2023-10-16

在我的程序中,我需要在大型2d数组的每个项目上运行内核一次。该程序在小范围内正确工作-高达约50x50,有时高达100x100。

然而,对于更大的数据集,调用内核会导致显卡驱动程序崩溃。

我在两台使用不同AMD卡的计算机上测试了这个程序,它们表现出完全相同的行为。另外,一维的内核可以正常工作,甚至对于~ 10,000 x 10,000项的庞大数据集也是如此。

同样,从matrix[i + (N + 1) * j]表达式中删除i变量可以使内核工作无错误。

我设置的范围不正确,在内核中犯了错误,或者问题在于其他地方?

队列的范围:

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]; 
}

一个可能的原因—如果内核运行时间太长,驱动程序可能会丢弃它。把问题分成小块

考虑一下,对于一个100x100的输入数组,您将使用N=100,因此内核中i的最大值将是100,因为队列参数中使用了N+1,而j的最大值将是99。我假设offset = 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。

根据我的经验,gpu在访问全局内存时不擅长捕捉分段错误。您有目的地创建的尝试有时可能在某些卡片上有效,但不能保证。

问题可能是由local-work-size和global-work-size引起的。在使用二维数组时,正确地计算它们是很重要的。对于大值,您的global_id(0)可能大于您在clEnqueueNDRangeKernel()中指定的值。