Lambda 優化和內聯函數:編譯器的優勢
Nicolai Josuttis 的聲明(與普通函數相比,lambda 表現出卓越的編譯器優化)引起了許多人的興趣開發人員。透過調查這項說法,我們試圖揭示這種優化優勢背後的根本原因。
函數物件和內聯
作為函數物件的Lambda 擁有一個關鍵優勢:將它們傳遞給函數模板會觸發專門為該lambda 定制的函數的實例化。這允許編譯器毫不費力地內聯 lambda 調用。
相反,函數在傳遞給函數範本時使用函數指標。傳統上,編譯器在透過函數指標內聯呼叫時遇到挑戰。只有當封閉函數本身內聯時,內聯最佳化才是可行的。
模板實例化:探索差異
為了說明這種差異,請考慮映射函數模板:
templatevoid map(Iter begin, Iter end, F f) { for (; begin != end; begin) *begin = f(*begin); }
使用 lambda 呼叫它:
int a[] = { 1, 2, 3, 4 }; map(begin(a), end(a), [](int n) { return n * 2; });
導致自訂實例化:
template void map(int* begin, int* end, _some_lambda_type f) { for (; begin != end; begin) *begin = f.operator()(*begin); }
編譯器辨識 _some_lambda_type::operator() 函式並且可以直接內聯呼叫它。每個不同的 lambda 類型都會提示映射的新實例化,從而保證特定於 lambda 的最佳化。
相反,使用函數指標呼叫映射會產生以下實例化:
template void map(int* begin, int* end, int (*f)(int)) { for (; begin != end; begin) *begin = f(*begin); }
這裡,函數指標 f 指向每個映射呼叫的不同位址,從而禁止內聯最佳化。必須內聯對 map 的調用,編譯器才能將 f 解析為特定函數。
因此,lambda 作為函數物件的獨特性及其促進模板實例化的能力使編譯器具有比傳統函數呼叫更強的最佳化能力通過指標。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3