Added support for generation of random complex numbers on CUDA devices

This commit is contained in:
Benoit Steiner 2015-07-07 17:40:49 -07:00
parent 6de6fa9483
commit e6297741c9
3 changed files with 140 additions and 0 deletions

View File

@ -387,6 +387,58 @@ template <> class UniformRandomGenerator<double> {
mutable curandStatePhilox4_32_10_t m_state;
};
template <> class UniformRandomGenerator<std::complex<float> > {
public:
static const bool PacketAccess = false;
__device__ UniformRandomGenerator(bool deterministic = true) : m_deterministic(deterministic) {
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
const int seed = deterministic ? 0 : get_random_seed();
curand_init(seed, tid, 0, &m_state);
}
__device__ UniformRandomGenerator(const UniformRandomGenerator& other) {
m_deterministic = other.m_deterministic;
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
const int seed = m_deterministic ? 0 : get_random_seed();
curand_init(seed, tid, 0, &m_state);
}
template<typename Index>
__device__ std::complex<float> operator()(Index, Index = 0) const {
float4 vals = curand_uniform4(&m_state);
return std::complex<float>(vals.x, vals.y);
}
private:
bool m_deterministic;
mutable curandStatePhilox4_32_10_t m_state;
};
template <> class UniformRandomGenerator<std::complex<double> > {
public:
static const bool PacketAccess = false;
__device__ UniformRandomGenerator(bool deterministic = true) : m_deterministic(deterministic) {
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
const int seed = deterministic ? 0 : get_random_seed();
curand_init(seed, tid, 0, &m_state);
}
__device__ UniformRandomGenerator(const UniformRandomGenerator& other) {
m_deterministic = other.m_deterministic;
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
const int seed = m_deterministic ? 0 : get_random_seed();
curand_init(seed, tid, 0, &m_state);
}
template<typename Index>
__device__ std::complex<double> operator()(Index, Index = 0) const {
double2 vals = curand_uniform2_double(&m_state);
return std::complex<double>(vals.x, vals.y);
}
private:
bool m_deterministic;
mutable curandStatePhilox4_32_10_t m_state;
};
#endif
@ -489,6 +541,58 @@ template <> class NormalRandomGenerator<double> {
mutable curandStatePhilox4_32_10_t m_state;
};
template <> class NormalRandomGenerator<std::complex<float> > {
public:
static const bool PacketAccess = false;
__device__ NormalRandomGenerator(bool deterministic = true) : m_deterministic(deterministic) {
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
const int seed = deterministic ? 0 : get_random_seed();
curand_init(seed, tid, 0, &m_state);
}
__device__ NormalRandomGenerator(const NormalRandomGenerator& other) {
m_deterministic = other.m_deterministic;
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
const int seed = m_deterministic ? 0 : get_random_seed();
curand_init(seed, tid, 0, &m_state);
}
template<typename Index>
__device__ std::complex<float> operator()(Index, Index = 0) const {
float4 vals = curand_normal4(&m_state);
return std::complex<float>(vals.x, vals.y);
}
private:
bool m_deterministic;
mutable curandStatePhilox4_32_10_t m_state;
};
template <> class NormalRandomGenerator<std::complex<double> > {
public:
static const bool PacketAccess = false;
__device__ NormalRandomGenerator(bool deterministic = true) : m_deterministic(deterministic) {
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
const int seed = deterministic ? 0 : get_random_seed();
curand_init(seed, tid, 0, &m_state);
}
__device__ NormalRandomGenerator(const NormalRandomGenerator& other) {
m_deterministic = other.m_deterministic;
const int tid = blockIdx.x * blockDim.x + threadIdx.x;
const int seed = m_deterministic ? 0 : get_random_seed();
curand_init(seed, tid, 0, &m_state);
}
template<typename Index>
__device__ std::complex<double> operator()(Index, Index = 0) const {
double2 vals = curand_normal2_double(&m_state);
return std::complex<double>(vals.x, vals.y);
}
private:
bool m_deterministic;
mutable curandStatePhilox4_32_10_t m_state;
};
#else
template <typename T> class NormalRandomGenerator {

View File

@ -144,5 +144,6 @@ if(EIGEN_TEST_CXX11)
# ei_add_test(cxx11_tensor_cuda "-std=c++0x")
# ei_add_test(cxx11_tensor_contract_cuda "-std=c++0x")
# ei_add_test(cxx11_tensor_reduction_cuda "-std=c++0x")
# ei_add_test(cxx11_tensor_random_cuda "-std=c++0x")
endif()

View File

@ -0,0 +1,35 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#define EIGEN_TEST_NO_LONGDOUBLE
#define EIGEN_TEST_NO_COMPLEX
#define EIGEN_TEST_FUNC cxx11_tensor_random_cuda
#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int
#define EIGEN_USE_GPU
#include "main.h"
#include <Eigen/CXX11/Tensor>
static void test_default()
{
Tensor<std::complex<float>, 1> vec(6);
vec.setRandom();
// Fixme: we should check that the generated numbers follow a uniform
// distribution instead.
for (int i = 1; i < 6; ++i) {
VERIFY_IS_NOT_EQUAL(vec(i), vec(i-1));
}
}
void test_cxx11_tensor_random_cuda()
{
CALL_SUBTEST(test_default());
}