Лучше ли использовать оговорку коллапса - PullRequest
0 голосов
/ 03 января 2019

Я никогда не уверен, какую возможность выбрать параллелизацию вложенных циклов.

Например, у меня есть следующий фрагмент кода:

#pragma omp parallel for schedule(static)
for(int b=0; b<bSize; b++)
    for(int n=0; n<N; n++) o[n + b*N] = b[n];


#pragma omp parallel for collapse(2) schedule(static)
for(int b=0; b<bSize; b++)
    for(int n=0; n<N; n++) o[n + b*N] = b[n];

В первом фрагменте я использую parallel forschedule(static) из-за политики первого касания). В некоторых кодах, которые я видел, люди используют главным образом коллапс-коллапс, чтобы парализовать вложенные циклы for в других кодах, которые он никогда не использует, вместо этого вложенные циклы for распараллеливаются с простым parallel for. Это больше привычка или есть разница между двумя версиями? Есть ли причина, по которой некоторые люди никогда не используют collapse(n)?

1 Ответ

0 голосов
/ 04 января 2019

Как и во всем в HPC, ответ «Это зависит ...»

Здесь это будет зависеть от

  1. Насколько велика ваша машина и насколько большие "bSize" и "N"
  2. Каково содержимое внутреннего цикла

Для статического планирования итераций, которые все выполняются за одно и то же время, если только вы не можете гарантировать, что количество итераций, распределяемых по работе, делится на количество потоков, вам необходимо убедиться, что количество доступных итераций составляет ~ 10x количество потоков гарантирует 90% эффективности из-за потенциального дисбаланса. Поэтому, если у вас 16-ядерная машина, вы хотите> 160 итераций. Если «bSize» невелик, то использование коллапса для создания более доступного параллелизма поможет повысить производительность (В худшем случае представьте, что «bSize» меньше, чем количество потоков!)

С другой стороны, как указывает @ tim18, если вы можете векторизовать внутренний цикл, сохраняя при этом достаточный параллелизм, что может быть лучше.

С третьей стороны, ничто не мешает вам сделать то и другое: -

#pragma omp for simd collapse(2)
for(int b=0; b<bSize; b++)
    for(int n=0; n<N; n++) o[n + b*N] = b[n];

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

...