c++ - 简单的基于任务的 OpenMP 应用程序挂起

标签 c++ openmp

下面的小程序 ( online version ) 尝试通过递归地划分为四个正方形直到最小的正方形具有单位长度(很难说是最佳的)来计算 64 x 64 正方形的面积。但由于某种原因,程序挂起。做错了什么?

#include <iostream>

unsigned compute( unsigned length )
{
    if( length == 1 ) return length * length;

    unsigned a[4] , area = 0 , len = length/2;

    for( unsigned i = 0; i < 4; ++i )
    {
        #pragma omp task
        {
            a[i] = compute( len );
        }

        #pragma omp single
        {
            area += a[i];
        }
    }

    return area;
}

int main()
{
    unsigned area , length = 64;

    #pragma omp parallel
    {
        area = compute( length );
    }

    std::cout << area << std::endl;
}

最佳答案

single 构造充当团队中所有线程的隐式屏障。然而,并不是团队中的所有线程都会遇到这个单一的 block ,因为不同的线程工作在不同的递归深度。这就是您的应用程序挂起的原因。

无论如何,您的代码都不正确。在您的任务 block 之后,a[i]尚未分配,因此您无法立即使用它!您必须等待任务完成。当然,您不应该在循环内执行此操作,否则任务分配将不会利用任何并行性。解决方案是在循环末尾执行此操作。此外,您还必须将 a 指定为共享,以使输出可见:

for( unsigned i = 0; i < 4; ++i )
{
    #pragma omp task shared(a)
    {
        a[i] = compute( len );
    }
}
#pragma omp taskwait
for( unsigned i = 0; i < 4; ++i )
{
    area += a[i];
}

请注意,缩减并未包装在单个构造中!计算是由一项任务执行的,因此只有一个线程应该拥有自己的本地区域。但是,在首次生成任何任务之前,您需要一个single 构造:

#pragma omp parallel
#pragma omp single
{
    area = compute( length );
}

简单来说,这会打开一个包含一组线程的并行区域,并且只有一个线程开始初始计算。其他线程将使用 task 构造获取此初始线程稍后生成的任务。这就是任务分配的意义所在。

关于c++ - 简单的基于任务的 OpenMP 应用程序挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38460374/

相关文章:

c - 为什么用OpenMP生成随机数没有提速?

c++ - 与 omp 并行

mpi - 运行混合 MPI 的最佳方式 - OpenMP 作业

c++ - OpenCV 调整质量

c - 当线程执行for循环迭代时如何继续与master一起工作?

c++ - 试除法代码在 Windows 上运行 32 位比在 Linux 上运行 64 位快 2 倍

c++ - CRT虚拟析构函数

c++ - 使用 omp_set_num_threads() 将线程数设置为 2,但 omp_get_num_threads() 返回 1

c++ - 链接问题 tinylibxml C++ Ubuntu

c++ - 在 OpenCV 中排序矩阵