variant
variant copied to clipboard
Can't build mpark::visit under cuda compiler
I'm trying to build code using mpark::visit
, which compiles fine under gcc/clang, but fails to compile with CUDA compiler:
visit-test.cpp(11): error: no instance of function template "mpark::visit" matches the argument list
argument types are: (Visit, mpark::variant<int>)
I installed CUDA compiler on Ubuntu 18.04:
$ sudo apt-get install nvidia-cuda-toolkit
$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2017 NVIDIA Corporation
Built on Fri_Nov__3_21:07:56_CDT_2017
Cuda compilation tools, release 9.1, V9.1.85
Simple example:
#include <mpark/variant.hpp>
struct Visit {
std::string operator()(int i) const {
return "int";
}
};
void test() {
mpark::variant<int> i(1);
mpark::visit(Visit{}, i);
}
Here's the gist with makefile: https://git.zooxlabs.com/gist/rrishel/cbfb122a65cdb629f89233e1fa2bc96c
FWIW, building same example using boost::variant
works:
#include <boost/variant.hpp>
struct Visit : public boost::static_visitor<std::string> {
std::string operator()(int i) const {
return "int";
}
};
void test() {
boost::variant<int> i(1);
boost::apply_visitor(Visit{}, i);
}
Still fails with nvcc 10.2.89, but with a different error message:
variant.hpp: In function ‘constexpr decltype(auto) mpark::visit(Visitor&&, Vs&& ...)’:
variant.hpp:2674:96: error: parameter packs not expanded with ‘...’:
return (detail::all({!vs.valueless_by_exception()...})
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
variant.hpp:2674:96: note: ‘vs’
As a workaround, you can replace the implementation of the visit
function
template <typename Visitor, typename... Vs>
inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) {
return (detail::all({!vs.valueless_by_exception()...})
? (void)0
: throw_bad_variant_access()),
detail::visitation::variant::visit_value(
lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...);
}
with this:
template <typename Visitor, typename... Vs>
inline constexpr decltype(auto) visit(Visitor &&visitor, Vs &&... vs) {
return (detail::all(std::initializer_list<bool>({!vs.valueless_by_exception()...}))
? (void)0
: throw_bad_variant_access()),
detail::visitation::variant::visit_value(
lib::forward<Visitor>(visitor), lib::forward<Vs>(vs)...);
}
Note that nvcc has problems with the variadic brace-initializer. I've already reported the problem for nvcc 9.2.88 but it seems that the same bug reappeared...
Does #73 fix this?
Yes, it seems to work with https://github.com/mpark/variant/blob/d1cdfdd3f2ed80710ba4d671fe6bffaa3e28201a/master/variant.hpp
I actually am getting errors of the following form:
error: calling a __host__ function("mpark::detail::copy_assignment< ::mpark::detail::traits<....
I am currently able to work around this by adding __host__ __device__
to copy_assign
at lines 1420 and 1424 of variant.hpp
I imagine there are better solutions to this, anyone else run into this?
@dholladay00 Which version of variant.hpp
are you using? And please show the full error, there is not even a full signature of the function where it fails...
I am using the latest master of mpark variant with Cuda 10.1.
Here is a more detailed version of the error(s):
error: calling a __host__ function("mpark::detail::copy_assignment< ::mpark::detail::traits< ... > , ( ::mpark::detail::Trait)1> ::operator =") from a __device__ function("Kokkos::Impl::ParallelFor< ::Kokkos::Impl::ViewCopy< ::Kokkos::View< ... > *, ::Kokkos::LayoutLeft, ::Kokkos::Device< ::Kokkos::Serial, ::Kokkos::AnonymousSpace> , ::Kokkos::MemoryTraits<(unsigned int)0u> > , ::Kokkos::LayoutRight, ::Kokkos::Cuda, (int)1, long, (bool)0> , ::Kokkos::RangePolicy< ::Kokkos::Cuda, ::Kokkos::IndexType<long> > , ::Kokkos::Cuda> ::operator () const") is not allowed
error: identifier "mpark::detail::copy_assignment< ::mpark::detail::traits< ... > , ( ::mpark::detail::Trait)1> ::operator =" is undefined in device code
along with some warnings along these lines:
/.../include/mpark/variant.hpp(1052): warning: calling a __host__ function("mpark::detail::destructor< ::mpark::detail::traits< ... > , ( ::mpark::detail::Trait)1> ::~destructor") from a __host__ __device__ function("mpark::detail::destructor< ::mpark::detail::traits< ... > , ( ::mpark::detail::Trait)1> ::~destructor [subobject]") is not allowed