[英]Performance penalty for large C++ dll's with autogenerated C code
我正在開發一個需要調用一系列優化求解器的軟件。 每個解算器都是一個自動生成的C代碼,有數千行代碼。 我使用了200個這樣的求解器,只是要解決的優化問題的大小不同。
總而言之,這些自動生成的解算器提供了大約180MB的C代碼,我在Visual Studio 2008中使用extern "C"{ /*200 solvers' headers*/ }
語法編譯為C ++。編譯全部這非常慢(使用“最大速度/ O2”優化標志,大約需要8小時)。 出於這個原因,我認為將解算器編譯成單個DLL是個好主意,然后我可以從一個單獨的軟件調用它(這將有一個合理的編譯時間,並允許我抽象出所有這些extern“ C“來自更高級別代碼的東西”。 編譯后的DLL大約是37MB。
問題是當使用DLL執行這些解算器之一時,執行需要大約30ms。 如果我只將那個單個解算器編譯成DLL,並從同一個程序調用它,那么執行速度大約快100倍(<1ms)。 為什么是這樣? 我可以繞過嗎?
DLL如下所示。 每個求解器使用相同的結構(即它們具有相同的成員變量),但它們具有不同的名稱,因此所有類型轉換。
extern "C"{
#include "../Generated/include/optim_001.h"
#include "../Generated/include/optim_002.h"
/*etc.*/
#include "../Generated/include/optim_200.h"
}
namespace InterceptionTrajectorySolver
{
__declspec(dllexport) InterceptionTrajectoryExitFlag SolveIntercept(unsigned numSteps, InputParams params, double* optimSoln, OutputInfo* infoOut)
{
int exitFlag;
switch(numSteps)
{
case 1:
exitFlag = optim_001_solve((optim_001_params*) ¶ms, (optim_001_output*) optimSoln, (optim_001_info*) &infoOut);
break;
case 2:
exitFlag = optim_002_solve((optim_002_params*) ¶ms, (optim_002_output*) optimSoln, (optim_002_info*) &infoOut);
break;
/*
...
etc.
...
*/
case 200:
exitFlag = optim_200_solve((optim_200_params*) ¶ms, (optim_200_output*) optimSoln, (optim_200_info*) &infoOut);
break;
}
return exitFlag;
};
};
我不知道您的代碼是否內聯到示例中的每個案例部分。 如果你的函數是內聯函數,並且你把它全部放在一個函數中,那么它會慢很多,因為代碼是在虛擬內存中布局的,這需要在執行代碼時跳轉到CPU。 如果不是全部內聯,那么這些建議可能會有所幫助。
你的解決方案可能會被...改進
A)1)將項目划分為200個獨立的dll。 然后使用.bat文件或類似文件構建。 2)在每個名為“MyEntryPoint”的dll中創建導出函數,然后使用動態鏈接在需要時加載庫。 這將相當於一個繁忙的音樂程序,加載了很多小的DLL插件。 使用GetProcAddress獲取一個指向EntryPoint的函數指針。
要么...
B)將每個解決方案構建為單獨的.lib文件。 然后,每個解決方案將非常快速地編譯,然后您可以將它們全部鏈接在一起。 構建一個指向所有函數的函數指針數組,並通過查找來調用它。
result = SolveInterceptWhichStep;
將所有libs組合成一個大型lib不應該花費8個小時。 如果花了那么長時間,你就會做一些非常錯誤的事情。
和...
嘗試將代碼放入不同的實際.cpp文件中。 也許特定的編譯器如果它們都在不同的單元等中會做得更好......然后一旦編譯了每個單元,如果你沒有改變任何東西,它將保持編譯。
確保測量並平均多次調用優化器的時間,因為可能是在第一次調用之前設置有很大的開銷。
然后還要檢查200分支條件語句(您的開關)對您的性能做了什么! 嘗試刪除該開關進行測試,只調用測試項目中的一個解算器,但鏈接DLL中的所有解算器。 你還看到性能緩慢嗎?
我假設您生成代碼的原因是為了獲得更好的運行時性能,以及更好的正確性。 我做同樣的事情。
我建議你嘗試這種技術來找出運行時性能問題。
如果您看到100:1的性能差異,這意味着每次中斷它並查看程序的狀態,您有99%的機會看到問題所在。
就構建時間而言,確定模塊化是有意義的。 這些都不會對運行時間產生太大影響,除非它意味着你正在做瘋狂的I / O.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.