Kernel Opencl运行良好,即使内核有错误

Kernel Opencl运行良好,即使内核有错误,kernel,opencl,Kernel,Opencl,我遇到了一个奇怪的问题。 我有一个简单的内核。它很好用。 我发现,如果我删除了opencl内核文件中的一些行或引入了一些错误,然后尝试运行该程序,该程序运行良好,就好像它有正确的代码并且没有给出任何错误一样。 但是它应该给出错误,因为内核有错误。 所以,它无法检测错误,如果发现错误,它将使用以前正确版本的代码运行。 这是一个功能吗?这里出了什么问题?这不是OpenCL的特性。我猜原因可能是: 你没有给clCreateProgramWithSource你认为你给它的内核。检查这一点的一个好方法是在

我遇到了一个奇怪的问题。 我有一个简单的内核。它很好用。 我发现,如果我删除了opencl内核文件中的一些行或引入了一些错误,然后尝试运行该程序,该程序运行良好,就好像它有正确的代码并且没有给出任何错误一样。 但是它应该给出错误,因为内核有错误。 所以,它无法检测错误,如果发现错误,它将使用以前正确版本的代码运行。
这是一个功能吗?这里出了什么问题?

这不是OpenCL的特性。我猜原因可能是:

你没有给clCreateProgramWithSource你认为你给它的内核。检查这一点的一个好方法是在调用之前立即打印出提供给clCreateProgramWithSource的字符串。 应用程序缓存内核,后续执行使用clCreateProgramWithBinary而不是修改的内核源代码。
这不是OpenCL的一个特性。我猜原因可能是:

你没有给clCreateProgramWithSource你认为你给它的内核。检查这一点的一个好方法是在调用之前立即打印出提供给clCreateProgramWithSource的字符串。 应用程序缓存内核,后续执行使用clCreateProgramWithBinary而不是修改的内核源代码。
我强烈地感觉到您忘记了在代码中为每个OpenCLAPI添加OpenCL错误检查,如果您没有显式地捕获错误,OpenCL内核将继续运行,就像没有问题一样。在OpenCL编程中永远不要错过这一点

如果您还没有执行错误检查,那么可以按照以下方式进行检查,具体取决于API调用

error=clGetPlatformIDs(1, &platform, &platforms);
if (error != CL_SUCCESS) {
        printf("\n Error number %d", error);
}

正如您在评论中提到的,即使内核有错误,您也会得到正确的值,这是因为设备内存或主机内存具有上次运行的结果,这可能会在某个时候发生。将输出缓冲区初始化为0,然后推送到gpu并读回,现在您可能会看到乱码输出

我强烈感觉到您忘记了在代码中为每个OpenCL API添加OpenCL错误检查,如果您没有明确捕获错误,OpenCL内核将继续运行,就像没有问题一样。在OpenCL编程中永远不要错过这一点

如果您还没有执行错误检查,那么可以按照以下方式进行检查,具体取决于API调用

error=clGetPlatformIDs(1, &platform, &platforms);
if (error != CL_SUCCESS) {
        printf("\n Error number %d", error);
}

正如您在评论中提到的,即使内核有错误,您也会得到正确的值,这是因为设备内存或主机内存具有上次运行的结果,这可能会在某个时候发生。将输出缓冲区初始化为0,然后推送到gpu并读回,现在您可能会看到乱码输出

在内核运行或程序启动之间,设备内存不会被清除。由于您正在注释实际写入内存的代码,因此您只需要获得上一次运行时写入的内容。使用NVIDIA GPU和更旧的驱动程序版本,我甚至可以看到系统重新启动时的内存持久性


为了确认这一点,您可以尝试分配几个缓冲区,并使用以前未触及的缓冲区启动错误的内核。

在内核运行或程序启动之间,设备内存不会被清除。由于您正在注释实际写入内存的代码,因此您只需要获得上一次运行时写入的内容。使用NVIDIA GPU和更旧的驱动程序版本,我甚至可以看到系统重新启动时的内存持久性


为了确认这一点,您可以尝试分配几个缓冲区,并使用以前未触及的缓冲区启动错误的内核。

为简单起见,我为内核分配了一些值和数组。像这样:c[iGID]=111;如果我去掉分号,程序仍然显示111。如果我改变c[iGID]=222;把分号放回去,我明白了。程序正在获取相同的源代码。我尝试删除可执行文件并重新编译。但它仍然可以在内核内部错误的情况下完美运行。@Luniam这似乎排除了我上面的第一个建议,然后-检查第二个建议?我已经删除了所有可执行文件并重新编译。因此,它应该作为一个新的开始,并且应该得到内核中所做的更改。顺便说一句,我的程序中没有使用clCreateProgramWithBinary one。@Luniam生成的内核不会是可执行文件,重新编译不会影响它。但是如果你不使用clCreateProgramWithBinary,这个选项也是不可能的,所以我恐怕没有一个解决方案:我把我的答案留在这里,以防它对其他有类似问题的人有帮助。我想说你使用的是build with binary,在任何编译错误时,程序都会使用旧的二进制文件。为了简单起见,我从内核向和数组分配了一些值。像这样:c[iGID]=111;如果我去掉分号,程序仍然显示111。如果我改变c[iGID]=222;把分号放回去,我明白了。程序正在获取相同的源代码。我尝试删除可执行文件并重新编译
N但它仍然可以在内核内部错误的情况下完美运行。@Luniam这似乎排除了我上面的第一个建议,然后-检查第二个建议?我已经删除了所有可执行文件并重新编译。因此,它应该作为一个新的开始,并且应该得到内核中所做的更改。顺便说一句,我的程序中没有使用clCreateProgramWithBinary one。@Luniam生成的内核不会是可执行文件,重新编译不会影响它。但是如果你不使用clCreateProgramWithBinary,这个选项也是不可能的,所以我恐怕没有一个解决方案:我把我的答案留在这里,以防它对其他有类似问题的人有帮助。我想说你使用的是build with binary,在任何编译错误时,程序都会使用旧的二进制文件。请发布一些关于如何构建内核的代码。请发布一些关于如何构建内核的代码。初始化0没有帮助。每次我错误地运行内核时,我都会得到上一个结果的结果。这是opencl的自然工作方式吗?我没有使用clCreateProgramWithBinary。是否应用了API错误检查?如果是的话,有没有失败的地方?这不是OpenCL的工作方式,请转储您的代码以便进一步调查。嗨,Sagar,这是OpenCL的工作方式。如果您的内核有错误并且无法运行,那么设备内存仍然保存上次成功运行代码时的值。因此,您将获得上一次运行的值。初始化0没有帮助。每次我错误地运行内核时,我都会得到上一个结果的结果。这是opencl的自然工作方式吗?我没有使用clCreateProgramWithBinary。是否应用了API错误检查?如果是的话,有没有失败的地方?这不是OpenCL的工作方式,请转储您的代码以便进一步调查。嗨,Sagar,这是OpenCL的工作方式。如果您的内核有错误并且无法运行,那么设备内存仍然保存上次成功运行代码时的值。因此,您将获得上一次运行的值。