【问题标题】:Opencl runs fine even the kernel has errors即使内核有错误,Opencl 也能正常运行
【发布时间】:2014-05-13 05:49:12
【问题描述】:

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

【问题讨论】:

  • 请发布一些关于如何构建内核的代码。

标签: kernel opencl


【解决方案1】:

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

  1. 你没有给clCreateProgramWithSource你认为你给它的内核。检查这一点的一个好方法是在调用前立即打印出您提供给clCreateProgramWithSource 的字符串。
  2. 您的应用程序“缓存”内核,随后的执行使用clCreateProgramWithBinary,而不是(修改后的)内核源代码。

【讨论】:

  • 为简单起见,我为内核分配了一些值和数组。像这样:c[iGID] = 111;如果我删除分号,程序仍然会显示 111。如果我更改 c[iGID] = 222;然后把分号放回去,我看到 222。程序得到了相同的源。我尝试删除可执行文件并重新编译。但它仍然可以在内核内部出错时完美运行。
  • @Luniam 这似乎排除了我上面的第一个建议,然后 - 检查第二个?
  • 我已删除所有可执行文件并再次重新编译。因此,它应该作为一个新的开始,并且应该在内核中进行更改。顺便说一句,我没有在我的程序中使用 clCreateProgramWithBinary 。
  • @Luniam 构建的内核将不是可执行文件,重新编译不应影响它。但是如果你不使用clCreateProgramWithBinary 这个选项也是不可能的,所以恐怕我没有适合你的解决方案:(我把我的答案留在这里,以防它可以帮助其他有类似问题的人.
  • 我会说你正在使用二进制构建,并且在任何编译错误时程序都使用旧的二进制。
【解决方案2】:

我强烈认为您忘记在代码中为每个 openCL API 添加 OpenCL 错误检查,如果您没有明确捕获错误,OpenCL 内核将继续执行,就好像没有问题一样。 (在 OpenCL 编程中千万不要错过这个)

如果您还没有进行错误检查,则可以如下进行(根据 API 调用而有所不同)

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

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

【讨论】:

  • 初始化 0 没有帮助。每次我运行内核出错时,我都会得到先前结果的结果。这是为 opencl 工作的自然方式吗?我没有使用 clCreateProgramWithBinary。
  • 您是否应用了 API 错误检查?如果是这样,有什么失败吗?这不是 OpenCL 的工作方式,请转储您的代码以供进一步调查。
  • 嗨 Sagar,这就是 OpenCL 的工作方式。如果您的内核有错误并且它不能运行,那么设备内存仍然保存之前成功运行代码的值。因此,您将获得上一次运行的价值。
【解决方案3】:

在内核运行甚至程序启动之间不会清除设备内存。由于您正在注释掉实际写入内存的代码,因此您只是获得了上次运行时写入的内容。使用 NVIDIA GPU 和较旧的驱动程序版本,我什至看到系统重启后内存持续存在。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 2023-02-19
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    相关资源
    最近更新 更多