关于 OpenCL 控制流,其中 if(false) 被读取而不是被跳过,并且通常调试 OpenCL
Concerning OpenCL control flow, where if(false) is read instead of skipped, and debugging OpenCL in general
首先,这是我第一次真正觉得有必要在 Whosebug 上提问,但我在 rubberducking 和破解我自己的 OpenCL 代码时解决了我的问题。然而,考虑到我在学习 OpenCL 的几个月里发现的有用和平易近人的调试信息是多么少,我认为写下来的努力可能会对处于我位置的其他人有所帮助,因为我的问题的解决方案对于初学者来说并不明显。
上下文:我正在写一个光线追踪器,对我的 C 有限制,但允许在学校使用 OpenCL。我已经构建并调试了一个 OpenCL RNG 库,我可以从简单的内核调用它,将一些算法移植到子函数中,但我仍在学习内存管理和将大型算法分解为有组织的内核序列以进行排队。
OS:Xubuntu 18.04
平台:NVIDIA CUDA |设备:GeForce GTX 950M |版本:OpenCL 1.2 CUDA
我的数据变得不连贯:printf() 告诉我,我的数据存在于我的第二个内核(发生问题的那个)并且是连贯的;但它从未遇到相应 'if' 语句中的检查。更糟糕的是,它似乎清楚地读取了 'false' 的 if 语句,考虑到 GPU 控制流的怪异,我不知所措。
互联网上的两个页面讨论的主题与我得到的最相似,但这两个都不是我的问题(这可能是你的问题,这就是我添加它们的原因):
https://community.amd.com/thread/225707
https://computergraphics.stackexchange.com/questions/4115/gpu-branching-if-without-else
为了调试,我在子函数中使用了以下代码片段,returns 主内核(调用它)的像素颜色。
if (isequal((float)scene->camera.c_to_w.sF, (float)0.))
{
return ((float3)(0., 255., 0.));
}
else if (isequal((float)scene->camera.c_to_w.sF, (float)0.5))
{
return ((float3)(255., 0., 255.));
}
else //if (some other condition)
return ((float3)(255., 255., 0.));
没有此代码段的函数返回黑屏。否则,它根据以下行为返回一个 if 语句颜色的屏幕。
分别和一起注释掉 "else" 语句并使用这些值,我发现:只要这个片段存在,就一定会读取其中一个 'return (R,G,B)';如果其中至少有一个为真,它将被读取,否则行为始终是这个可变长度 if-else 序列的第一个条件。
我的错误是 get_pixel_color() 子函数末尾缺少行 "return (result_pixel_color);"。是的,我很笨
OpenCL 编译器似乎不会像大多数 C 编译器那样警告您 'control flow reached end of non-void function before return' 类型错误。在我的例子中,缺少 return 的未定义行为采用了将函数中的任何 return 作为控制流的一般 return 的方法。如果这个错误可以滑动,OpenCL 编译器可能不会警告您其他经典错误:对您自己的代码更加挑剔!
这是一个更笼统的陈述,但我觉得它可能对学习 OpenCL 时遇到一些隐蔽错误的人有用。我的问题是我高估了 OpenCL 编译器的帮助,特别是考虑到我的代码的大小。我们试图在不同的 .cl 文件中包含许多子函数,并带有 .cl.h header 以使其在架构和注释中清晰易读且模块化:这是一个团队项目,但我已经最了解 OpenCL。 .. 似乎大部分内核编码实际上是关于使函数长数百行,这对于可维护性和模块化 IMO 来说确实是一个问题。每个文件超过 1 个内核,每个程序超过 1 个文件,您开始 运行 遇到问题,尤其是在编译方面。对于像 (bidirectional/fast/etc) 路径追踪这样的复杂算法,它需要对许多不同类型的大数据、加速结构进行建模,并以 workgroup-coherent 的方式将光线分类到 运行 个交叉点,你应该小心编译器,你永远不知道 dumb/mundane 你的错误究竟是什么。
首先,这是我第一次真正觉得有必要在 Whosebug 上提问,但我在 rubberducking 和破解我自己的 OpenCL 代码时解决了我的问题。然而,考虑到我在学习 OpenCL 的几个月里发现的有用和平易近人的调试信息是多么少,我认为写下来的努力可能会对处于我位置的其他人有所帮助,因为我的问题的解决方案对于初学者来说并不明显。
上下文:我正在写一个光线追踪器,对我的 C 有限制,但允许在学校使用 OpenCL。我已经构建并调试了一个 OpenCL RNG 库,我可以从简单的内核调用它,将一些算法移植到子函数中,但我仍在学习内存管理和将大型算法分解为有组织的内核序列以进行排队。
OS:Xubuntu 18.04 平台:NVIDIA CUDA |设备:GeForce GTX 950M |版本:OpenCL 1.2 CUDA
我的数据变得不连贯:printf() 告诉我,我的数据存在于我的第二个内核(发生问题的那个)并且是连贯的;但它从未遇到相应 'if' 语句中的检查。更糟糕的是,它似乎清楚地读取了 'false' 的 if 语句,考虑到 GPU 控制流的怪异,我不知所措。
互联网上的两个页面讨论的主题与我得到的最相似,但这两个都不是我的问题(这可能是你的问题,这就是我添加它们的原因):
https://community.amd.com/thread/225707
https://computergraphics.stackexchange.com/questions/4115/gpu-branching-if-without-else
为了调试,我在子函数中使用了以下代码片段,returns 主内核(调用它)的像素颜色。
if (isequal((float)scene->camera.c_to_w.sF, (float)0.))
{
return ((float3)(0., 255., 0.));
}
else if (isequal((float)scene->camera.c_to_w.sF, (float)0.5))
{
return ((float3)(255., 0., 255.));
}
else //if (some other condition)
return ((float3)(255., 255., 0.));
没有此代码段的函数返回黑屏。否则,它根据以下行为返回一个 if 语句颜色的屏幕。 分别和一起注释掉 "else" 语句并使用这些值,我发现:只要这个片段存在,就一定会读取其中一个 'return (R,G,B)';如果其中至少有一个为真,它将被读取,否则行为始终是这个可变长度 if-else 序列的第一个条件。
我的错误是 get_pixel_color() 子函数末尾缺少行 "return (result_pixel_color);"。是的,我很笨
OpenCL 编译器似乎不会像大多数 C 编译器那样警告您 'control flow reached end of non-void function before return' 类型错误。在我的例子中,缺少 return 的未定义行为采用了将函数中的任何 return 作为控制流的一般 return 的方法。如果这个错误可以滑动,OpenCL 编译器可能不会警告您其他经典错误:对您自己的代码更加挑剔!
这是一个更笼统的陈述,但我觉得它可能对学习 OpenCL 时遇到一些隐蔽错误的人有用。我的问题是我高估了 OpenCL 编译器的帮助,特别是考虑到我的代码的大小。我们试图在不同的 .cl 文件中包含许多子函数,并带有 .cl.h header 以使其在架构和注释中清晰易读且模块化:这是一个团队项目,但我已经最了解 OpenCL。 .. 似乎大部分内核编码实际上是关于使函数长数百行,这对于可维护性和模块化 IMO 来说确实是一个问题。每个文件超过 1 个内核,每个程序超过 1 个文件,您开始 运行 遇到问题,尤其是在编译方面。对于像 (bidirectional/fast/etc) 路径追踪这样的复杂算法,它需要对许多不同类型的大数据、加速结构进行建模,并以 workgroup-coherent 的方式将光线分类到 运行 个交叉点,你应该小心编译器,你永远不知道 dumb/mundane 你的错误究竟是什么。