GLSL 中数学运算的计算成本

Computational cost of math operations in GLSL

我正在使用 GLSL 着色器编写 GPGPU 程序,并试图为 N 体碰撞检测算法提出一些优化。一个是执行 'quick' 检查以确定两个对象是否在同一范围内。这个想法是快速取消很多可能性,这样我只需要对少数物体进行更准确的碰撞测试。如果快速检查确定它们有可能发生碰撞,则会执行准确检查。

对象是圆形(或球体)。我知道它们的中心位置和半径。快速检查将查看它们的方形(或立方体)边界框是否重叠:

//make sure A is to the right of and above B
//code for that

if(A_minX > B_maxX) return false;   //they definitely don't collide
if(A_minY > B_maxY) return false;   //they definitely don't collide

if(length(A_position - B_position) <= A_radius + B_radius){
    //they definitely do collide
    return true;
}

我的问题是执行此快速检查(确保 A 和 B 的顺序正确,然后检查它们的边界框是否重叠)的开销是否会比调用 length() 和将其与它们的组合半径进行比较。

了解 GLSL 中各种数学运算的相对计算成本会很有用,但我不太确定如何根据经验发现它们,或者这些信息是否已经发布在某个地方。

虽然我们讨论的是成本,但您在这里不需要两个分支。您可以改为测试组件测试的结果。因此,可以使用 any (greaterThan (A_min, B_max)) 将其合并为一个测试。一个好的编译器可能会解决这个问题,但如果您自己考虑数据并行性,它会有所帮助。

成本都是相对的。 15 年前,完成 length (...) 所需的算术工作使得您可以在更短的时间内进行立方体贴图纹理查找 - 在较新的硬件上,您这样做会很疯狂,因为计算比内存更快。

综上所述,线程发散比指令或内存吞吐量更可能成为瓶颈。也就是说,如果您的两个着色器调用 运行 并行采用不同的路径通过着色器,您可能会引入不必要的性能损失。底层硬件架构意味着曾经是优化安全赌注的东西可能不会在未来出现,甚至可能导致您的优化尝试损害性能。

您可以通过比较值的平方来避免使用平方根(length() 函数隐式需要)。

测试可能如下所示:

vec3 vDiff = A_position - B_position;
float radSum = A_radius + B_radius;
if (dot(vDiff, vDiff) < radSum * radSum) {
    return true;
}

这将它减少回单个测试,但仍然只使用简单高效的操作。