为什么 clEnqueueNDRangeKernel 会因浮点异常而崩溃?

问题描述

我正在尝试从 C++ 程序中使用 clEnqueueNDRangeKernel() 启动某个内核。但它不会入队或返回错误,而是得到一个浮点异常信号 (SIGFPE)。

由于 IP 原因我无法深入,我很难提供触发此信号的示例。但是 - 似乎没有任何合法的理由发生这种情况。是否存在该函数本身实际执行无效浮点运算的已知情况?

解决方法

tl;dr:由于您的尺寸问题,它被零除。

使用 NVIDIA CUDA 的 OpenCL 库(至少 v11.2.152),传递工作组维度和不同维度的整体网格维度可能确实会触发这种情况。 OpenCL 用户过去have reported有类似行为。

NVIDIA 遗憾地选择仅以闭源方式提供其库,因此我只能推测原因,但似乎如下:当您构建具有二维的 cl::NDRange 时,第三个值在国际表示中被初始化为 0(明确地和必然地,或者只是有时)。现在,如果您仔细阅读 clEnqueueNDRangeKernel() 的文档,您会注意到全局维度和局部维度必须具有相同的维度,即相同的维度数; clEnqueueNDRangeKernel() 可能假设是这种情况,并使用 global_dims_it_got[i] / local_dims_it_got[i] 为其接收到的全局维度的每个维度计算第三维度中的网格块数(工作组数)。因此,当全局维数更高时,它最终会被 0 除。这会触发 SIGFPE,尽管它的名称如此,但它不仅用于无效的浮点运算,还用于 any arithmetic error