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