Почему мой код работает медленнее с несколькими потоками, чем с одним потоком, когда он компилируется для профилирования (-pg)? - PullRequest
2 голосов
/ 21 мая 2010

Я пишу трассировщик лучей.

Недавно я добавил в программу многопоточность, чтобы использовать дополнительные ядра на моем i5 Quad Core.

При странном повороте событий отладочная версия приложения теперь работает медленнее, но оптимизированная сборка работает быстрее, чем до того, как я добавил многопоточность.

Я передаю флаги "-g -pg" в gcc для отладочной сборки и флаг "-O3" для оптимизированной сборки.

Хост-система: Ubuntu Linux 10.4 AMD64.

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

Есть идеи, почему я вижу это поведение?

Отладочная версия скомпилирована с "-g3 -pg". Оптимизированная версия с "-O3".

Optimized no threading:        0m4.864s
Optimized threading:           0m2.075s

Debug no threading:            0m30.351s
Debug threading:               0m39.860s
Debug threading after "strip": 0m39.767s

Debug no threading (no-pg):    0m10.428s
Debug threading (no-pg):       0m4.045s

Это убеждает меня в том, что «-g3» не виноват в странной дельте производительности, а в том, что это скорее ключ «-pg». Вероятно, опция -pg добавляет какой-то механизм блокировки для измерения производительности потока.

Так как "-pg" не работает на многопоточных приложениях, я просто удалю его.

Ответы [ 4 ]

8 голосов
/ 21 мая 2010

Что вы получаете без флага -pg? Это не отладочные символы (которые не влияют на генерацию кода), это для профилирования (что влияет).

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

2 голосов
/ 21 мая 2010

Достаточно ли кода профиля для вставки вызовов инструментария в функции, способные причинить вам боль?
Если вы сделаете один шаг на уровне ассемблера, вы узнаете довольно быстро.

2 голосов
/ 21 мая 2010

Вы говорите о двух разных вещах здесь. Отладка символов и оптимизация компилятора. Если вы используете самые строгие настройки оптимизации, которые может предложить компилятор, вы делаете это из-за потери символов, которые полезны при отладке.

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

Символы отладки не являются «накладными», если не считать того факта, что они занимают больше места на диске. Код, скомпилированный с максимальной оптимизацией (-O3), не должен добавлять символы отладки. Это флаг, который вы устанавливаете, когда вам не нужны эти символы.

Если вам нужны отладочные символы, вы получаете их за счет потери оптимизации компилятора. Однако, опять же, это не «накладные расходы», это просто отсутствие оптимизации компилятора.

0 голосов
/ 06 февраля 2018

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

Мой пример: запуск теста LULESH CORAL на 2NUMA узлах песчаный мост INTEL (8 ядер + 8 ядер) с размером -s 50и 20 итераций -i, скомпилировать с gcc 6.3.0, -O3, у меня есть:

с 1 запущенным потоком: ~ 3,7 без -pg и ~ 3,8 с этим, но согласно анализу gprof код работал только для 3,5.

с 16 работающими потоками: ~ 0,6 без -pg и ~ 0,8 с ним, но согласно анализу gprof код работал для ~ 4,5 ...

Время в полужирном было измерено gettimeofday, внепараллельная область (начало и конец основной функции).

Поэтому, возможно, если бы вы измерили время вашего приложения таким же образом, вы бы увидели одно и то же speeduo с и без -pg.Это просто мера gprof, которая ошибочна параллельно.В LULESH openmp версия в любом случае.

...