OpenMp Task: can't pass argument by reference

c++, openmp, undefined-reference

Solution

To fix the issue, you can manually specify `shared(sum, vec)` (strongly assuming you want it shared).

Interestingly enough older gcc versions (e.g. 5.4.0) give a much more helpful error message:

error: 'vec' implicitly determined as 'firstprivate' has reference type

Whereas the Intel compiler `icpc 17.0.1` gives an "`internal error : 0_1855`".

Manually specifying `firstprivate` or `private` - which makes little sense in your case - results in other more descriptive errors. Note, as Hristo Iliev explained in the other comments, `firstprivate` would mean that a copy of the vector is made for each thread.

As per the current (4.5) standard:

In an orphaned task generating construct, if no default clause is present, formal arguments passed by reference are `firstprivate`.

I suppose that applies here. Further,

A variable that appears in a `firstprivate` clause must not have an incomplete C/C++ type or be a reference to an incomplete type. If a list item in a `firstprivate` clause on a worksharing construct has a reference type then it must bind to the same object for all threads of the team.

It doesn't appear in a clause, but I think this is still what the standard means.

Now I don't think that `std::vector<T, A>` is an incomplete type within the template, unless I am missing something about how templates are instantiated. So I do think your code should be valid and given that each thread just binds to the same object, it actually would make sense.

So I do think this is a bug in recent `gcc` versions as well as the Intel compiler. It looks like the compiler fails to instantiate some things for the template.

Further, adding:

if (0) std::vector<T, A> wtf = vec;

at the beginning of the function makes the code compile and link with `gcc`. But if `firstprivate` is added manually, gcc continues to complain that `'vec' has incomplete type`.

P.S.: Allowing reference types in data sharing attribute clauses was added in OpenMP 4.5, this is the old gcc gives a different error.

Problem

`g++ -fopenmp main.cpp` complains about undefined reference to `std::vector`. How to fix this? I have installed the `libomp-dev` package on 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; } ``` Undefined References ``` /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 ```

Original source