2013-04-29 17 views
2

這是微型優化,還是它是最優化的?C++這是微型優化的一種形式

void Renderer::SetCamera(FLOAT x, FLOAT y, FLOAT z) { 
    // Checking for zero before doing addition? 
    if (x != 0) camX += x; 
    if (y != 0) camY += y; 
    if (z != 0) camZ += z; 

    // Checking if any of the three variables are not zero, and performing the code below. 
    if (x != 0 | y != 0 | z != 0) { 
     D3DXMatrixTranslation(&w, camX, camY, camZ); 
    } 
} 

會運行一個具有vector.size()條件的for循環強制應用程序重新計算每個循環中向量中的元素?

std::vector<UINT> vect; 

INT vectorSize = vect.size(); 
for (INT Index = 0; Index < vectorSize; Index++) { 
// Do vector processing 
} 

// versus: 

std::vector<UINT> vect; 

for (INT Index = 0; Index < vect.size(); Index++) { 
// Do vector processing 
} 

我使用Visual Studio和作爲第二個問題,它看起來像是一個編譯器可以優化,但我只是不知道這一點。

回答

5

根據矢量的實現,編譯器可能會或可能不知道大小沒有改變。畢竟,你在循環中調用了不同的矢量函數,其中任何一個都可能改變大小。

因爲vector是一個模板,所以編譯器知道它的一切,所以如果它真的很難,可能明白大小不會改變,但這可能太多了。

通常情況下,你會想這樣寫:

for (size_t i = 0, size = vect.size(); i < size; ++i) 
    ... 

雖然我們在這,一個類似的方法是使用迭代器:

for (list<int>::iterator i = lst.begin(), end = lst.end(); i != end; ++i) 
    ... 

編輯:我錯過了第一部分:

這是優化嗎?

if (x != 0) camX += x; 
if (y != 0) camY += y; 
if (z != 0) camZ += z; 

號首先,即使他們是整型,它不會是因爲檢查而當值很可能大部分時間不爲零更多的工作分支優化。

其次,更重要的是,它們是浮動的。這意味着除了you shouldn't directly compare them to 0之外,它們基本上幾乎不會完全等於0.因此,if的值爲99.9999%爲真。

同樣適用於這樣的:

if (x != 0 | y != 0 | z != 0) 

在這種情況下,但是由於矩陣轉換可能是昂貴的,你可以這樣做:

#define EPS 1e-6 /* epsilon */ 
if (x > EPS || x < -EPS || y > EPS || y < -EPS || z > EPS || z < -EPS) 

,現在是,比較矩陣乘法,這可能是一個優化。

還請注意,我使用||,如果例如從頭開始x > EPS爲真(它不會計算其餘部分),那麼它將被短路,但是|不會發生。

+0

如果這些值大部分時間都是「int」並且爲零,它會不會反效果呢?我的意思是,檢查和分支似乎並不比加入零更快。 – zakinster 2013-04-29 17:03:59

+0

@zakinster,如果他們大部分時間都是int並且爲零,那真的取決於架構。我和你一起認爲最可能的是繼續前進並添加它,但你永遠不知道所有(奇怪)的體系結構。 – Shahbaz 2013-04-29 17:06:01

+1

即使在大多數情況下它是'int'並且爲零,如果'camX'上的緩存讀取錯誤接近100%,它只會更快。 @zakinster – dialer 2013-04-29 17:08:46

2

我懷疑在許多體系結構中,前三行是反優化,因爲它們可能會引入浮點比較,然後分支,這比只是總是添加(即使是浮點)要慢。

另一方面,確保在進行轉換之前,至少有一個組件是非零的。

對於你的第二種情況,size必須是恆定的時間,幾乎肯定會被內聯到直接訪問vector的大小。這很可能是完全優化的。也就是說,有時它可以通過保存大小來讓代碼/循環變得更容易閱讀,因爲它清楚地表明你斷言在循環過程中大小不會改變。

2

首先,關於vector.size(),參見 this SO question。在旁註中,我沒有看到std::vector::size()不是O(1)的實現。

if (x != 0) camX += x;這個cmp和因此jne然而,要比簡單地添加變量x無論如何都要慢。 編輯:除非您預計超過50%的高速緩存未命中的camX

1

第一種可能是pessimisation,0檢查可能比加法慢。最重要的是,在撥打D3DXMatrixTranslation之前的檢查中,您使用|而不是短路邏輯或||。由於在函數調用前的檢查可能是一個節省時間(甚至語義必要),包裹在檢查整個代碼,

void Renderer::SetCamera(FLOAT x, FLOAT y, FLOAT z) { 

    if (x != 0 || y != 0 || z != 0) { 
     camX += x; 
     camY += y; 
     camZ += z; 
     D3DXMatrixTranslation(&w, camX, camY, camZ); 
    } 
} 

如果所有的xyz是零,沒有什麼需要做否則,盡一切努力。

對於第二,編譯器可以吊起vector.size()循環外,如果它能夠確定的尺寸不同時循環運行而改變。如果編譯器無法確定,則不得在循環外部提起計算size()

當你知道尺寸沒有改變時自己這樣做是一種很好的做法。

+0

我真的很喜歡你的答案。 Pessimization是我不得不添加到字典中的一個新詞。 :) 我很喜歡。 – 2013-04-29 17:12:25