OpenMP num_threads (1) выполняется быстрее, чем OpenMP
Я запускаю свой код в самых разных обстоятельствах, что привело к тому, что я считаю странным поведением. Мое тестирование было на двухъядерном процессоре Intel xeon с HT.
Нет инструкции OpenMP '#pragma', общая продолжительность выполнения = 507 секунд
С оператором OpenMP '#pragma', определяющим 1 ядро, общая продолжительность выполнения = 117 секунд
С оператором OpenMP '#pragma', определяющим 2 ядра, общая продолжительность выполнения = 150 секунд
С оператором OpenMP '#pragma', определяющим 3 ядра, общая продолжительность выполнения = 157 секунд
С оператором OpenMP '#pragma', определяющим 4 ядра, общая продолжительность выполнения = 144 секунды
Я думаю, что я не могу понять, почему комментирование моей строки openmp заставляет программу замедлять так много между 1 потоком без openmp и 1 нить WITH openmp.
Все, что я изменяю, находится между:
//#pragma omp parallel for shared(segs) private(i, j, p_hough) num_threads(1) schedule(guided)
and...
#pragma omp parallel for shared(segs) private(i, j, p_hough) num_threads(1,2,3,4) schedule(guided)
В любом случае, если кто-нибудь знает, почему это может происходить, сообщите мне!
Спасибо за любую помощь,
Бретт
EDIT: я рассмотрю некоторые комментарии здесь.
Я использую num_threads (1), num_threads (2) и т.д.
С дальнейшим исследованием выясняется, что мои результаты непоследовательны в зависимости от того, включена ли в код строка "расписание (руководство)".
-Когда я использую график (ориентированный), я генерирую самое быстрое решение, независимо от количества потоков.
-Когда я использую планировщик по умолчанию, мои результаты значительно медленнее и разные значения
-При улучшении графика (ориентированного) не достигается увеличение потоков
- Без графика (с учетом) я получаю улучшение с добавлением потоков
Я думаю, что не нашел достаточно подробного описания того, что для меня делает график (ориентированный), я понимаю, что он пытается разбить цикл так, чтобы сначала выполнялись самые длительные итерации, которые должны иметь эффект наименьшего количества времени, в течение которого один поток ожидает, что остальные завершат свои итерации.
Похоже, что для моего цикла итерации ~ 900, когда я использую расписание (управляемый), я обрабатываю только 200 итераций, где, как и без графика (с инструкцией), я обрабатываю все 900 итераций. Любые мысли?
Ответы
Ответ 1
OpenMP имеет значительные накладные расходы на синхронизацию. Я обнаружил, что, если у вас нет действительно большого цикла, который выполняет большую работу и не имеет синхронизации внутри цикла, тогда обычно не стоит использовать OpenMP.
Я думаю, что когда вы устанавливаете количество потоков в один (1), OpenMP просто выполняет вызов процедуры для процедуры OpenMP, реализуя цикл, поэтому накладные расходы минимальны, а производительность по существу идентична случаю без OpenMP,
В противном случае я думаю, что OpenMP устанавливает некоторые семафоры, а ожидания "рабочих" потоков пробуждаются, синхронизируют их доступ к структурам данных, сообщая им, какие параметры цикла устанавливаются, а затем вызывают процедуру, которая выполняет эту работу, и когда они завершают кусок работы, они снова сигнализируют мастер-поток. Эта синхронизация должна выполняться для каждого фрагмента работы, выполняемого потоком, а затраты на синхронизацию нетривиальны.
Использование опции планирования STATIC может помочь снизить накладные расходы на планирование/синхронизацию, особенно если число итераций цикла велико относительно количества ядер.