![](/img/trans.png)
[英]With a single file descriptor, Is there any performance difference between select, poll and epoll and …?
[英]Is there any performance difference between for() and while()?
或者它是關於語義的嗎?
簡答:不,他們完全一樣。
猜測它理論上可能依賴於編譯器; 一個真正破碎的人可能會做一些略有不同的事情,但我會感到驚訝。
只是為了好玩,這里有兩個變種,使用Ubuntu附帶的x86 gcc版本4.3.3編譯為完全相同的匯編代碼。 您可以使用linux上的objdump檢查最終二進制文件上生成的程序集。
int main() { #if 1 int i = 10; do { printf("%d\n", i); } while(--i); #else int i = 10; for (; i; --i) printf("%d\n", i); #endif }
編輯:這是一個“橘子與橘子”,而循環示例也編譯成同樣的東西:
while(i) { printf("%d\n", i); --i; }
如果for和while循環執行相同的操作,編譯器生成的機器代碼應該(幾乎)相同。
比如幾年前我做的一些測試,
for (int i = 0; i < 10; i++)
{
...
}
和
int i = 0;
do
{
...
i++;
}
while (i < 10);
將生成完全相同的代碼,或者(和Neil在評論中指出)使用一個額外的jmp,這將不會在性能上產生足夠大的差異而擔心。
沒有語義差異,不需要任何編譯差異。 但這取決於編譯器。 所以我嘗試使用g ++ 4.3.2,CC 5.5和xlc6。
g ++,CC是相同的,xlc不是
xlc的差異在於初始循環條目。
extern int doit( int );
void loop1( ) {
for ( int ii = 0; ii < 10; ii++ ) {
doit( ii );
}
}
void loop2() {
int ii = 0;
while ( ii < 10 ) {
doit( ii );
ii++;
}
}
XLC輸出
.loop2: # 0x00000000 (H.10.NO_SYMBOL)
mfspr r0,LR
stu SP,-80(SP)
st r0,88(SP)
cal r3,0(r0)
st r3,64(SP)
l r3,64(SP) ### DIFFERENCE ###
cmpi 0,r3,10
bc BO_IF_NOT,CR0_LT,__L40
...
enter code here
.loop1: # 0x0000006c (H.10.NO_SYMBOL+0x6c)
mfspr r0,LR
stu SP,-80(SP)
st r0,88(SP)
cal r3,0(r0)
cmpi 0,r3,10 ### DIFFERENCE ###
st r3,64(SP)
bc BO_IF_NOT,CR0_LT,__La8
...
while
循環測試中變量的范圍比for
循環標題中聲明的變量范圍更寬。
因此,如果存在性能影響作為保持變量更長時間活動的副作用,那么在while和for循環之間進行選擇會產生性能影響(並且不會在{}中包含while,以縮小其范圍。變量)。
一個示例可能是並發集合,它計算引用它的迭代器的數量,如果存在多個迭代器,它會應用鎖定以防止並發修改,但如果只有一個迭代器引用它,優化就會使鎖定失敗。 如果你在一個函數中有兩個for
循環,在同一個容器上使用不同名稱的迭代器,那么將采用快速路徑,但是使用兩個while
循環時將采用慢速路徑。 同樣,如果對象很大(更多緩存流量)或使用系統資源,可能會對性能產生影響。 但我想不出一個我見過的真正的例子,它會產生什么影響。
使用循環展開優化的編譯器可能只在for-loop情況下這樣做。
兩者都是等價的。 這是一個語義問題。
唯一的區別可能在於做... while結構,在那里你推遲條件的評價,直到身體后 ,從而可節省1分的評價。
i = 1; do { ... i--; } while( i > 0 );
而不是
for( i = 1; i > 0; --i )
{ ....
}
我寫編譯器。 我們將所有“結構化”控制流( if
, while
, for
, switch
, do
... while
)編譯成條件和無條件分支。 然后我們分析控制流圖。 由於C編譯器無論如何都必須處理一般goto
,因此最簡單的方法是將所有內容都減少為分支和條件分支指令,然后一定要很好地處理這種情況。 (AC編譯器不僅要在手寫代碼上做得很好,還要在自動生成的代碼上做得很好,這些代碼可能有很多很多的goto
語句。)
不。如果他們正在做相同的事情,他們將編譯成相同的代碼 - 正如你所說,它是關於語義。 選擇最能代表您要表達的內容的那個。
理想情況下它應該是相同的,但最終它取決於您的編譯器/解釋器。 當然,您必須測量或檢查生成的匯編代碼。
證明可能存在差異:這些線使用cc65生成不同的匯編代碼。
for (; i < 1000; ++i);
while (i < 1000) ++i;
Atmel ATMega雖然()比()更快。 為什么在AVR035中解釋了這一點:AVR的高效C編碼。
PS原始平台沒有提到問題。
繼續在for和while中表現不同:in for ,它改變了計數器, 而while通常不會
添加另一個答案:根據我的經驗,優化軟件就像是一個被人剃掉的大而濃密的胡須。
最后一個是for()
和while()
之間的差異,但可能不會產生影響。
PS我認識的程序員(他們都非常好,我懷疑是一個有代表性的樣本)基本上從另一個方向去做。
就性能而言,它們是相同的。 我傾向於使用while
等待狀態改變(例如,等待一個緩沖器被填充),並且當for
處理多個離散的對象(諸如一個集合中的每個項目去)時。
在某些情況下存在差異。
如果您處於這種差異很重要的位置,您需要選擇更好的算法或開始使用匯編語言進行編碼。 相信我,在匯編中編碼比修復編譯器版本更可取。
是while()
快/慢for()
讓我們回顧一下有關優化的一些事情:
編譯器編寫器通過減少調用跳轉,比較,增量以及它們生成的其他類型的指令來非常努力地削減周期。
另一方面,調用指令會消耗更多的周期,但是編譯器幾乎無能為力去除它們。
作為程序員,我們編寫了很多函數調用,有些是因為我們的意思是,有些因為我們很懶,有些因為編譯器將它們滑入而沒有顯而易見。
大多數時候,這並不重要,因為硬件太快了,而且我們的工作很小,以至於計算機就像一只小獵犬,狼吞虎咽地吃着她的食物並且乞求更多。
然而,有時候,這項工作足夠大,以至於性能成為一個問題。
那我們做什么? 哪里有更大的回報?
編譯器不能做后者。 只有我們程序員才能。
我們需要學習或教會如何做到這一點。 它不是自然而然的。 我們先天傾向於做出錯誤的猜測,然后押注於他們。 獲得更好的算法是一個開始,但只是一個開始。 我們的老師需要教這個,如果他們確實知道如何。
Profilers是一個開始。 我這樣做
Willie Sutton在被問到為什么要搶銀行時的虛偽引用? :
因為這就是錢的所在。
如果您想保存周期,請找出它們的位置。
可能只是編碼風格。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.