mercredi 7 août 2019

CUDA 10.1 compile error with SFINAE templates

CUDA 10.1
g++ 7.3

For the purposes of a unit testing suite, I need large sets of repeatable data (more than can be hard-coded). I came up with this "generator" paradigm, with the idea that it could be used to fill arbitrary containers with data.

Now I need to extend the generator to populate multivalue containers (float2, int2, thrust::complex). My solution is to use SFINAE to conditionally define a function based on whether it can be constructed from a single value or requires a pair of values.

The below code compiles fine with GCC (-std=c++1z) but fails with nvcc (-std=c++14)

#include <random>
#include <type_traits>

template <typename T>
class RandomGenerator
{
public:
    RandomGenerator(T min, T max, unsigned seed = 42);

    // Generate the next element in the sequence. This requires keeping all the necessary state
    // to advance
    T operator()();

    // fill a container if it is scalar
    template<typename Container>
    typename std::enable_if_t<std::is_constructible_v<typename Container::value_type, T>>
    fill( Container& c );

    // fill a container if it takes 2 values (e.g., complex)
    template<typename Container>
    typename std::enable_if_t<std::is_constructible_v<typename Container::value_type, T, T>>
    fill2( Container& c );

protected:
private:
    std::uniform_real_distribution< T > dist;
    std::mt19937 rng;
};


// Constructor - define the domain of this generation
template <typename T>
RandomGenerator<T>::RandomGenerator(T min, T max, unsigned seed)
    : dist(min, max)
    , rng()
{
    rng.seed(seed);
}

// generate one random number
template <typename T>
T
RandomGenerator<T>::operator()()
{
    return dist(rng);
}

template <typename T>
template<typename Container>
typename std::enable_if_t<std::is_constructible_v<typename Container::value_type, T>>
RandomGenerator<T>::fill( Container& c )
{
    std::generate(c.begin(), c.end(), *this);
}

template <typename T>
template<typename Container>
typename std::enable_if_t<std::is_constructible_v<typename Container::value_type, T, T>>
RandomGenerator<T>::fill2( Container& c )
{
    std::generate(c.begin(), c.end(), [this]() { return typename Container::value_type( (*this)(), (*this)() ); });
}



The compiler error:

/usr/local/cuda/bin/nvcc  -g -Xcompiler=-fPIE -gencode=arch=compute_60,code=sm_60 --std=c++14 --use_fast_math -Xcompiler -pthread -x cu -dc unittest.cu -o unittest.cu.o
RandomGenerator.hh(30): error: namespace "std" has no member "is_constructible_v"

RandomGenerator.hh(30): error: type name is not allowed

RandomGenerator.hh(30): error: expected an identifier

RandomGenerator.hh(34): error: namespace "std" has no member "is_constructible_v"

RandomGenerator.hh(34): error: type name is not allowed

RandomGenerator.hh(34): error: too many arguments for alias template "std::enable_if_t"

RandomGenerator.hh(34): error: expected an identifier

RandomGenerator.hh(63): error: namespace "std" has no member "is_constructible_v"

RandomGenerator.hh(63): error: type name is not allowed

RandomGenerator.hh(63): error: expected an identifier

RandomGenerator.hh(71): error: namespace "std" has no member "is_constructible_v"

RandomGenerator.hh(71): error: type name is not allowed

RandomGenerator.hh(71): error: too many arguments for alias template "std::enable_if_t"

RandomGenerator.hh(71): error: expected a ";"


Am I missing something? Is there a way to pass this to CUDA?

Aucun commentaire:

Enregistrer un commentaire