關於速度,如果我需要計算大量的表情,說:如何C++處理0 *(大表達式)
switch1*(large expression 1)+switch2*(large expression 2)
根據我的投入,switch1
可以0
或1
,因爲可以switch2
是。對於C++來說,最快的做法是做出if語句還是像上面那樣寫下來?
關於速度,如果我需要計算大量的表情,說:如何C++處理0 *(大表達式)
switch1*(large expression 1)+switch2*(large expression 2)
根據我的投入,switch1
可以0
或1
,因爲可以switch2
是。對於C++來說,最快的做法是做出if語句還是像上面那樣寫下來?
所以,本質上則是問有關短路計算,你問C++是否會爲除了布爾表達式算術表達式。
這是很難證明一個否定的,但據我所知,C++只對邏輯表達式進行短路評估,因此沒有等價的算術表達式。另外,如果算術表達式是以短路方式進行評估的,我可以想象大量的代碼會破壞性很強,所以我認爲不會那樣。
理論上,編譯器可以生成代碼以避免計算表達式,如果它可以表明它沒有副作用。但在實踐中,不可能添加代碼來檢查值是否爲零,因爲它沒有理由認爲它是。
另一方面,邏輯運算(||
和&&
)保證在C++中短路。所以你應該使用它們。
result = 0;
if(switch1) {
result += large_expresion_1();
}
if(switch2)
result += large_expression2();
}
但是,如果你正在優化「大型表達式」一定要檢查是否實際上是更快地計算他們兩個,然後在網點的方式添加。例如像
result = ((-(uint64_t)(switch1)) & large_expression_1) + ((-(uint64_t)(switch2)) & large_expression_2);
這樣bithacks一束這裏記載: https://graphics.stanford.edu/~seander/bithacks.html
基準和分離到,讀取生成的彙編語言找出編譯器實際上做的(或)您。
switch1
可以0
或1
,一樣可以switch2
如果switch1
和switch2
實際上只能有0
或1
值,那麼這將是更好地爲他們是布爾值,而不是整數。
布爾開關,你的說法就變成了:
result = (switch1 ? (large expression 1) : 0)
+ (switch2 ? (large expression 2) : 0)
正是在這種形式下,表現將即使其結果將不被使用計算的情況下。一個簡單而明確的方式,以避免浪費計算是明顯的:
result = 0;
if(switch1) {
result += large expression 1;
}
if(switch2) {
result += large expression 2;
}
你可以通過提取方法,在其中傳遞的開關整理這件事:
result = guardedLargeExpression1(switch1, otherparams1)
+ guardedLargeExpression2(switch2, otherparams2);
... ..用。
int guardedLargeExpression1(bool switch, foo params) {
if(switch) {
return 0;
}
return large expression(...);
}
你也可以做聰明的東西與pointers to functions:
int guardedFunctionCall(bool switch, int *functionptr(foo), foo arg) {
if(switch) {
return 0;
}
return (*functionptr)(arg);
}
...這是接近的那種你會用Java做的事情,當你使用Supplier
懶洋洋地評估代碼。
或者,因爲你在C++不是C,你可以做更多的事情OO和實際使用的Supplier
的C++相當於:What is the C++ equivalent of a java.util.function.Supplier?
如果依賴於精確的條件。 CPU,編譯器,確切的表達式。
如果if
成爲彙編代碼中的條件跳轉,並且條件無法預測,則if
可能會減慢程序速度。
如果條件不能被預測,並且「大表達式」其實很簡單,那麼做「乘法」可能會更快。但是,如果表達式計算速度慢,或者if
可以完美分支預測(或者它不會編譯爲條件跳轉),那麼我認爲if
方式會更快。
總之,你應該嘗試兩種解決方案,並檢查哪個更快。
請提供一個[mcve],並且您可以在godbolt上檢查自己 –
如果您的大型expresssion包含函數調用,其中編譯器無法確定它們沒有副作用,它們將不會被優化。如果任何一個開關在編譯時不是常量0值,也不會對整個表達式進行優化。 –
看起來像過早的優化。首先測量,然後優化。 – Rakete1111