Parallel processing openCL光线跟踪和分支内核代码问题

Parallel processing openCL光线跟踪和分支内核代码问题,parallel-processing,kernel,opencl,gpu,raytracing,Parallel Processing,Kernel,Opencl,Gpu,Raytracing,因此,我正在尝试使用openCL实现一个光线/路径跟踪器,它看起来非常简单——编写一个内核,跟踪单个光线/像素/等的路径,并在多条光线上并行执行 但是,当遍历场景时,一条光线可以有相当多的方向。例如,根据命中对象的材质,光线可以反射或折射。此外,不同的材质需要不同的着色算法。例如,如果一个场景对象需要cook-torrance着色器,而另一个场景对象需要ward各向异性着色器,则需要在内核中调用不同的着色函数 根据我所阅读的内容,在内核中包含分支代码是不明智的,因为这会影响性能。但在光线跟踪器中

因此,我正在尝试使用openCL实现一个光线/路径跟踪器,它看起来非常简单——编写一个内核,跟踪单个光线/像素/等的路径,并在多条光线上并行执行

但是,当遍历场景时,一条光线可以有相当多的方向。例如,根据命中对象的材质,光线可以反射或折射。此外,不同的材质需要不同的着色算法。例如,如果一个场景对象需要cook-torrance着色器,而另一个场景对象需要ward各向异性着色器,则需要在内核中调用不同的着色函数

根据我所阅读的内容,在内核中包含分支代码是不明智的,因为这会影响性能。但在光线跟踪器中,如果我基于每条光线并行化代码,这似乎是不可避免的

那么,“分支”代码结构真的对内核性能有那么大的阻碍吗?如果是这样的话,我将如何构建代码来解释这一点

第一遍(1M条射线)、无符号字符数组(甚至压缩单位)

排序(缓存或多路复用以重新用于折射和反射) 具有曲面类型(存在/不存在)和曲面位置(时间相关性)


现在有两组1M的光线,在每次迭代时加倍。所以,如果你有256M元素的空间,你应该能够投射光线直到深度7或8。所有这些都可以通过适当的索引在单个数组上完成。

不要进行分支,而是将“1”保存到数组元素中作为“待分支”(“0”表示非待分支)并对数组进行排序,以便所有分支彼此相邻,无分支的“0”彼此相邻,因此SIMD可以更快地得到它想要的东西,因为所有元素都做相同的事情(仅分支或仅非分支)在多个过程(迭代)中,而不是伪递归(以指数方式降低性能)。单个基数排序过程可以做到这一点。我的意思是,在第二个过程中,内核查找“1”进行分支,并继续跟踪波束和“0”在这里结束并获得像素的颜色。我仍然有点困惑。首先,当你说要使用“多次通过”时你的意思是不同的内核调用?光线排序在哪里发生,在内核还是在主机上?如果是在主机上,这不会影响性能吗?在任何情况下,我们仍然不确定整个控制流。就像你说的在内核1中有一个光线缓冲区,跟踪它们直到它们到达某个位置,然后将它们分成内核2和内核23根据它们击中的位置,再次跟踪,等等?感谢这个深思熟虑的答案。这无疑为我需要做的事情提供了一个开始参考(不知何故,我必须从中推断出如何不仅进行反射/折射,而且还进行多个着色算法、不同形状类型的相交测试等)。对于单内核版本,您可以从每个工作组的songle像素开始,然后在单个工作组中分支并生成光线(refr/refl),直到深度达到6-7(128/256条光线)直到工作组无法再接受它,然后用下一个像素重复这个过程,这样的内核会很慢,但我可以说内核启动开销会很小。使用全局内存,我想你可以很容易地拥有30-40个深度。这个方法的实现在哪里存在吗?这是一个不错的工作,你可以看看。
   ray 0     ------------------  render end  -------------->   0     \
   ray 1     ------------------  surface    --------------->   1      \
   ray 2     ------------------  surface    --------------->   1        }-- bad for SIMD
   ray 3     ------------------  render end  -------------->   0      /
   ray 4     ------------------  surface    --------------->   1     /
   ...
   ...
   ray 1M    ...
   ray 1  \
   ray 2   -------------------- all surfaces --------------> 1   good for simd
   ray 4  /
   ray 0  \
   ray x   -------------------- all render end ------------> 0   good for simd
   ray 3  /

   second pass (refraction)  (1M rays)

   ray 1  ..................... refract ...................> cast a new ray  
   ray 2  ..................... refract ...................> cast a new ray
   ray 4  ..................... refract ...................> cast a new ray
   ray 0  .................... no new ray casting .........> offload some other work/draw 
   ray x  .................... no new ray casting .........> offload some other work/draw
   ray 3  .................... no new ray casting .........> offload some other work/draw

   third pass (reflection) (1M rays)

   ray 1  ..................... reflect...................> cast a new ray  
   ray 2  ..................... reflect...................> cast a new ray
   ray 4  ..................... reflect...................> cast a new ray
   ray 0  .................... no new ray casting .........> offload some other work/draw 
   ray x  .................... no new ray casting .........> offload some other work/draw
   ray 3  .................... no new ray casting .........> offload some other work/draw