【问题标题】:OpenMP reduction from within parallel region从并行区域内减少 OpenMP
【发布时间】:2020-03-10 00:58:14
【问题描述】:

如何在并行区域内进行 OpenMP 缩减(求和)? (只有主线程需要结果)。

算法原型:

#pragma omp parallel
{
    t = omp_get_thread_num();

    while iterate 
    {
        float f = get_local_result(t);

        // fsum is required on master only
        float fsum = // ? - SUM of f

        if (t == 0):
            MPI_Bcast(&fsum, ...);
}

如果我在 while iterate 循环中有 OpenMP 区域,则每次迭代的并行区域开销都会影响性能...

【问题讨论】:

  • 我认为您将 OpenMP 与 MPI 混淆了。 OpenMP 只关注共享内存架构,而 MPI 更关注分布式架构。是否要在多个 MPI 进程之间执行f 的缩减?
  • @JérômeRichard 这是一个混合代码。节点上的内核之间的 OpenMP,节点之间的 MPI。 OpenMP 主线程通过 MPI 与其他节点通信。

标签: openmp


【解决方案1】:

这是最简单的方法:

    float sharedFsum = 0.f;
    float masterFsum;

    #pragma omp parallel
    {
        const int t = omp_get_thread_num();

        while(iteration_condition)
        {
            float f = get_local_result(t);

            // Manual reduction
            #pragma omp update
            sharedFsum += f;

            // Ensure the reduction is completed
            #pragma omp barrier

            #pragma omp master
            MPI_Bcast(&sharedFsum, ...);

            // Ensure no other threads update sharedFsum during the MPI_Bcast
            #pragma omp barrier
        }
    }

如果您有很多线程(例如数百个),原子操作的成本可能会很高。更好的方法是让运行时为您执行归约。 这是一个更好的版本:

    float sharedFsum = 0;

    #pragma omp parallel
    {
        const int threadCount = omp_get_num_threads();
        float masterFsum;

        while(iteration_condition)
        {
            // Execute get_local_result on each thread and
            // perform the reduction into sharedFsum
            #pragma omp for reduction(+:sharedFsum) schedule(static,1)
            for(int i=0 ; i<threadCount ; ++i)
                sharedFsum += get_local_result(i);

            #pragma omp master
            {
                MPI_Bcast(&sharedFsum, ...);

                // sharedFsum must be reinitialized for the next iteration
                sharedFsum = 0.f;
            }

            // Ensure no other threads update sharedFsum during the MPI_Bcast
            #pragma omp barrier
        }
    }

旁注:

  • t 在您的代码中不受保护,请在 #pragma omp parallel 部分中使用 private(t) 以避免由于竞争条件导致的未定义行为。或者,您可以使用作用域变量。

  • #pragma omp master 应优先于以线程 ID 为条件的条件。

每次迭代的并行区域开销都会影响性能...

大多数情况下,这是由于(隐式)同步/通信或工作不平衡造成的。 上面的代码可能有同样的问题,因为它是非常同步的。 如果它在您的应用程序中有意义,您可以通过移除或移动与MPI_Bcastget_local_result 的速度有关的障碍,使其同步性降低(因此可能更快)。然而,正确做到这一点远非易事。一种方法是使用 OpenMP 任务多缓冲

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2021-10-01
    相关资源
    最近更新 更多