Как работает заказываемая статья omp?

vector<int> v;

#pragma omp parallel for ordered schedule(dynamic, anyChunkSizeGreaterThan1)
    for (int i = 0; i < n; ++i){
            ...
            ...
            ...
#pragma omp ordered
            v.push_back(i);
    }

Это заполняет v упорядоченным списком размера n.

При достижении блока omp ordered все потоки должны дождаться завершения последней нити, связанной с итерацией, но что, если ни один из потоков не был назначен этой конкретной итерацией? Или библиотека OpenMP во время выполнения всегда следит за тем, чтобы наименьшая итерация обрабатывалась каким-то потоком?

Также почему предлагается, чтобы предложение ordered использовалось вместе с dynamic schedule? Повлияет ли static schedule на производительность?

Ответ 1

Предложение ordered работает следующим образом: разные потоки выполняются одновременно, пока они не столкнутся с областью ordered, которая затем выполняется последовательно в том же порядке, в каком она будет выполняться в последовательном цикле. Это все еще допускает некоторую степень concurrency, особенно если область кода вне области ordered имеет значительное время выполнения.

Нет особых причин использовать расписание dynamic вместо расписания static с небольшим размером блока. Все зависит от структуры кода. Поскольку ordered вводит зависимость между потоками, если используется с schedule(static) с размером блока по умолчанию, второй поток должен будет дождаться, когда первый завершит все итерации, тогда третий поток должен будет дождаться второго закончите свои итерации (и, следовательно, для первого), и так далее. Легко визуализировать его с помощью 3 потоков и 9 итераций (3 на поток):

tid  List of     Timeline
     iterations
0    0,1,2       ==o==o==o
1    3,4,5       ==.......o==o==o
2    6,7,8       ==..............o==o==o

= показывает, что поток выполняет код параллельно. o - это когда поток выполняет область ordered. . - это нить, находящаяся в режиме ожидания, ожидая своего поворота для выполнения области ordered. С помощью schedule(static,1) произойдет следующее:

tid  List of     Timeline
     iterations
0    0,3,6       ==o==o==o
1    1,4,7       ==.o==o==o
2    2,5,8       ==..o==o==o

Я считаю, что разница в обоих случаях более чем очевидна. При schedule(dynamic) приведенные выше снимки станут более или менее случайными, так как список итераций, назначенных каждому потоку, не является детерминированным. Это также добавит дополнительные накладные расходы. Это полезно только в том случае, если количество вычислений различно для каждой итерации, и для вычисления требуется гораздо больше времени, чем добавленные накладные расходы на использование динамического планирования.

Не беспокойтесь о наименьшей нумерованной итерации. Обычно он обрабатывается первым потоком в команде, чтобы стать готовым к выполнению кода.