g++ -fopenmp main.cpp
抱怨对std::vector
的未定义引用。如何解决这个问题?
我在Ubuntu上安装了libomp-dev
包。
的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;
}
未定义的参考文献
/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
答案 0 :(得分:4)
要解决此问题,您可以手动指定shared(sum, vec)
(强烈假设您希望它共享)。
有趣的是,较旧的gcc版本(例如5.4.0)提供了更有用的错误消息:
error: 'vec' implicitly determined as 'firstprivate' has reference type
英特尔编译器icpc 17.0.1
提供“internal error : 0_1855
”。
手动指定firstprivate
或private
- 这在您的情况下毫无意义 - 会导致其他更具描述性的错误。请注意,正如Hristo Iliev在其他评论中所解释的那样,firstprivate
意味着为每个线程创建了一个向量副本。
根据目前的(4.5)标准:
在孤立的任务生成构造中,如果不存在默认子句,则通过引用传递的正式参数为
firstprivate
。
我想这适用于此。此外,
firstprivate
子句中出现的变量不能包含不完整的C / C ++类型,也不能是对不完整类型的引用。 如果工作共享构造的firstprivate
子句中的列表项具有引用类型,则它必须绑定到团队的所有线程的同一对象。
它没有出现在一个条款中,但我认为这仍然是标准的含义。
现在我认为std::vector<T, A>
在模板中不是一个不完整的类型,除非我遗漏了一些关于如何实例化模板的内容。所以我认为你的代码应该是有效的,并且假设每个线程只绑定到同一个对象,它实际上是有意义的。
所以我认为这是最近的gcc
版本以及英特尔编译器中的错误。看起来编译器无法为模板实例化一些东西。
此外,添加:
if (0) std::vector<T, A> wtf = vec;
在函数的开头使代码编译并与gcc
链接。但如果手动添加firstprivate
,gcc会继续抱怨'vec' has incomplete type
。
P.S。:在OpenMP 4.5中添加了允许数据共享属性子句中的引用类型,这是旧的gcc给出了不同的错误。
答案 1 :(得分:1)
如果您还将vec
声明为共享变量,问题就会消失:
#pragma omp task shared(sum, vec)
似乎task
的默认可见性为firstprivate
,未按预期分享。您可以在this forum entry中找到更多信息。