While porting a code from Linux to Windows, thanks to Visual Studio C++ 2015 Community, I encountered a compilation error that I cannot understand. Below is a sample program exhibiting this error, building a vector of doubles and then sorting it with cuda thrust, using OpenMP.
# include <thrust/sort.h>
# include <thrust/system/omp/execution_policy.h>
# include <chrono>
# include <random>
# include <vector>
double unit_random()
{
static std::default_random_engine generator(std::chrono::system_clock::now().time_since_epoch().count());
static std::uniform_real_distribution<double> distribution(double(0), double(1));
return distribution(generator);
}
int main(int argc, char* argv[])
{
constexpr size_t input_size = 100000;
std::vector< double > input(input_size, 0);
for ( size_t i = 0; i < input_size; ++i)
input[i] = unit_random() * 1000;
thrust::sort(thrust::omp::par, input.begin(), input.end());
return 0;
}
Here is the error seen in the Visual Studio console (file names are shortened):
thrust/system/omp/detail/sort.inl(136): error C2146: syntax error: missing ';' before identifier 'nseg'
thrust/detail/sort.inl(83): note: see reference to function template instantiation 'void thrust::system::omp::detail::stable_sort<thrust::system::omp::detail::par_t,RandomAccessIterator,StrictWeakOrdering>(thrust::system::omp::detail::execution_policy<thrust::system::omp::detail::par_t> &,RandomAccessIterator,RandomAccessIterator,StrictWeakOrdering)' being compiled
with
[
RandomAccessIterator=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>,
StrictWeakOrdering=thrust::less<value_type>
]
thrust/system/detail/generic/sort.inl(63): note: see reference to function template instantiation 'void thrust::stable_sort<DerivedPolicy,RandomAccessIterator,StrictWeakOrdering>(const thrust::detail::execution_policy_base<DerivedPolicy> &,RandomAccessIterator,RandomAccessIterator,StrictWeakOrdering)' being compiled
with
[
DerivedPolicy=thrust::system::omp::detail::par_t,
RandomAccessIterator=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>,
StrictWeakOrdering=thrust::less<value_type>
]
thrust/detail/sort.inl(56): note: see reference to function template instantiation 'void thrust::system::detail::generic::sort<Derived,RandomAccessIterator,StrictWeakOrdering>(thrust::execution_policy<Derived> &,RandomAccessIterator,RandomAccessIterator,StrictWeakOrdering)' being compiled
with
[
Derived=thrust::system::omp::detail::par_t,
RandomAccessIterator=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>,
StrictWeakOrdering=thrust::less<value_type>
]
thrust/system/detail/generic/sort.inl(49): note: see reference to function template instantiation 'void thrust::sort<DerivedPolicy,RandomAccessIterator,thrust::less<value_type>>(const thrust::detail::execution_policy_base<DerivedPolicy> &,RandomAccessIterator,RandomAccessIterator,StrictWeakOrdering)' being compiled
with
[
DerivedPolicy=thrust::system::omp::detail::par_t,
RandomAccessIterator=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>,
StrictWeakOrdering=thrust::less<value_type>
]
thrust/detail/sort.inl(41): note: see reference to function template instantiation 'void thrust::system::detail::generic::sort<Derived,RandomAccessIterator>(thrust::execution_policy<Derived> &,RandomAccessIterator,RandomAccessIterator)' being compiled
with
[
Derived=thrust::system::omp::detail::par_t,
RandomAccessIterator=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>
]
windows_cuda_thrust_error.cc(24): note: see reference to function template instantiation 'void thrust::sort<DerivedPolicy,std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>>(const thrust::detail::execution_policy_base<DerivedPolicy> &,RandomAccessIterator,RandomAccessIterator)' being compiled
with
[
DerivedPolicy=thrust::system::omp::detail::par_t,
RandomAccessIterator=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<double>>>
]
thrust/system/omp/detail/sort.inl(136): error C2275: 'IndexType': illegal use of this type as an expression
thrust/system/omp/detail/sort.inl(113): note: see declaration of 'IndexType'
thrust/system/omp/detail/sort.inl(136): error C2065: 'nseg': undeclared identifier
thrust/system/omp/detail/sort.inl(142): error C2065: 'nseg': undeclared identifier
thrust/system/omp/detail/sort.inl(159): error C2065: 'nseg': undeclared identifier
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
The same code works fine on Linux.
How are we supposed to specify an OpenMP execution policy in a cuda thrust call on Windows? Alternatively, what I am doing wrong in this particular context?
The thrust version used is 1.8.1 and here is an excerpt of the thrust function, in file thrust/system/omp/detail/sort.inl, raising the compilation errors:
template<typename DerivedPolicy,
typename RandomAccessIterator,
typename StrictWeakOrdering>
void stable_sort(execution_policy<DerivedPolicy> &exec,
RandomAccessIterator first,
RandomAccessIterator last,
StrictWeakOrdering comp)
{
// ...
typedef typename thrust::iterator_difference<RandomAccessIterator>::type IndexType;
if(first == last)
return;
#pragma omp parallel
{
thrust::system::detail::internal::uniform_decomposition<IndexType> decomp(last - first, 1, omp_get_num_threads());
// process id
IndexType p_i = omp_get_thread_num();
// every thread sorts its own tile
if(p_i < decomp.size())
{
thrust::stable_sort(thrust::seq,
first + decomp[p_i].begin(),
first + decomp[p_i].end(),
comp);
}
#pragma omp barrier
IndexType nseg = decomp.size(); // line 136
// ...
}
}
As suggested by @kangshiyin, I filed an issue on github (see issue #817) and thrust developers found a workaround. The problem came from the way MSVC currently deals with OpenMP code, so the code provided in the question was perfectly fine.
If a similar problem arise, try first to update to the latest version of thrust. You can also try to apply the same workaround: simply add a semi-colon before the line raising the error.