回答
它有所不同,首先從檢查不同的指令集開始,以及編譯器如何使用這些指令集。以openrisc 32爲例,這顯然是mips的靈感,但條件不同。對於or32有比較和置位標誌指令,比較這兩個寄存器如果小於或等於無符號則設置標誌,比較這兩個寄存器是否相等設置標誌。然後有兩個條件分支指令在標誌集上分支並在標誌清除時分支。編譯器必須遵循這些路徑之一,但少於,少於或等於,大於等等都將使用相同數量的指令,相同的執行時間用於條件分支,相同的執行時間用於不執行條件分支。
現在,對於大多數架構來說,執行分支需要比不執行分支更長的時間,因爲必須刷新並重新填充管道。一些分支預測等可以幫助解決這個問題。
現在一些體系結構的指令大小可能會有所不同,比較gpr0和gpr1與比較gpr0和立即數1234,可能需要更大的指令,例如x86中會看到很多。所以雖然這兩種情況可能是一個分支,如果少於你如何編碼,取決於哪些寄存器碰巧保持什麼值會導致性能差異(當然,x86會做很多流水線處理,大量緩存等來彌補這些問題)。另一個類似的例子是mips和or32,其中r0總是零,它不是一個真正的通用寄存器,如果你寫它,它不會改變,它是硬連線到零,所以比較,如果等於0可能會花費你如果需要額外的指令或兩個指令來填充gpr以使比較可能發生,最壞的情況是必須將寄存器驅逐到堆棧或存儲器,釋放註冊立即在那裏,以便可以發生比較。
某些架構,條件執行像手臂,爲全面臂(未拇指)的指令,你可以在每個指令的基礎上執行的,所以如果你有代碼
if(i==7) j=5; else j=9;
對手臂的僞代碼將是
cmp i,#7
moveq j,#5
movne j,#7
沒有實際的分支,所以沒有管道問題你飛輪通過,非常快。
一個體繫結構到另一個如果這是一個有趣的比較一些提到的,mips或32,你必須專門執行某種比較的指令,其他像x86,msp430和絕大多數每個alu操作改變標誌,手臂等改變標誌,如果你告訴它改變標誌,否則不要如上所示。所以
while(--len)
{
//do something
}
環1減法還設置了標誌,如果在循環中的東西是很簡單的,你可以使整個事情的條件,因此可以節省您的獨立的比較和分支指令並且您在保存管道罰款。 Mips通過比較解決了這一點,並且分支是一條指令,並且它們在分支之後執行一條指令以在管道中保存一點。
一般的答案是你不會看到差異,指令的數量,執行時間等等對於各種條件是相同的。特殊情況下,如小立即比較大的立即數等可能會對角落案例產生影響,或者編譯器可能會根據您做的比較而選擇完全不同。如果您嘗試重寫您的算法以使其給出相同的答案,但使用小於而不是大於等於,則可以更改代碼以獲得不同的指令流。同樣,如果您執行的性能測試過於簡單,編譯器可以/將優化比較完成並僅生成結果,這可能會因您的測試代碼而異,從而導致不同的執行。所有這些的關鍵是反彙編你想比較的東西,看看指令的不同之處。這將告訴你,如果你應該期望看到任何執行差異。
TL; DR
似乎有小到無的四大運營商之間的差異,因爲它們都執行大約在同一時間,我(可能在不同的系統,不同的!)。所以,如果有疑問,只需使用對情況最有意義的運算符(特別是在使用C++時)。
所以,事不宜遲,這裏是長的解釋:
假設整數比較:
至於組件產生,結果是依賴於平臺。在我的電腦公司(Apple LLVM編譯器4.0,x86_64的),結果(生成的安裝步驟如下):
a < b (uses 'setl'):
movl $10, -8(%rbp)
movl $15, -12(%rbp)
movl -8(%rbp), %eax
cmpl -12(%rbp), %eax
setl %cl
andb $1, %cl
movzbl %cl, %eax
popq %rbp
ret
a <= b (uses 'setle'):
movl $10, -8(%rbp)
movl $15, -12(%rbp)
movl -8(%rbp), %eax
cmpl -12(%rbp), %eax
setle %cl
andb $1, %cl
movzbl %cl, %eax
popq %rbp
ret
a > b (uses 'setg'):
movl $10, -8(%rbp)
movl $15, -12(%rbp)
movl -8(%rbp), %eax
cmpl -12(%rbp), %eax
setg %cl
andb $1, %cl
movzbl %cl, %eax
popq %rbp
ret
a >= b (uses 'setge'):
movl $10, -8(%rbp)
movl $15, -12(%rbp)
movl -8(%rbp), %eax
cmpl -12(%rbp), %eax
setge %cl
andb $1, %cl
movzbl %cl, %eax
popq %rbp
ret
這是不是真的告訴我了。所以,我們跳到基準測試:
和女士&先生們,結果在,我創建了以下測試程序(我知道'時鐘'不是計算這種結果的最好方法,但它現在必須要做)。
#include <time.h>
#include <stdio.h>
#define ITERS 100000000
int v = 0;
void testL()
{
clock_t start = clock();
v = 0;
for (int i = 0; i < ITERS; i++) {
v = i < v;
}
printf("%s: %lu\n", __FUNCTION__, clock() - start);
}
void testLE()
{
clock_t start = clock();
v = 0;
for (int i = 0; i < ITERS; i++)
{
v = i <= v;
}
printf("%s: %lu\n", __FUNCTION__, clock() - start);
}
void testG()
{
clock_t start = clock();
v = 0;
for (int i = 0; i < ITERS; i++) {
v = i > v;
}
printf("%s: %lu\n", __FUNCTION__, clock() - start);
}
void testGE()
{
clock_t start = clock();
v = 0;
for (int i = 0; i < ITERS; i++) {
v = i >= v;
}
printf("%s: %lu\n", __FUNCTION__, clock() - start);
}
int main()
{
testL();
testLE();
testG();
testGE();
}
其中,我的機器(帶-O0
編譯)上,給了我這個(5次獨立運行):
testL: 337848 testLE: 338237 testG: 337888 testGE: 337787 testL: 337768 testLE: 338110 testG: 337406 testGE: 337926 testL: 338958 testLE: 338948 testG: 337705 testGE: 337829 testL: 339805 testLE: 339634 testG: 337413 testGE: 337900 testL: 340490 testLE: 339030 testG: 337298 testGE: 337593
我認爲,這些運營商之間的差異是次要的,在最好的,不要在現代計算機世界中不佔重要地位。
彙編代碼實際上告訴了很多。這是說,所有這些片段必須完全相同,所有情況都是平等的。 'setcc'需要1個週期(P4除外,需要3個週期),而不管cc是什麼。但這又如何相關?比較運算符幾乎從不以這種方式使用 - 比較'jcc'的性能(不管cc是什麼)似乎更合理。 – harold 2012-08-01 17:15:53
我第二@harold。程序集講述了很多 - 所有的比較都是使用相同的'cmpl'指令完成的,它比較了它的參數。基本上它從第一個參數中減去第二個參數(丟棄結果),ALU設置標誌寄存器中的相應位。然後可以對這些進行測試,根據或用於設置內存/寄存器值。 – 2012-08-01 18:17:26
@harold他大概的意思是「它不會告訴_me_多」 – hirschhornsalz 2012-08-01 18:43:33
- 1. 哪一個是更快的字符串[]或列表<string>
- 2. 哪個.NET集合更快:枚舉foreach Dictionary <>。Values或List <>?
- 3. >><<和運算符重載
- 4. C++ << >>運算符
- 5. 按位運算符「>>」和「<<」?
- 6. 哪個布爾更快? <或<=
- 7. C++重載運算符<<和運算符>>
- 8. <script>或<noscript>?
- 9. QList <QString>運算符<<
- 10. 哪個更好:<腳本類型= 「文/ JavaScript的」> ...</script>或<script> ...</script>
- 11. 哪一個更快/更高效:Dictionary <字符串,對象>或字典<enum,object>?
- 12. IE事件<input>或<textarea>或<textarea>
- 13. 定義布爾邏輯運算符(V,^,異或, - >,<->)
- 14. 運算符重載'<<' and '>>'和一個字符串
- 15. 條件運算符<pre><code><%#Eval("TaxAmount")%> <%#Eval("TaxGroup")%> </code></pre>
- 16. 要使用哪個Seam組件:<h:outputLink>或<h:commandLink>?
- 17. 應該使用哪一個:python- <module>或<module> -python?
- 18. <Provider /> outside或<Router /> outside>?
- 19. C++運算符「<" and ">」
- 20. PHP運算符<>
- 21. 在<head>,其中第一個:<meta>或<title>?
- 22. 如</p> <p><code><p>This is text </p></code>或<code><div></code>或<code>This is text</code></p> <p>使用<code>XmlPullParser</code>檢索URL
- 23. 哪個更好 - <aside>或<footer>爲網站的'擴展頁腳'?
- 24. 搜索一個HashMap <字符串,ArrayList的<Users>>或HashMap中<字符串,HashSet的<Users>>
- 25. 鑄造字符串到布爾運算符(<, <=, >,> =)
- 26. System.config()調用<head>或<body>?
- 27. ObjectQuery <T>或IQueryable <T>
- 28. 不能#include <QQuickView>(或<QtQuick>)。
- 29. SortedDictionary <>或(Dictionary <> Manual Sort)
- 30. SharedPreference或Map <String,SoftReference <Bitmap>>
我猜想他們在大多數架構中都可以編譯成單一指令,但答案是:誰在乎? – meagar 2012-08-01 16:17:50
它們在生成彙編指令方面幾乎相同,如果這就是您要求的。 – 2012-08-01 16:18:04
我明白你的問題背後的精神,但是:你是出於學術興趣問這個問題,還是因爲你認爲這可能會影響你的應用的性能?它不會。如果存在的話,這個差異絕對會被你的應用中的其他因素所淹沒**。不是2或10倍,而是1m或更多。我敢打賭你根本無法衡量它。 – 2012-08-01 16:19:38