2011-10-11 140 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)); 
} 

你得到第一的速度和第二的清晰度,以及優化的編譯器甚至可以優化出來的函數調用。