Понимание отчета VTune

это продолжение существующего потока (http://stackoverflow.com/questions/12724887/caching-in-a-high-performance-financial-application) - я обнаружил, что это не кеш, который мешает моему приложению. Короче говоря, у меня есть приложение, которое тратит 70 процентов времени выполнения на одну функцию (15 секунд из 22). Следовательно, я хотел бы максимально сократить время выполнения этой функции, поскольку предполагаемое использование функции предназначено для НАМНОГО больших данных (т.е. 22 секунды не являются запланированным временем выполнения :)

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

Взглянув на инкриминированную функцию AssessmentExits(), я озадачен следующими вещами:

1/ функция тратит 2,2 с на вызов встроенной функции, которая возвращает 1 независимо от параметров (строка 425, this->contractManager->contractCount()). Примечание: версия, в которой функция возвращает 1 независимо от параметров, является одним из возможных случаев, поэтому я не могу поставить "contractCount=1" и оставить так. Может ли перенаправление с указателя виртуальной таблицы съесть эти 2,2 секунды (contractCount() — виртуальный метод)?

2/ функция тратит 3,3 с на min(uint1, uint2) (строка 432), несмотря на то, что я использую версию wmin, которая должна быть максимально дружественной к процессору.

3/ функция тратит 1,6 с на строку 512, что является очень тривиальной операцией, а вызываемая функция не является виртуальной.

Итак, вопросы: почему эти три строчки кода занимают так много времени? Что я упускаю из виду? И как я могу оптимизировать свой код, чтобы он работал быстрее? Должен ли я заменить wmin() версией min SSE, применяемой ко всем массивам?

Любой вклад очень ценится. Даниэль

EDIT: Взглянув на сборку, я обнаружил, что в случае 1/ действительно именно vfptr делает код "медленным". Я заменил вызов виртуальной функции на fastdelegate Дона Клагстона, но никаких изменений в производительности не произошло (я понятия не имею, почему). Благодаря комментарию Найтингейла вложения теперь должны содержать все необходимые файлы. Однако двоичный файл не может быть успешно запущен, так как он подключается к общей памяти, где находятся сотни МБ данных.

Итак, я прикрепляю весь проект вместе с результатами VTune здесь и здесь


person Daniel Bencik    schedule 10.10.2012    source источник


Ответы (1)


Даниэль,

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

Я также попытался пересобрать ваши исходники, но не удалось найти ряд заголовочных файлов:

  • Некоторые заголовки Qt (у меня не установлен Qt, и я не эксперт в этом)
  • Файл параметраHolder.h
  • файл externFloatConsts.h

Итак, чтобы помочь, было бы хорошо иметь эти файлы или двоичный файл, который использовался для сбора данных.

person Alexey Alexandrov    schedule 13.10.2012
comment
Здравствуй, Соловей! Большое спасибо! Я обновил исходные ссылки. Теперь есть весь проект (без файла sdf, который большой), а также вся коллекция библиотек, которые использует проект. - person Daniel Bencik; 13.10.2012
comment
Бинарники уже есть, спасибо. Но когда я пытаюсь указать VTune, чтобы использовать их, он говорит, что несоответствие контрольной суммы. Это означает, что вы, вероятно, перекомпилировали двоичный файл ПОСЛЕ того, как собрали данные. Но чтобы увидеть сборку, мне нужен именно тот бинарник, который использовался для сбора данных. (Я попытался указать инструмент как для выпуска, так и для отладки исполняемого файла, хотя профилирование с помощью исполняемого файла отладки обычно является плохой идеей, поэтому я предполагаю, что вы использовали выпуск). - person Alexey Alexandrov; 14.10.2012
comment
Кроме того, правильно ли я понимаю, что файл *.sdf является входным файлом для теста, и поэтому я все равно не смогу запустить его самостоятельно? Если да, то исполняемый файл, соответствующий собранному вами результату, необходим. - person Alexey Alexandrov; 14.10.2012
comment
Привет Соловей, спасибо за твои усилия. Это очень странно, к сожалению :( Я скачал весь rar-файл с rapidshare, поместил его в отдельный раздел и открыл проект VS. Оттуда я открыл отчет VTune, и все было в порядке, я смог просмотреть сборку без проблемы.Файл *.sdf - это файл, сгенерированный VS для более быстрого поиска функций во время программирования.Если я удалю его и открою проект заново, он будет создан заново.Поэтому я хотел бы спросить вас, открывали ли вы отчет VTune так, как я сделал?Большое спасибо!! - person Daniel Bencik; 14.10.2012
comment
Я смог наконец-то посмотреть на результат - но мне пришлось заново дорабатывать результаты VTune в предположении, что модуль действительно тот же самый. По какой-то причине контрольная сумма все еще не совпадала для меня, пока я не сделал это. При этом всегда существует риск получения непоследовательных двоичных данных по сравнению с данными о производительности, но проверка работоспособности, похоже, показывает, что все в порядке. - person Alexey Alexandrov; 14.10.2012
comment
Что касается самого спектакля. Я посмотрел на хотспоты и ничего особенно плохого там не вижу. Я вижу, что функция AssessmentExists удаляет около 19,5 байт инструкций на один поток (кажется, что в результате доступа к памяти три потока, но я считаю, что это всего лишь три отдельных запуска VTune, а не отдельные потоки внутри приложения). Он удаляет эти 19,5 миллиардов инструкций за 16,5 миллиардов тактовых импульсов, что означает, что CPI составляет около 0,85. Это далеко не идеальное значение 0,25, но тоже не так уж плохо. Поэтому я бы рассмотрел другой алгоритм или добавление потоков. - person Alexey Alexandrov; 14.10.2012
comment
Спасибо за усилия! Мне удалось получить ускорение второй по эффективности функции ( uiTickCount() ) более чем в 10 раз с помощью SSE, поэтому я рассчитываю на снижение времени выполнения на 4,5 секунды. Что касается отчета об эффективности, не могли бы вы как-то объяснить мне, почему CPI не равен 0,25? Я имею в виду... означает ли это, что мой код большую часть времени ожидает чего-то (данных?) или чего-то еще? Как многопоточность поможет снизить CPI? Большое спасибо! - person Daniel Bencik; 14.10.2012
comment
Чтобы достичь CPI 0,25, вам нужно, чтобы ЦП удалял 4 инструкции каждый цикл. Есть несколько причин, по которым это может быть трудно получить. Во-первых, некоторые инструкции выполняются более чем за 1 цикл из-за того, как они реализованы в HW. Например, умножения и деления выполняются довольно медленно (особенно деления, всегда старайтесь вычислить обратное значение один раз, а затем умножьте, если сможете). Во-вторых, могут существовать зависимости данных от загрузки памяти, так что если загрузка не выполняется, последующие инструкции должны ждать. В-третьих, даже если есть независимые инструкции для выполнения, они могут... - person Alexey Alexandrov; 16.10.2012
comment
... им все еще может не хватать ресурсов для выполнения. Например, у вас может быть несколько делений подряд, которые не имеют взаимозависимостей и теоретически могут выполняться параллельно в неупорядоченном процессорном движке. Но поскольку в ALU обычно не так много блоков деления, вы не получите такого большого параллелизма. Короче говоря, для циклов вам нужно внимательно следить за критическим путем зависимости данных и следить за тем, чтобы на нем не было инструкций с длительной задержкой (включая промахи кеша). Надеюсь, это поможет. Задача непростая. SSE — хороший способ привести вещи в порядок — каламбур. - person Alexey Alexandrov; 16.10.2012
comment
Я понимаю. Спасибо за разъяснение. SSE создает беспорядок - мне действительно нужно было сделать одну вещь быстрее, и я тщательно протестировал новый код SSE - он просто дает те же результаты, что и старый (проверенный) код. Вы думаете, что мне нужно быть осторожным даже больше, чем просто тестировать код SSE в сравнении со старым кодом? Еще раз спасибо за ваше терпение! - person Daniel Bencik; 16.10.2012
comment
Обычные угловые случаи с SSE: 1) количество элементов, не кратное ширине вектора; 2) выравнивание данных. Для покрытия первого убедитесь, что вы тестируете свой код с данными, которые не являются просто степенью двойки, но некоторыми другими значениями, такими как простое число или что-то в этом роде. Для выравнивания данных - это сложнее. Просто обычно требуется дополнительное тестирование и тестирование в режиме выпуска с оптимизацией, где упаковка обычно более плотная. - person Alexey Alexandrov; 17.10.2012