[英]Profiling inlined C++ functions with Visual Studio Compiler
當大量代碼被編譯器內聯時,我怎樣才能理解Windows上的C ++分析數據? 即我當然想要測量實際運行的代碼,因此根據定義,我將測量代碼的優化構建。 但似乎我嘗試實際設法解決內聯函數的工具都沒有。
我已經嘗試過Visual Studio 2017 Professional和VTune 2018中的采樣分析器。我嘗試啟用/Zo
,但它似乎沒有任何影響。
我發現以下資源似乎表明只有Visual Studio Ultimate或Premium支持內聯框架信息 - 這仍然適用於Visual Studio 2017嗎? https://social.msdn.microsoft.com/Forums/en-US/9df15363-5aae-4f0b-a5ad-dd9939917d4c/which-functions-arent-pgo-optimized-using-profile-data?forum=vsdebug
這是一個示例代碼:
#include <cmath>
#include <random>
#include <iostream>
inline double burn()
{
std::uniform_real_distribution<double> uniform(-1E5, 1E5);
std::default_random_engine engine;
double s = 0;
for (int i = 0; i < 100000000; ++i) {
s += uniform(engine);
}
return s;
}
int main()
{
std::cout << "random sum: " << burn() << '\n';
return 0;
}
在發布模式下使用Visual Studio編譯它。 或者在命令行上,嘗試cl /O2 /Zi /Zo /EHsc main.cpp
。 然后嘗試使用Visual Studio中的CPU Sampling Profiler對其進行配置。 你最多會看到這樣的事情:
VTune 2018在Windows上看起來很相似。 在Linux上,perf和VTune顯示來自內聯函數的幀沒有問題...這個功能,在我看來對C ++工具至關重要,真的不是非Premium / Ultimate Visual Studio工具鏈的一部分嗎? Windows上的人們如何處理這個問題? 那么/Zo
什么意義呢?
編輯:我只是嘗試用clang編譯上面的最小例子,它產生不同的,但仍然不滿意的結果? 我編譯了clang 6.0.0(trunk),從LLVM rev 318844和clang rev 318874構建。然后我用clang++ -std=c++17 -O2 -g main.cpp -o main.exe
編譯我的代碼並運行結果再次使用Visual Studio中的Sampling Profiler執行,結果是:
所以現在我看到了burn
功能,但丟失了源文件信息。 此外, uniform_real_distribution
仍然沒有在任何地方顯示。
編輯2:正如意見建議,我現在也嘗試了clang-cl
用的相同的參數cl
之上,即: clang-cl.exe /O2 /Zi /Zo /EHsc main.cpp
。 這產生與clang.exe
相同的結果,但我們也得到了一些有效的源映射:
編輯3:我原本以為clang會神奇地解決這個問題。 遺憾的是,它沒有。 大多數內聯框架仍然缺失:(
編輯4: VTune中不支持內聯框架,用於使用MSVC / PDB版本構建的應用程序: https : //software.intel.com/en-us/forums/intel-vtune-amplifier-xe/topic/749363
我已經嘗試過Visual Studio 2017 Professional和VTune 2018中的采樣分析器。我嘗試啟用/ Zo,但它似乎沒有任何影響。
我發現以下資源似乎表明只有Visual Studio Ultimate或Premium支持內聯框架信息 - 這仍然適用於Visual Studio 2017嗎?
幸運的是,我已經安裝了三個不同版本的VS. 我可以告訴您有關內聯函數信息功能支持的更多信息,如您引用的文章中所述:
VC ++博客上沒有關於VS 2017采樣分析器的任何改進的公告,所以我認為與VS Community 2015的分析器相比沒有任何改進。
請注意,編譯器的不同版本可能會做出不同的優化決策。 例如,我觀察到VS 2013和2015沒有內聯burn
功能。
通過使用VS Community 2015 Update 3,我得到的分析結果與第三張圖片中顯示的結果非常相似,並突出顯示相同的代碼。
現在,我將討論在解釋分析結果時這些附加信息如何有用,如何通過更多工作手動獲得這些信息,以及如何在內聯函數的情況下解釋結果。
當大量代碼被編譯器內聯時,我怎樣才能理解Windows上的C ++分析數據?
VS剖析器僅將成本歸因於未內聯的函數。 對於內聯函數,成本將被累加並包含在一些未內聯的調用函數中(在本例中為burn
函數)。
通過將來自burn
的非內聯調用函數的估計執行時間相加(如圖所示),得到31.3 + 22.7 + 4.7 + 1.1 = 59.8%。 此外,如圖所示, Function Body
的估計執行時間為40.2%。 請注意,59.8%+ 40.2%= 100%的burn
時間,應該是這樣。 換句話說,在burn
中花費的時間的40.2%花費在函數的主體中以及在其中內嵌的任何函數中。
40.2%是很多。 下一個合乎邏輯的問題是,哪些函數在burn
被內聯? 通過使用我之前討論過的功能(可在VS Community 2015中獲得),我可以確定在burn
中內聯了以下功能:
std::mersenne_twister_engine<unsigned int,32,624,397,31,2567483615,11,4294967295,7,2636928640,15,4022730752,18,1812433253>::{ctor};
std::mersenne_twister<unsigned int,32,624,397,31,2567483615,11,7,2636928640,15,4022730752,18>::{ctor};
std::mersenne_twister<unsigned int,32,624,397,31,2567483615,11,7,2636928640,15,4022730752,18>::seed;
std::uniform_real<double>::operator();
std::uniform_real<double>::_Eval;
std::generate_canonical;
如果沒有該功能,則必須手動反匯編發出的可執行二進制文件(使用VS調試器或使用dumpbin )並找到所有x86 call
指令。 通過將其與源代碼中調用的函數進行比較,您可以確定內聯哪些函數。
此時,VS采樣分析器的功能(包括VS 2017)將結束。 但這確實不是一個重要的限制。 通常,由於編譯器對每個函數的大小施加了硬上限,因此在同一函數中沒有很多函數被內聯。 因此,通常可以手動檢查每個內聯函數的源代碼和/或匯編代碼,並查看該代碼是否會顯着影響執行時間。 我做到了這一點,很可能是burn
體(不包括內聯函數)和這兩個內聯函數主要負責40.2%。
std::mersenne_twister<unsigned int,32,624,397,31,2567483615,11,7,2636928640,15,4022730752,18>::seed;
std::uniform_real<double>::_Eval;
綜合考慮所有這些因素,我在這里看到的唯一潛在優化機會就是記住log2
的結果。
VTune采樣分析器肯定比VS采樣分析器更強大。 特別是,VTune將成本歸因於各個源代碼行或匯編指令。 但是,這種歸因非常接近並且通常是荒謬的。 所以在解釋以這種方式可視化的結果時我會非常小心。 我不確定VTune是否支持增強優化調試信息,或者它支持在何種程度上支持內聯函數的成本。 提出這些問題的最佳地點是英特爾VTune Amplifier社區論壇 。
我不確定我是否理解你問題中描述的問題。 在您的網站上,我會嘗試使用/ Ob0 Visual C ++編譯器選項。 它必須禁用內聯擴展。
/ Ob編譯器選項控制函數的內聯擴展。 它必須跟隨數字0,1或2。
0禁用內聯擴展。 默認情況下,編譯器會根據所有函數自行決定擴展,通常稱為自動內聯。
1僅允許擴展標記為inline,__ inline或__forceinline的函數,或者擴展為類聲明中定義的C ++成員函數。
2默認值。 允許擴展標記為內聯,__ inline或__forceinline的函數,以及編譯器選擇的任何其他函數。
當使用/ O1 , / O2 (最小化尺寸,最大化速度)或/ Ox (啟用最高速度優化)時, / Ob2有效。
此選項要求您使用/ O1 , / O2 , / Ox或/ Og啟用優化。
在Visual Studio開發環境中設置此編譯器選項
- 打開項目的“屬性頁”對話框。 有關詳細信息,請參閱使用項目屬性。
- 展開“配置屬性”,“C / C ++”,然后選擇“優化”。
- 修改內聯函數擴展屬性。
有關更多信息,請閱讀文章/ Ob(內聯函數擴展)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.