Функция "Pragma omp Parallel for" не работает, когда функция вызывается в другом параллельном цикле - PullRequest
1 голос
/ 10 октября 2019

Внутри параллельного цикла for я вызываю функцию, которая, в свою очередь, содержит дорогостоящие вычисления, которые я хотел бы распараллелить с остальными процессорами. Тем не менее, моя внутренняя директива «параллельно для» просто игнорируется.

Это для конвейера обработки изображений. Камера имеет 4 детектора и снимает, например, 100 изображений. Я хочу рассчитать для каждого детектора медиану из 100 входных изображений. Следовательно, мой внешний цикл использует 4 потока для 4 детекторов, и я хочу использовать оставшиеся ЦП для распараллеливания вычисления медианы во внутреннем цикле.

int main()
{
  // OUTER LOOP over various detectors
  # pragma omp parallel for
  for (int det=0; det<4; ++det) {
      // some serial work
      calculate_median(det);
  }
}

void calculate_median(int det)
{
   // some serial work

   #pragma omp parallel for num_threads(available_additional_threads)
   for (int pixel =0; pixel < numpixels; ++pixel) {
        // create a stack of pixels from the 100 input images
        // calculate median of stack
   }

   // more serial work
}

Я вычисляю дополнительные доступные потоки на основе того, сколькоДетекторы камеры и по количеству процессоров на машине пользователя. Таким образом, никогда не выполняется больше потоков, чем процессоров.

Я наблюдаю, что внутренняя «параллель для omp» игнорируется, то есть, независимо от значения «available_additional_threads», я получаю только один поток,ОДНАКО, если я установлю внешний цикл только на один поток, то внутреннее распараллеливание будет работать как положено. Это действительно озадачивает меня. Большое спасибо за любую дополнительную информацию!

ОБНОВЛЕНИЕ / РЕШЕНИЕ: установка 'omp_set_nested (true)' включила распараллеливание внутреннего цикла.

1 Ответ

0 голосов
/ 10 октября 2019

Вы можете использовать предложение свернуть, компилятор поддерживает OpenMP 3.0

#pragma omp parallel for collapse(2)
for (int x = 0; x < x_max; ++x) {
    for (int y = 0; y < y_max; ++y) { 
    //parallelize this code here
    }
//IMPORTANT: no code in here
}

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

Мой опытявляется то, что вложенные циклы имеют худшую производительность, чем один параллельный цикл, который хорошо панелизирован.

Обычно хорошей идеей является распараллеливание внешнего цикла. Поскольку ваш внешний цикл имеет только 4 итерации, я думаю, что разумно использовать OMP только для внутреннего цикла. Планировщик может лучше справляться с дисбалансом нагрузки.

Имейте в виду золотое правило рефакторинга производительности: мера.

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

...