Накладные расходы OpenMP

Я распараллелил свертку изображений и факторизацию lu, используя OpenMP и Intel TBB. Тестирую на 1-8 ядрах. Но когда я пробую это на 1 ядре в OPenMP и TBB, указав один поток, например, с помощью set_num_threads(1) и task_scheduler_init InitTBB(1) соответственно; Производительность TBB показывает небольшое ухудшение по сравнению с последовательным кодом из-за накладных расходов TBB, но, что удивительно, OpenMP не показывает никаких накладных расходов на одном ядре и работает точно так же, как последовательный код (с использованием уровня оптимизации Intel O3). Я использую статическое планирование циклов OpenMP. Это реально или я делаю какую-то ошибку?


person Akhtar Ali    schedule 04.09.2011    source источник
comment
это также происходит, если аргумент от num_threads до set_num_threads(num_threads) известен только во время выполнения, то есть из пользовательского ввода?   -  person Walter    schedule 20.03.2013


Ответы (4)


Среда выполнения OpenMP, вероятно, не создаст никаких потоков, если вы запустите ее только с одним потоком.

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

person cschleiden    schedule 01.10.2011
comment
Директивы параллелизации OpenMP иногда также ускоряют работу последовательного кода, поскольку вы, по сути, предоставляете компилятору больше информации - это интересно. К сожалению, я заметил небольшое снижение производительности, когда использую 1 поток с прагмой openmp, и с тех пор использовал #ifdefs, чтобы предотвратить это, если есть только 1 поток. Наблюдали ли вы это за конкретной комбинацией компилятора/кода? - person Sayan; 19.03.2012
comment
Ого, тоже о таком не слышал. Надо попробовать это. Интересно! - person DirkMausF; 14.06.2012

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

TBB, насколько я понимаю, это просто библиотека. Алгоритм всегда нужно будет дополнить необходимыми частями, чтобы запускать его как параллельно, так и последовательно.

person Flexo    schedule 04.09.2011
comment
То есть вы хотите сказать, что если я установлю один поток в OpenMP, его реализация будет достаточно разумной, чтобы пропустить прагмы OpenMP и запустить его последовательно? - person Akhtar Ali; 05.09.2011
comment
Если вы установите его во время компиляции, что, как я думаю, у вас есть из вашего вопроса, то да, это возможно и вероятно. - person Flexo; 05.09.2011
comment
set_num_threads(1) является частью библиотеки OpenMP, а не директивой компилятора OpenMP, поэтому он не пропускается компилятором. - person DirkMausF; 14.06.2012
comment
@DirkMausF, конечно, но он может быть встроен в заголовочный файл, если реализация решит сделать это таким образом, или даже магией каким-то другим способом. Таким образом, он может быть встроен и оптимизирован, если компилятор сможет доказать, что он не имеет никакого эффекта. Компилятор также может создать два варианта кода, один параллельный, один последовательный в одном и том же выводе, если он хочет, и выбрать один из них во время выполнения с одной (довольно дешевой) ветвью. В OpenMP доступно гораздо больше опций, чем в какой-либо библиотеке, где у вас есть только предварительно скомпилированный код. - person Flexo; 14.06.2012
comment
Почему компилятор должен это делать? Достаточно проверить, настроен ли только один поток, а затем выполнить его без параллелизма... один, если... тогда это не накладные расходы по сравнению с переписыванием всего компилятора... ;) - person DirkMausF; 14.06.2012

OpenMP разветвляет декорированную часть (#pragma omg for/parallel) кода на основной поток (который также будет выполняться без OpenMP) и дополнительные потоки.

Если вы настроите использование только одного потока, то это будет только основной поток, который будет выполняться без директивы OpenMP. Накладных расходов нет, потому что путь выполнения не был разветвлен.

person DirkMausF    schedule 14.06.2012

Суть OpenMP в том, что компилятор делает всю работу за вас, требует минимальной модификации последовательного кода и часто дает хорошие результаты, если задачи, поставленные перед каждым потоком, довольно велики. Я бы посоветовал попробовать протестировать ваш код с помощью Pthread или thread на С++ 11 и посмотреть результаты.

person Anas    schedule 31.01.2015