Ответ 1
Я пробовал как прокси-сервер выборки в Visual Studio 2017 Professional, а также VTune 2018. Я попытался включить /Zo, но это похоже, не влияет.
Я нашел следующий ресурс, который, по-видимому, указывает, что только Visual Studio Ultimate или Premium поддерживают встроенную информацию о кадре - это все еще верно для Visual Studio 2017?
К счастью, у меня уже есть три разных версии VS. Я могу рассказать вам больше информации о поддержке функции информации о встроенных функциях, как описано в статье, на которую вы ссылались:
- VS Community 2013 Update 5 не поддерживает показ встроенных функций, даже когда я указываю /d 2Zi+. Похоже, что он поддерживается только в VS 2013 Premium или Ultimate.
- VS Community 2015 Update 3 поддерживает показ встроенных функций (функция, обсуждаемая в статье). По умолчанию указывается /Zi. /Zo активируется неявно с /Zi, поэтому вам не нужно явно указывать его. Поэтому вам не нужны VS 2015 Premium или Ultimate.
- VS Community 2017 с последним обновлением не поддерживает показ встроенных функций независимо от /Zi и/Zo. Кажется, что он поддерживается только в VS 2017 Professional и/или Enterprise.
В блоге VС++ не сообщается о каких-либо улучшениях в профилировщике выборки VS 2017, поэтому я не думаю, что это лучше по сравнению с профилировщиком VS Community 2015.
Обратите внимание, что разные версии компилятора могут принимать различные решения по оптимизации. Например, я заметил, что VS 2013 и 2015 не поддерживают функцию burn
.
Используя VS Community 2015 Update 3, я получаю профилирующие результаты, очень похожие на то, что показано в третьем рисунке, и тот же код выделены.
Теперь я расскажу, как эта дополнительная информация может быть полезна при интерпретации результатов профилирования, как вы можете получить это вручную с еще большим усилием и как интерпретировать результаты, несмотря на встроенные функции.
Как я могу осмыслить данные профилирования С++ в Windows, когда много код встраивается компилятором?
Профилировщик VS будет относить затраты только к функциям, которые не были включены. Для функций, которые были встроены, затраты будут добавлены и включены в некоторую функцию вызывающего абонента, которая не была включена (в этом случае функция burn
).
Сложив оценочное время выполнения не-inline-вызванных функций из burn
(как показано на рисунке), получаем 31.3 + 22.7 + 4.7 + 1.1 = 59.8%. Кроме того, расчетное время выполнения Function Body
, как показано на рисунке, составляет 40,2%. Обратите внимание, что 59,8% + 40,2% = 100% времени, проведенного в burn
, как и должно быть. Другими словами, 40,2% времени, проведенного в burn
, было потрачено в теле функции и на любые функции, которые были в ней встроены.
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;
Учитывая все это, единственная потенциальная возможность оптимизации, которую я вижу здесь, состоит в том, чтобы memoize результаты log2
.
Профилировщик выборки VTune, безусловно, более мощный, чем профилировщик выборки VS. В частности, атрибуты VTune зависят от отдельных строк исходного кода или инструкций по сборке. Однако эта атрибуция очень аппроксимируется и часто бессмысленна. Поэтому я был бы очень осторожен при интерпретации результатов, визуализированных таким образом. Я не уверен, поддерживает ли VTune "Улучшить оптимизированную отладочную информацию" или в какой степени он поддерживает расходы на привязку к встроенным функциям. Лучшее место, чтобы задать эти вопросы, - это форум сообщества Intel VTune Amplifier.