OpenMp任务:不能通过引用传递参数

ham*_*els 6 c++ openmp undefined-reference

g++ -fopenmp main.cpp抱怨未定义的引用std::vector.如何解决这个问题?

libomp-dev在Ubuntu上安装了这个包.

main.cpp中

#include<vector>
#include<iostream>

template<typename T, typename A>
T recursiveSumBody(std::vector<T, A> &vec) {
    T sum = 0;
    #pragma omp task shared(sum)
    {
        sum = recursiveSumBody(vec);
    }
    return vec[0];
}

int main() {
    std::vector<int> a;
    recursiveSumBody(a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

未定义的参考文献

/tmp/ccTDECNm.o: In function `int recursiveSumBody<int, std::allocator<int> >(std::vector<int, std::allocator<int> >&) [clone ._omp_cpyfn.1]':
main.cpp:(.text+0x148): undefined reference to `std::vector<int, std::allocator<int> >::vector(std::vector<int, std::allocator<int> > const&)'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

Zul*_*lan 5

要解决此问题,您可以手动指定shared(sum, vec)(强烈假设您希望它共享)。

有趣的是,较旧的 gcc 版本(例如 5.4.0)给出了更有用的错误消息:

error: 'vec' implicitly determined as 'firstprivate' has reference type
Run Code Online (Sandbox Code Playgroud)

而英特尔编译器icpc 17.0.1给出了一个“ internal error : 0_1855”。

手动指定firstprivateor private- 这在您的情况下意义不大 - 会导致其他更具描述性的错误。请注意,正如 Hristo Iliev 在其他评论中所解释的那样,firstprivate这意味着为每个线程制作向量的副本。

根据当前 (4.5) 标准:

在孤立任务生成构造中,如果不存在默认子句,则通过引用传递的正式参数为firstprivate

我想这适用于这里。更远,

出现在firstprivate子句中的变量不得具有不完整的 C/C++ 类型或对不完整类型的引用。如果firstprivate工作共享构造子句中的列表项具有引用类型,则它必须绑定到团队所有线程的同一对象。

它没有出现在条款中,但我认为这仍然是标准的意思。

现在我不认为这std::vector<T, A>是模板中的不完整类型,除非我遗漏了一些关于模板如何实例化的信息。所以我确实认为你的代码应该是有效的,并且考虑到每个线程都绑定到同一个对象,它实际上是有意义的。

所以我确实认为这是最近gcc版本以及英特尔编译器中的一个错误。看起来编译器无法为模板实例化一些东西。

进一步补充:

if (0) std::vector<T, A> wtf = vec;
Run Code Online (Sandbox Code Playgroud)

在函数的开头使代码编译并与gcc. 但是如果firstprivate是手动添加,gcc 会继续抱怨'vec' has incomplete type.

PS:OpenMP 4.5 中添加了允许数据共享属性子句中的引用类型,这是旧的 gcc 给出了不同的错误。