Kernel函数中能否大量使用if、 else if 、 while(例如树查找)

数据:2000×2000条光线、采用二叉树数据结构进行组织的三角面片集合
问题描述:我想将每一条光线均与上述三角面片集合的二叉树结构进行求交计算,光线数据、二叉树数据已传递至显存中,并用Grid、Block对2000×2000条光线进行合理组织。

然而,由于cuda不支持二叉树的递归求交计算,于是我采用迭代法进行二叉树的求交计算,并设计了一个光线与二叉树结构求交计算的kernel函数,该函数约500行,其中大量使用了if、else if、while等,调试时有时会出现满足条件A,且执行代码1后,还会跳至代码2或者代码3(实际上不能足条件B和C)

if(A)
{
   代码1;
}
else if(B)
{
  代码2;
}
else if(C)
{
  代码3;
}

或者出现如下问题,条件ObNdArray[nCurTrcKdDepth].bIsNull || ObNdArray[nCurTrcKdDepth].bIsTracing为假,但调试时会直接跳至代码252行,随后才会执行else后的语句[attach]2960[/attach]

LZ您好,仅就kernel里面“能不能”进行如上的分支操作,答案是“可以”。而且应该没有任何问题可以维持您所预期的逻辑意图。

此外,如果分支情况比较复杂和随机,那么效率可能会受到比较大的影响。

第三,您说的调试的时候的这种情况,我不是很清楚,不过估计可能是“假执行”,即虽然执行了,但是不保存结果,从而在逻辑上依然是正确的。

个人观点大致如上,供您参考。

祝您元宵佳节愉快!

恩,感谢版主的回答,亦祝版主元宵佳节快乐!

此外,如果分支情况比较复杂和随机,那么效率可能会受到比较大的影响。

kernel中确实有比较复杂的分支情况,请问版主有什么方案可以提高效率么?

一般来说,如果分支的情况是确定的(也就是提前可以知道的),那么使分支按照warp对齐(即同一个warp里面都走同一条分支)是一种解决方案。

而,如果是随机获取条件进行分支,或者分支情况十分复杂,我还不清楚如何解决,请其他人补充。

祝LZ好运。

首先谢谢楼主!
由于是对二叉树进行迭代(递归)查找,因此涉及到比较复杂的分支情况…

具体这个算法我就不清楚了,看看论坛有没有其他人熟悉的和你进一步讨论讨论。

祝您一切顺利~

这个现象我不记得遭遇过,

对于短的语句,的确会产生@p inst;的形式。
但是为了防止给你在debugging的时候造成迷惑,开启了-G选项后,生成的代码会最终在短分支的@p …之前,强制加入一条@!p bra …;进行跳转到else部分,以避免进入了虽然无效果的但却会带来困惑的短@p …语句部分。

所以一般你应该看不到这个现象才对。

我建议现尝试使用最新版的nsight/toolkit/driver并rebuild all后,看问题是否消失。

以及,如果在您升级到最新版本后, 问题依然存在,我建议您联系nvidia原厂支持,以确定此问题是出现在您个体、编译器、调试器的究竟哪一方。

对了,需要有的时候,在您这种嵌套的if中,有的时候的确会显示出问题。

例如假设您的例子,在外层的if成立,但是内层的if不成立,此时在执行到外层的if生成的代码的最后几句的时候,调试器会错误的对应到外层if和里层if的共同的最后一行(您的那个return false处)。这个是个已知BUG.

但此BUG不会在您的描述“条件ObNdArray[nCurTrcKdDepth].bIsNull || ObNdArray[nCurTrcKdDepth].bIsTracing为假”下出现。

除非您的描述不是"ObNdArray…不成立“,而是改为“ObNdArray…成立,但nCurTrc…不成立", 方有可能触发。

请仔细检查是否存在您存在错误的问题描述的情况,我们只有完全信任、采纳您提供的描述的情况下,方能有效的为您解决问题。

谢谢版主的详解!
版主说的那个BUG确实被我碰到了,调试发现并不会影响计算的准确性。
然而现在遇到一个程序运行黑屏的问题,我重新开个帖子讨论吧!

嗯嗯。感谢楼主回复。其实楼主你碰到的不是这个BUG. 您可以仔细看我和你的说法的不同。:slight_smile:

您的新贴已经回复。