OpenMP: как убедиться, что каждый поток работает как минимум 1 итерацию в динамическом планировании

Я использую динамическое планирование для итерации цикла. Но когда работ в каждой итерации слишком мало, некоторые потоки не работают или когда потоков огромное количество. Например. Есть 100 итераций и 90 потоков, я хочу, чтобы каждый поток делал хотя бы одну итерацию, а остальные 10 итераций можно было распределить между потоками, которые выполнили свою работу. Как я могу это сделать?


person nanda    schedule 29.02.2020    source источник


Ответы (1)


Вы не можете заставить среду выполнения OpenMP сделать это. Однако вы можете дать подсказки среде выполнения OpenMP, чтобы она, скорее всего, сделала это, когда (она решила, что) это возможно за счет более высоких накладных расходов. На подходе указать степень детализации динамически запланированного цикла. Вот пример:

#pragma omp parallel for schedule(dynamic,1)
for(int i=0 ; i<100 ; ++i)
    compute(i);

С таким кодом среда выполнения может равномерно распределять работу между потоками (используя планировщик разделения работы) или позволять потокам забирать работу главного потока, управляющего параллельными вычислениями (используя планировщик кражи работы). Во втором подходе, несмотря на то, что степень детализации составляет 1 итерацию цикла, некоторые потоки могут забирать больше работы, чем им на самом деле нужно (например, для общего повышения производительности). Если итерации цикла достаточно быстрые, работа, вероятно, не будет сбалансирована между потоками.

Создание 90 потоков является дорогостоящим, и отправка работы в 90 потоков также далеко не бесплатна, поскольку она в основном ограничена относительно высокой задержкой атомарных операций, их продаваемостью, а также задержкой пробуждения потоков. Более того, хотя такая операция кажется синхронной с точки зрения пользователя, на практике это не так (особенно при 90 потоках и многосокетных архитектурах на основе NUMA). В результате некоторые потоки могут закончить вычисление одной итерации цикла, в то время как другие могут не знать о параллельных вычислениях или даже еще не созданы. Затраты на информирование потоков о предстоящих вычислениях обычно растут по мере увеличения числа используемых потоков. В некоторых случаях эти накладные расходы могут быть выше, чем фактические вычисления, и использование меньшего количества потоков может оказаться более эффективным.

Разработчикам среды выполнения OpenMP иногда следует балансировать работу с меньшими затратами на связь. Таким образом, эти решения могут плохо работать в вашем случае, но могут улучшить продажи других приложений. Это особенно верно для планировщика кражи работы (например, среды выполнения Clang/ICC OpenMP). Обратите внимание, что улучшение масштабируемости сред выполнения OpenMP является постоянной областью исследований.

Я советую вам попробовать несколько сред выполнения OpenMP (включая исследовательские, которые могут или не могут быть полезны для использования в производственном коде). Вы также можете поиграть с переменной OMP_WAIT_POLICY, чтобы уменьшить нагрузку на пробуждение. потоки. Вы также можете попробовать использовать задачи OpenMP, чтобы заставить среду выполнения не объединять итерации. Я также советую вам профилировать свой код, чтобы увидеть, что происходит, и найти потенциальные программные/аппаратные узкие места.

Обновлять

Если вы используете больше потоков OpenMP, чем аппаратных потоков на вашем компьютере, процессор не может выполнять их одновременно (он может выполнять только один поток OpenMP для каждого аппаратного потока). Следовательно, операционные системы на вашем компьютере планируют потоки OpenMP на аппаратных потоках так, чтобы с точки зрения пользователя они выполнялись одновременно. Однако они выполняются не одновременно, а чередуются в течение очень небольшого промежутка времени (например, 100 мс).

Например, если у вас есть процессор с 8 аппаратными потоками и вы используете 8 потоков OpenMP, вы можете грубо предположить, что они будут работать одновременно. Но если вы используете 16 потоков OpenMP, ваша операционная система может запланировать их следующим образом:

  • первые 8 потоков выполняются по 100 мс;
  • последние 8 потоков выполняются по 100 мс;
  • первые 8 потоков выполняются повторно по 100 мс;
  • последние 8 потоков выполняются повторно в течение 100 мс;
  • и т.п.

Если ваши вычисления длятся менее 100 мс, динамические/управляемые планировщики OpenMP переместят работу 8 последних потоков в 8 первых потоков, чтобы общее время выполнения было быстрее. Следовательно, 8 первых потоков могут выполнять всю работу, а 8 последних потоков не будут иметь ничего, что нужно было бы выполнить. Это является причиной дисбаланса работы между потоками.

Таким образом, если вы хотите измерить производительность программы OpenMP, вы НЕ должны использовать больше потоков OpenMP, чем аппаратных потоков (если только вы точно не знаете, что делаете, и полностью не осознаете такие эффекты).

person Jérôme Richard    schedule 29.02.2020
comment
Я использую первый подход, и он не работает должным образом. Некоторые темы не работают. Я проверяю, какой из них делает, и результат меня смутил. Например. поток 1,2,5,10,88 работает только. Если в результате потоки 1,2,3,4,5 работают только из 90 потоков, я могу предположить, что работа выполнена до создания всех потоков. И это правда, что большее количество потоков не означает более быстрое время выполнения. Я хочу сравнить размер потоков различий во время выполнения. например запустить программу с 1 потоком, запустить программу с 2 потоками.... до 100 потоков (столько, сколько итерация). Так что я могу сравнить время выполнения. - person nanda; 29.02.2020
comment
Каков результат std::thread::hardware_concurrency() на вашем компьютере? - person Jérôme Richard; 29.02.2020
comment
Когда я бегу, это 8. - person nanda; 01.03.2020
comment
Я обнаружил, что если я ставлю номер потока больше 8, только 8 потоков работают как в динамическом, так и в управляемом планировании. Однако при статическом планировании работают все потоки. Как это происходит? - person nanda; 01.03.2020
comment
Ответ был обновлен, чтобы учесть эту информацию. - person Jérôme Richard; 01.03.2020