Files
triton/tests/common/api.hpp

388 lines
11 KiB
C++
Raw Normal View History

2014-08-30 18:02:17 -04:00
#ifndef TEST_COMMON_HPP_
#define TEST_COMMON_HPP_
#include <cassert>
#include <vector>
#include <algorithm>
#include <functional>
#include "isaac/array.h"
2014-08-30 18:02:17 -04:00
namespace sc = isaac;
typedef isaac::int_t int_t;
2014-08-30 18:02:17 -04:00
template<typename T> struct numeric_trait;
template<> struct numeric_trait<float> { static constexpr float epsilon = 1e-4; static const char* name; };
template<> struct numeric_trait<double> { static constexpr double epsilon = 1e-8; static const char* name; };
const char * numeric_trait<float>::name = "float";
const char * numeric_trait<double>::name = "double";
2015-06-25 23:12:26 -07:00
template<class T> struct BLAS;
template<> struct BLAS<float> { template<class FT, class DT> static FT F(FT SAXPY, DT ) { return SAXPY; } };
template<> struct BLAS<double> { template<class FT, class DT> static DT F(FT , DT DAXPY) { return DAXPY; } };
enum interface_t
{
clBLAS,
2015-11-20 02:56:33 -05:00
cuBLAS,
CPP
};
2015-06-27 11:44:50 -04:00
cl_mem cl(sc::array_base const & x) { return x.data().handle().cl(); }
CUdeviceptr cu(sc::array_base const & x) { return x.data().handle().cu(); }
CUdeviceptr off(sc::array_base const & x) { return x.start(); }
CUdeviceptr inc(sc::array_base const & x) { return x.stride()[0]; }
CUdeviceptr ld(sc::array_base const & x) { return x.stride()[1]; }
template<class Iterator>
std::string join(Iterator begin, Iterator end, std::string delimiter){
std::string result;
while(begin!=end){
result += *begin;
if(++begin!=end) result += delimiter;
}
return result;
}
2015-06-27 13:53:31 -04:00
/*------ Simple Vector ---------*/
template<class T>
class simple_vector_base
2014-08-30 18:02:17 -04:00
{
public:
typedef T value_type;
simple_vector_base(int_t start, int_t end, int_t stride, std::vector<T> & data) : N_((end-start)/stride), start_(start),
stride_(stride), data_(data)
{ }
int_t size() const { return N_; }
int_t start() const { return start_; }
int_t stride() const { return stride_; }
std::vector<T> & data() { return data_; }
T & operator[](int_t i) { return data_[start_ + i*stride_]; }
T operator[](int_t i) const { return data_[start_ + i*stride_]; }
2014-08-30 18:02:17 -04:00
private:
int_t N_;
int_t start_;
int_t stride_;
std::vector<T> & data_;
2014-08-30 18:02:17 -04:00
};
template<class T>
class simple_vector : public simple_vector_base<T>
2014-08-30 18:02:17 -04:00
{
public:
simple_vector(int_t N) : simple_vector_base<T>(0, N, 1, data_), data_(N){}
2014-08-30 18:02:17 -04:00
private:
std::vector<T> data_;
2014-08-30 18:02:17 -04:00
};
template<class T>
class simple_vector_s : public simple_vector_base<T>
2014-08-30 18:02:17 -04:00
{
public:
simple_vector_s(simple_vector_base<T> & x, int_t start, int_t end, int_t stride) :
simple_vector_base<T>(start, end, stride, x.data()){ }
2014-08-30 18:02:17 -04:00
};
/*------ Simple Matrix ---------*/
template<class T>
class simple_matrix_base
{
public:
simple_matrix_base(int_t start1, int_t end1, int_t stride1,
int_t start2, int_t end2, int_t stride2,
int_t ld, std::vector<T> & data) : M_((end1 - start1)/stride1), start1_(start1), stride1_(stride1),
N_((end2-start2)/stride2), start2_(start2), stride2_(stride2),
ld_(ld), data_(data)
{}
2014-08-30 18:02:17 -04:00
int_t size1() const { return M_; }
int_t start1() const { return start1_; }
int_t stride1() const { return stride1_; }
2014-08-30 18:02:17 -04:00
int_t size2() const { return N_; }
int_t start2() const { return start2_; }
int_t stride2() const { return stride2_; }
2014-08-30 18:02:17 -04:00
std::vector<T> & data() { return data_; }
2014-08-30 18:02:17 -04:00
int_t ld() const { return ld_; }
2014-08-30 18:02:17 -04:00
T operator()(int_t i, int_t j) const
{
int_t ii = start1_ + i*stride1_;
int_t jj = start2_ + j*stride2_;
return data_[ii + jj*ld_];
}
2014-08-30 18:02:17 -04:00
T& operator()(int_t i, int_t j)
{
int_t ii = start1_ + i*stride1_;
int_t jj = start2_ + j*stride2_;
return data_[ii + jj*ld_];
}
private:
int_t M_;
int_t start1_;
int_t stride1_;
2014-08-30 18:02:17 -04:00
int_t N_;
int_t start2_;
int_t stride2_;
2014-08-30 18:02:17 -04:00
int_t ld_;
2014-08-30 18:02:17 -04:00
std::vector<T> & data_;
2014-08-30 18:02:17 -04:00
};
2014-08-30 18:02:17 -04:00
template<class T>
class simple_matrix : public simple_matrix_base<T>
2014-08-30 18:02:17 -04:00
{
public:
simple_matrix(int_t M, int_t N) : simple_matrix_base<T>(0, M, 1, 0, N, 1, M, data_), data_(M*N){}
simple_matrix(int_t M, int_t N, std::vector<T> data) : simple_matrix_base<T>(0, M, 1, 0, N, 1, M, data_), data_(data){}
2014-08-30 18:02:17 -04:00
private:
std::vector<T> data_;
2014-08-30 18:02:17 -04:00
};
template<class T>
class simple_matrix_s : public simple_matrix_base<T>
2014-08-30 18:02:17 -04:00
{
public:
simple_matrix_s(simple_matrix_base<T> & A,
int_t start1, int_t end1, int_t stride1,
int_t start2, int_t end2, int_t stride2) :
simple_matrix_base<T>(start1, end1, stride1, start2, end2, stride2, A.ld(), A.data()){ }
2014-08-30 18:02:17 -04:00
};
template<class T>
std::ostream& operator<<(std::ostream& os, simple_matrix_base<T> const & x)
{
for(size_t i = 0 ; i < (size_t)x.size1() ; i++){
for(size_t j = 0; j < (size_t)x.size2() ; j++)
os << ((j>0)?",":"") << x(i,j);
os << std::endl;
}
return os;
}
/*------ Initializer ---------*/
template<class T>
std::vector<T> random(size_t N)
{
std::vector<T> res(N);
for (size_t i = 0; i < res.size(); ++i)
res[i] = (T)rand()/RAND_MAX;
return res;
}
2014-08-30 18:02:17 -04:00
template<typename T>
void init_rand(simple_vector_base<T> & x)
2014-08-30 18:02:17 -04:00
{
for (int_t i = 0; i < x.size(); ++i)
2015-07-09 15:03:55 -04:00
x[i] = (T)rand()/RAND_MAX;
2014-08-30 18:02:17 -04:00
}
template<typename T>
void init_rand(simple_matrix_base<T> & A)
2014-08-30 18:02:17 -04:00
{
for (int_t i = 0; i < A.size1(); ++i)
for(int_t j = 0 ; j < A.size2() ; ++j)
A(i,j) = (T)rand()/RAND_MAX;
2014-08-30 18:02:17 -04:00
}
template<typename T>
simple_matrix<T> simple_trans(simple_matrix_base<T> const & A)
2014-08-30 18:02:17 -04:00
{
simple_matrix<T> res(A.size2(), A.size1());
for(int_t i = 0 ; i < A.size1(); ++i)
for(int_t j = 0; j < A.size2(); ++j)
res(j, i) = A(i, j);
return res;
2014-08-30 18:02:17 -04:00
}
/*------ Compare -----------*/
template<typename T>
bool diff(T a, T b, T epsilon, typename std::enable_if<std::is_arithmetic<T>::value>::type* = 0)
{
T delta = std::abs(a - b);
if(std::max(a, b)!=0)
delta/=std::abs(std::max(a, b));
return delta > epsilon;
}
template<class VecType1, class VecType2>
2015-01-29 15:19:40 -05:00
bool diff(VecType1 const & x, VecType2 const & y, typename VecType1::value_type epsilon)
2014-08-30 18:02:17 -04:00
{
assert((size_t)x.size()==(size_t)y.size());
typedef typename VecType1::value_type T;
T max = 0;
for(int_t i = 0 ; i < (int_t)x.size() ; ++i)
2014-08-30 18:02:17 -04:00
{
if(diff(x[i], y[i], epsilon)){
2014-08-30 18:02:17 -04:00
return true;
2015-01-17 15:47:52 -05:00
}
2014-08-30 18:02:17 -04:00
}
return false;
}
template<class VecType>
bool diff(VecType const & x, isaac::array const & iy, typename VecType::value_type epsilon)
{
VecType y(x.size());
isaac::copy(iy, y);
return diff(x, y, epsilon);
}
template<class VecType>
bool diff(isaac::array const & x, VecType const & y, typename VecType::value_type epsilon)
{ return diff(y, x, epsilon); }
2015-01-19 14:40:13 -05:00
#define INIT_VECTOR(N, SUBN, START, STRIDE, CPREFIX, PREFIX, CTX) \
simple_vector<T> CPREFIX(N);\
simple_vector_s<T> CPREFIX ## _s(CPREFIX, START, START + STRIDE*SUBN, STRIDE);\
init_rand(CPREFIX);\
isaac::array PREFIX(CPREFIX.data(), CTX);\
isaac::view PREFIX ## _s = PREFIX[{START, START + STRIDE*SUBN, STRIDE}];
2015-01-19 14:40:13 -05:00
#define INIT_MATRIX(M, SUBM, START1, STRIDE1, N, SUBN, START2, STRIDE2, CPREFIX, PREFIX, CTX) \
simple_matrix<T> CPREFIX(M, N);\
simple_matrix_s<T> CPREFIX ## _s(CPREFIX, START1, START1 + STRIDE1*SUBM, STRIDE1,\
START2, START2 + STRIDE2*SUBN, STRIDE2);\
init_rand(CPREFIX);\
isaac::array PREFIX(M, N, CPREFIX.data(), CTX);\
isaac::view PREFIX ## _s(PREFIX({START1, START1 + STRIDE1*SUBM, STRIDE1},\
2015-10-03 19:30:50 -04:00
{START2, START2 + STRIDE2*SUBN, STRIDE2}));\
simple_matrix<T> CPREFIX ## T = simple_trans(CPREFIX);\
isaac::array PREFIX ## T(N, M, CPREFIX ## T.data(), CTX);\
isaac::view PREFIX ## T_s(PREFIX ## T( {START2, START2 + STRIDE2*SUBN, STRIDE2},\
2015-10-03 19:30:50 -04:00
{START1, START1 + STRIDE1*SUBM, STRIDE1}));\
2014-09-01 09:24:21 -04:00
template<typename test_fun_t>
2016-09-30 02:34:25 -04:00
int run_test(test_fun_t const & testf, test_fun_t const & /*testd*/)
{
int nfail = 0;
int npass = 0;
std::list<isaac::driver::Context const *> data;
sc::driver::backend::contexts::get(data);
for(isaac::driver::Context const * context : data)
{
sc::driver::Device device = sc::driver::backend::queues::get(*context,0).device();
if(device.type() != sc::driver::Device::Type::GPU)
continue;
std::cout << "Device: " << device.name() << " on " << device.platform().name() << " " << device.platform().version() << std::endl;
std::cout << "---" << std::endl;
testf(*context, nfail, npass);
2016-09-30 02:34:25 -04:00
// if(device.fp64_support())
// testd(*context, nfail, npass);
std::cout << "---" << std::endl;
}
if(nfail>0)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}
#define ADD_TEST_1D_EW(NAME, CPU_LOOP, GPU_EXPR) \
{\
simple_vector<T> buffer(N);\
std::cout << NAME << "..." << std::flush;\
for(int_t i = 0 ; i < N ; ++i)\
CPU_LOOP;\
GPU_EXPR;\
isaac::copy(y, buffer.data());\
if(diff(cy, buffer, numeric_trait<T>::epsilon)){\
nfail++;\
std::cout << " [FAIL] " << std::endl;\
}\
else{\
npass++;\
std::cout << std::endl;\
}\
}
#define ADD_TEST_1D_RD(NAME, CPU_REDUCTION, INIT, ASSIGNMENT, GPU_REDUCTION) \
{\
T tmp = 0;\
std::cout << NAME << "..." << std::flush;\
cs = INIT;\
for(int_t i = 0 ; i < N ; ++i)\
CPU_REDUCTION;\
cs= ASSIGNMENT ;\
GPU_REDUCTION;\
tmp = ds;\
if(std::isnan((T)tmp) || (std::abs(cs - tmp)/std::max(cs, tmp)) > numeric_trait<T>::epsilon){\
nfail++;\
std::cout << " [FAIL] " << std::endl;\
}\
else{\
npass++;\
std::cout << std::endl;\
}\
}
#define ADD_TEST_2D_EW(NAME, CPU_LOOP, GPU_EXPR) \
{\
std::cout << NAME << "..." << std::flush;\
for(int_t i = 0 ; i < M ; ++i)\
for(int_t j = 0 ; j < N ; ++j)\
CPU_LOOP;\
GPU_EXPR;\
isaac::copy(C, buffer.data());\
std::vector<T> cCbuffer(M*N);\
for(int i = 0 ; i < M ; ++i)\
for(int j = 0 ; j < N ; ++j)\
cCbuffer[i + j*M] = cC(i,j);\
if(diff(cCbuffer, buffer, numeric_trait<T>::epsilon)) {\
nfail++;\
std::cout << " [Failure!]" << std::endl;\
}\
else{\
npass++;\
std::cout << std::endl;\
}\
}
#define ADD_TEST_2D_RD(NAME, SIZE1, SIZE2, NEUTRAL, REDUCTION, ASSIGNMENT, GPU_REDUCTION, RES, BUF, CRES)\
{\
std::cout << NAME << "..." << std::flush;\
for(int i = 0 ; i < SIZE1 ; ++i)\
{\
yi = NEUTRAL;\
xi = NEUTRAL;\
for(int j = 0 ; j < SIZE2 ; ++j)\
REDUCTION;\
ASSIGNMENT;\
}\
GPU_REDUCTION;\
sc::copy(RES, BUF.data());\
if(diff(CRES, BUF, numeric_trait<T>::epsilon)){\
nfail++;\
std::cout << " [FAIL] " << std::endl;\
}\
else{\
npass++;\
std::cout << std::endl;\
}\
}
#define ADD_TEST_MATMUL(NAME, GPU_OP)\
{\
std::cout << NAME << "..." << std::flush;\
GPU_OP;\
sc::copy(C, buffer);\
if(diff(buffer, cCbuffer, numeric_trait<T>::epsilon))\
{\
nfail++;\
std::cout << " [Failure!]" << std::endl;\
}\
else{\
npass++;\
std::cout << std::endl;\
}\
}
2014-09-01 09:24:21 -04:00
2014-08-30 18:02:17 -04:00
#endif