2016-07-29 2 views
0

Я использую Visual Studio для профилирования моего многопоточного приложения на C++. Из того, что я прочитал о методе Sampling, я понимаю, что он смотрит на процессор через определенные интервалы, чтобы увидеть, какая функция выполняется.Профилирование многопоточного кода, как работает выборка

Мне любопытно, как он обрабатывает многопоточный код. Вполне возможно, что две или более функции могут выполняться одновременно на разных потоках на разных ядрах. В этом случае используется ли счетчик выборки для обеих этих функций? Я считаю, что это то, что на самом деле происходит.

Это фактически затрудняет получение информации из отчета о профилировании. Функция, которая имеет наибольшее количество собранных образцов, если они выполняются в рабочем потоке, может выполняться на другом ядре (чем основной поток) и вообще не может влиять на производительность приложения. Но если он отключает основной поток для выполнения своей работы, то он должен иметь заметное влияние на производительность.

Есть ли лучший способ профилировать многопоточный код?

+1

Да. Если потоки не влияют на производительность вашего приложения, вы делаете это неправильно, и вам, конечно, лучше не использовать их вообще. Модулирование необходимости асинхронности для предотвращения зависания пользовательского интерфейса, но это не параллелизм. Выяснение, почему многопоточные программы всасывают грязь, требуется другой тип инструмента, [анализатор параллелизма] (https://msdn.microsoft.com/en-us/library/dd537632.aspx?f=255&MSPPError=-2147217396) , –

ответ

1

При выполнении функции выборки профилировщики, как правило, примерят каждую программную нить отдельно. Таким образом, если у вас есть три потока, выполнение функций foo(), bar() и baz() с интенсивным использованием процессора соответственно, а частота дискретизации 100 Гц, а продолжительность сеанса профилирования - 1 с, вы получите 100 выборок в каждом функций.

Приятный профилировщик также, как правило, даст вам возможность фильтровать данные по данному потоку, чтобы вы могли видеть, какие горячие точки присутствуют в изолированном потоке. Например, то, что происходит в основном потоке, может иметь большое значение, если основной поток - это то, где выполняется визуализация пользовательского интерфейса с используемой структурой.

Выяснение того, как вычисления, выполненные в фоновом режиме, влияют на отзывчивость приложения, является широкой темой отдельно и часто зависит от приложения. Некоторые образцы:

  • Ищите, где основной поток блокируется. Это может блокировать ожидание результата фонового вычисления.
  • Ищите, есть ли в главном потоке какие-либо точки, где ему нужно было что-то пропустить, потому что у него не было доступных данных. Это особенно характерно для обработки пользовательского интерфейса/рендеринга - если данные не готовы к тому времени, когда кадр должен быть визуализирован, код не имеет ничего лучшего, как пропускание рендеринга кадра, вызывающего видимость пользователя в пользовательском интерфейсе.

Надеюсь, это поможет.

0

Есть ли лучший способ профилировать многопоточный код?

Я всегда должны спросить, потому что это не то же самое:
Вы ищете 1) то, что нашли время на стене часы, и которые могут быть исправлены, чтобы ускорить применение, или 2) измерения различных типов, таких как подсчет вызовов функций, время автономной работы процессора, время включения процессора, горячий путь и т. д.?

Предполагая, что ответ равен 1, метод, которым многие люди и я пользуюсь, - это просто pause the application, если необходимо, в среде Visual Studio IDE. Когда вы это делаете, он приостанавливает все потоки. Вы можете отображать стек вызовов для каждого потока. Это показывает вам, чего он ждет и почему. Один или несколько потоков будут на какой-то части пауз находиться в процессе либо какого-либо вычисления, либо какого-либо ожидания системы или ввода-вывода, которые вы можете сочтет недопустимыми.

Вы могли бы назвать его «профайлер бедного человека» а, , но вот как это выходит за рамки выхода профилировщика:

  • Вам не придется заботиться, если проблема заключается в вычислении или I/O, или угадать, что это такое, и выбирать различные методы профилирования. В любом случае, вы это видите.

  • Если вы хотите знать общую долю времени, затрачиваемую на функцию/метод, грубо говоря, это доля выборок, где функция находится в стеке. То же самое касается любой строки кода. Если вы хотите узнать эксклюзивную (самостоятельную) фракцию, то функция или строка кода находятся на конце .

  • Если вы хотите знать, какая часть времени тратится с функцией Вызывающая функция B, то доля проб, где А вызывает B. Если вы заинтересованы в вызывающем В через посредника, вы также можете увидеть это (о котором не может рассказать ни один график вызовов).

  • Предположим, что стек имеет глубину 30 уровней, оканчиваясь на некоторые операции ввода-вывода, и вы хотите знать, какая часть вашего кода вызывает это, просто сканируйте стек, просматривая каждую строку кода до тех пор, пока ты нашел это. Обратите внимание, что это, вероятно, не «горячий путь», потому что может быть несколько способов получить код проблемы.

  • Когда вы это сделаете, вы можете не только увидеть ответственную строку (строки) кода, вы можете проверить значения соответствующих переменных данных. Профилировщики не могут вам это показать; вы должны угадать.

  • Это не пугает ваше время, сообщая вам, что много вещей не проблемы, потому что они принимают небольшие проценты. (Иногда люди думают, что они ищут только мелкие вещи, например, 5% или менее, делая розовые предположения, что нет ничего большего. Профилировщик может привести к тому, чтобы сделать это предположение, потому что с ним вы не можете см. ничего большего .)

  • Это позволяет вам сконцентрироваться на коде, который вы можете что-то сделать, ваш код, в отличие от системного кода.

  • Вам не нужно искать сроки, чтобы найти интервал интереса. Вы останавливаете его, когда он заставляет вас ждать; его трудно приостановить в любое другое время. Итак, это скажет вам, почему это заставляет вас ждать.