2011-10-11 152 views
2

我刚刚得知编译器巧妙地将函数和变量的调用替换为它们所代表的代码。考虑到这一点,第二种方法事实上会比以下更好(由于清晰度),实际上运行速度与第一种方法一样快?编译器优化

//check to see if sphere intersects the box 
bool BoundingBox::Intersects(BoundingSphere boundingSphere) 
{ 
// check for intersection on each axis by seeing if the radius is large enough to reach the edge of the cube on the 
// appropriate side. All must evaluate to true for there to be an intersection. 
return (
    ((boundingSphere.Centre().x < negCorner.x && boundingSphere.Radius() > posCorner.x - boundingSphere.Centre().x) || 
    (boundingSphere.Centre().x > posCorner.x && boundingSphere.Radius() > boundingSphere.Centre().x - negCorner.x)) 
    && 
    ((boundingSphere.Centre().y < negCorner.y && boundingSphere.Radius() > posCorner.y - boundingSphere.Centre().y) || 
    (boundingSphere.Centre().y > posCorner.y && boundingSphere.Radius() > boundingSphere.Centre().y - negCorner.y)) 
    && 
    ((boundingSphere.Centre().z < negCorner.z && boundingSphere.Radius() > posCorner.z - boundingSphere.Centre().z) || 
    (boundingSphere.Centre().z > posCorner.z && boundingSphere.Radius() > boundingSphere.Centre().z - negCorner.z))); 
} 

第二种方法:

//check to see if sphere intersects the box 
bool BoundingBox::Intersects(BoundingSphere boundingSphere) 
{ 
bool xIntersects, yIntersect, zIntersects; 

xIntersects = 
    ((boundingSphere.Centre().x < negCorner.x && boundingSphere.Radius() > posCorner.x - boundingSphere.Centre().x) || 
    (boundingSphere.Centre().x > posCorner.x && boundingSphere.Radius() > boundingSphere.Centre().x - negCorner.x))); 

yIntersects = 
      ((boundingSphere.Centre().y < negCorner.y && boundingSphere.Radius() > posCorner.y - boundingSphere.Centre().y) || 
    (boundingSphere.Centre().y > posCorner.y && boundingSphere.Radius() > boundingSphere.Centre().y - negCorner.y))); 

zIntersects = 
      ((boundingSphere.Centre().z < negCorner.z && boundingSphere.Radius() > posCorner.z - boundingSphere.Centre().z) || 
    (boundingSphere.Centre().z > posCorner.z && boundingSphere.Radius() > boundingSphere.Centre().z - negCorner.z))); 

return (xIntersects && yIntersects && zIntersects); 
} 
+0

也许这不是最好的例子,因为它们都比较相似,但是想法是第二个更清晰但使用更多线条。 – SirYakalot

+1

在某种程度上取决于你使用的编译器以及它如何优化代码:) – Eilidh

+3

这更多的是关于可读性和优化。 – Philip

回答

1

首先,这不是一个准确的球体与盒子检查。它本质上是一个破碎的(当球体中心被包含在盒子里时,它不会报告交叉点!)盒子与盒子周围的球体测试。如果你想这样做的话,寻找阿沃的算法。

但是回到你的问题:如果存在可测量的速度差异,并且我怀疑存在,那么肯定不会与内联相关,而是与两个函数的稍微不同的语义相关。第一个函数通过&&运算符对其顶级进行懒惰评估。所以如果你在第一轴上得到一个负面的结果,它会碰撞出来,而不是测试其他的结果。如果在该轴或第二个轴上有足够的负面结果,这可能会为您在速度非常慢的计算机上带来速度优势。

第二个函数不会检查您在前一轴上是否得到否定答案。因此,它总是会测试所有三个。现在,在一台体面的计算机上这可能会更快,因为它不必等待第一次检查的结果,以确定它是否可能执行接下来的检查。因此,这种分支预测误差较小,通常比两个分支的工作都要快。

再次,优化程序可能会让我足够聪明地发现,它可以在没有副作用的情况下在&&运算符的另一侧执行表达式。内联(明确地或通过链接时代代码生成)在这里实际上扮演着一个小角色 - 因为优化器需要看看函数实际执行的功能。

但是唯一可以确定的方法是查看生成的代码并进行基准测试!

+0

谢谢你指点我朝向阿沃 – SirYakalot

8

没有你的预期行为的保证 - 编译器必须足够聪明才能制定出它没有计算所有的条件x/y/z返回结果之前。

在第一个版本中,你知道你会在第一次失败的测试中返回。我坚持这一点,并评论和格式化代码,使其更清晰。

+0

我同意。唉,我没票了。 –

1

我会争论这两者的组合。你想检查xIntersects && yIntersects && z Intersects,所以让他们每个人都有自己的功能。像这样:

bool BoundingBox::Intersects(BoundingSphere boundingSphere) 
{ 
    return XIntersects(boundingSphere) && YIntersects(boundingSphere) && ZIntersects(boundingSphere); 
} 

bool BoundingBox::XIntersects(BoundingSphere boundingSphere) 
{ 
    return ((boundingSphere.Centre().x < negCorner.x && boundingSphere.Radius() > posCorner.x - boundingSphere.Centre().x) || 
      (boundingSphere.Centre().x > posCorner.x && boundingSphere.Radius() > boundingSphere.Centre().x - negCorner.x)); 
} 
bool BoundingBox::YIntersects(BoundingSphere boundingSphere) 
{ 
    return ((boundingSphere.Centre().y < negCorner.y && boundingSphere.Radius() > posCorner.y - boundingSphere.Centre().y) || 
      (boundingSphere.Centre().y > posCorner.y && boundingSphere.Radius() > boundingSphere.Centre().y - negCorner.y)); 
} 
bool BoundingBox::ZIntersects(BoundingSphere boundingSphere) 
{ 
    return ((boundingSphere.Centre().z < negCorner.z && boundingSphere.Radius() > posCorner.z - boundingSphere.Centre().z) || 
      (boundingSphere.Centre().z > posCorner.z && boundingSphere.Radius() > boundingSphere.Centre().z - negCorner.z)); 
} 

你得到第一的速度和第二的清晰度,以及优化的编译器甚至可以优化出来的函数调用。