Opened 5 years ago

Closed 4 years ago

#13513 closed Bugs (obsolete)

Nvidia cuda compiler 9 does not work with boost::mp11

Reported by: Alexander Matthes <a.matthes@…> Owned by:
Milestone: To Be Determined Component: None
Version: Boost 1.66.0 Severity: Showstopper
Keywords: Cc:

Description

I am working with cuda and I choose to use boost::mp11 for my projects. However cuda 9 does not work with boost::mp11, even this simple application fails:

#include <boost/mp11.hpp>
int main() {}

To be fair, this seems to be a bug in the nvidia compiler not boost, but this is a showstopper for using boost::mp11 together with a recent cuda version. Everything works fine with cuda 8.

I already figured out, what fails in the background in the nvcc (details are here), but now also found a work around for boost::mp11:

The problem occurs on code like this:

template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;

Everytime mp_if is used, the nvcc preprocessor tries to be "smart" and starts recursively replacing stuff so that in the end detail::mp_no_type... is given to the compiler.

I figured out I can prevent nvcc from doing this with invoking another struct inbetween like this:

template<template<class...> class F, class... T>
struct cuda_workaround
{
    using type = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
};

template<template<class...> class F, class... T>
using mp_defer = typename cuda_workaround< F, T... >::type;

This work around is needed on 5 places in the boost mp11:

  • mp_append.hpp
    template<class... L> struct mp_append_impl: mp_if_c<(sizeof...(L) > 111), mp_quote<append_inf_impl>, mp_if_c<(sizeof...(L) > 11), mp_quote<append_111_impl>, mp_quote<append_11_impl> > >::template fn<L...>
    
  • algorithm.hpp
    template<template<class...> class F, class... L> using mp_transform = typename mp_if<mp_same<mp_size<L>...>, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>::type;
    
    template<class L, std::size_t I> using mp_at_c = typename mp_if_c<(I < mp_size<L>::value), detail::mp_at_c_impl<L, I>, void>::type;
    
        using type = typename mp_cond<
    
            mp_bool<(I < N1)>, mp_nth_element_impl<L1, I, P>,
            mp_bool<(I == N1)>, mp_identity<T1>,
            mp_true, mp_nth_element_impl<L2, I - N1 - 1, P>
    
        >::type;
    
  • utility.hpp
    template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
    

I added an intermediate struct as seen above for every case if cuda 9 is used and now my code compiles with nvcc 9.

So I suggest to add such a work around for cuda 9 and above. I can also do this myself, what would be the best way? Providing a patch for the most recent version on github or directly opening a pull request?

Change History (2)

comment:1 by Alexander Matthes <a.matthes@…>, 5 years ago

I opened a PR in the mp11 github: https://github.com/boostorg/mp11/pull/21

comment:2 by John Maddock, 4 years ago

Resolution: obsolete
Status: newclosed
Note: See TracTickets for help on using tickets.