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 может помочь снизить накладные расходы на планирование/синхронизацию, особенно если число итераций цикла велико относительно количества ядер.