OpenMP: как правильно вложить как MASTER, так и FOR в ПАРАЛЛЕЛЬНЫЙ блок?

#c #c #multithreading #openmp #openmpi

#c #c #многопоточность #openmp #openmpi

Вопрос:

Я работаю над программой как с OpenMP, так и с OpenMPI.

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

Структура кода выглядит так:

 int computation(...)
{
    #pragma parallel for .....
}

int main(...)
{
    ...
    if (mpi_rank == 0) // initial node
    {
        #pragma omp parallel
        {
            #pragma omp master
            {
                // task scheduling for other nodes
            }
            {
                // WRONG: said 4 threads in total, this block will be executed for
                // 3 times simultaneously, and the nested "for" in the function
                // will spawn 4 threads each as well
                // so ACTUALLY 3*4 1=13 threads here!
                int computation(...);
            }
        }
    }
    else // other nodes
    {
        // get a task from node 0 scheduler by MPI
        int computation(...);
    }
}
  

Я хочу, чтобы в начальном узле планировщик выполнял один поток, и одновременно выполнялась только одна вычислительная функция, поэтому одновременно используется не более 4 потоков.

Я тоже пробовал:

 int computation(...)
{
    register int thread_use = omp_get_max_threads();    // this is 4
    if (rank == 0)
    {
        --thread_use;   // if initial node, use 3
    }
    #pragma parallel for ..... num_threads(thread_use)
}

int main(...)
{
    ...
    if (mpi_rank == 0) // initial node
    {
        #pragma omp parallel
        {
            #pragma omp master
            {
                // task scheduling for other nodes
            }
            #pragma omp single
            {
                // WRONG: nest "for" can only use 1 thread
                int computation(...);
            }
        }
    }
    else // other nodes
    {
        // get a task from node 0 scheduler by MPI
        int computation(...);
    }
}
  

…или

 //other parts are the same as above
if (mpi_rank == 0) // initial node
{
    #pragma omp parallel num_threads(2)
    {
        #pragma omp master
        {
            // task scheduling for other nodes
        }
        {
            // WRONG: nest "for" can only use 1 thread
            int computation(...);
        }
    }
}
  

…но ни один из них не работал.

Как я должен упорядочить блоки с помощью OpenMP для достижения моей цели? Любая помощь будет оценена, большое спасибо.

Ответ №1:

Прежде всего, если вы хотите указать вложенный параллелизм в OpenMP, вам необходимо установить переменную окружения OMP_NESTED на true .

Тогда возможная реализация может выглядеть следующим образом:

 // Parallel region. Topmost level
#pragma omp parallel sections num_threads(2)
{
    #pragma omp section
    scheduling_function();

    #pragma omp section
    compute_function();
}
  

Где scheduling_function() находится однопоточная функция, а compute_function() структура похожа на:

 void compute_function() {
    // Nested parallel region. Bottommost level
    #pragma omp parallel
    {
        computation();
    }
}
  

Дополнительная информация о вложенном параллелизме OpenMP

Комментарии:

1. Потрясающе! Большое спасибо.

2. Примите во внимание, что вы также можете установить количество потоков, используемых на каждом уровне вложенности, со значениями, разделенными запятыми, в OMP_NUM_THREADS переменной среды.