并行任务中的 C++ OpenMP 变量可见性

Posted

技术标签:

【中文标题】并行任务中的 C++ OpenMP 变量可见性【英文标题】:C++ OpenMP variable visibility in parallel tasks 【发布时间】:2010-07-20 17:10:27 【问题描述】:

不明白,我哪里弄错了。如果在没有 openmp 支持的情况下编译,代码可以正常工作。但是使用 openmp 变量似乎得到了错误的可见性。

我有以下意图。每个线程都有自己的 max_private,它可以在其中找到局部最大值。然后在临界区找到全局最大值。

#include <iostream>
#include <vector>

typedef std::vector<long> Vector;

long max(const Vector& a, const Vector& b)

    long max = 0;
    #pragma omp parallel
    
        long max_private = 0;

        #pragma omp single
        
            for (   Vector::const_iterator a_it = a.begin();
                    a_it != a.end();
                    ++a_it)
            
                #pragma omp task
                
                    for (   Vector::const_iterator b_it = b.begin();
                            b_it != b.end();
                            ++b_it)
                    
                        if (*a_it + *b_it > max_private) 
                            max_private = *a_it + *b_it;
                        
                    
                
            
        

        #pragma omp critical
        
            std::cout << max_private << std::endl;
            if (max_private > max) 
                max = max_private;
            
        
    
    return max;


int main(int argc, char* argv[])

    Vector a(100000);
    Vector b(10000);
    for (long i = 0; i < a.size(); ++i) 
        a[i] = i;
    
    for (long i = 0; i < b.size(); ++i) 
        b[i] = i * i;
    

    std::cout << max(a, b) << std::endl;

    return 0;

我不想使用并行,因为后者我将使用不支持随机访问迭代器的数据结构。

我用的是g++-4.4编译器。

【问题讨论】:

【参考方案1】:

在 OpenMP 论坛上获得了详细答案。 http://openmp.org/forum/viewtopic.php?f=3&t=912&start=0

必须将 max_private 线程设为私有。

【讨论】:

【参考方案2】:

我认为您需要的是变量的一些属性。默认情况下,所有变量都是共享的,并且由于您希望 max_private 是每个线程的,您可以愉快地在其声明中添加 'private' 子句(那样可能会快一点)。

对于 max,您需要将其放在 omp 块中,如果仍然无法正常工作,则将其标记为“共享”(尽管应该没问题)

所以,我认为您想要#pragma omp parallel private(max_private) 并将这两个变量放在主 omp 块之外。

【讨论】:

我已经尝试了您在第三段中的建议,但它对我不起作用。这是确保我理解正确的差异: 9c9,10 long max_private = 0; > #pragma omp parallel private(max_private) 11,12c12 max_private = 0; 看起来任务中的 max_private 永远不会复制回每个线程本地的 max_private 嗯。不确定 - 但我会尝试将 'private(max_private)' 添加到 '#pragma omp task' 指令中。【参考方案3】:

您需要减少 openmp 以找到最大值。它在 OpenMP 3.0 中可用

在for上做减法

long max(const Vector& a, const Vector& b)

    long max_val = 0;  // <- change the name for clarity
    #pragma omp parallel reduction(max : max_val)
     
      [...] 
      #pragma omp critical
      
        std::cout << max_private << std::endl;
        if (max_private > max_val) 
            max_val = max_private;
        
      
    
    return max_val; 

max_val 在每个线程中都是私有的,在循环结束时会发生缩减并返回每个 open_mp 线程的最大值。

【讨论】:

以上是关于并行任务中的 C++ OpenMP 变量可见性的主要内容,如果未能解决你的问题,请参考以下文章

openMP 并行部分中的共享变量有些奇怪

使用 OpenMP 的多级并行性 - 可能吗?聪明的?实际的?

OpenMP 中的 C++ 动态内存分配速度较慢,即使对于非并行代码段也是如此

如何为Fibonacci算法设计并行代码,但没有openmp任务?

在 C++ 中使用 OpenMP 并行化算法

如何使用 OpenMP 通过 C++ std::list 并行化 for 循环?