2015-01-12 13:20:53 -05:00
|
|
|
#include <cmath>
|
|
|
|
#include "common.hpp"
|
2015-04-29 15:50:57 -04:00
|
|
|
#include "isaac/array.h"
|
2015-06-27 11:44:50 -04:00
|
|
|
#include "isaac/wrap/clBLAS.h"
|
|
|
|
|
2015-08-12 19:38:53 -07:00
|
|
|
namespace sc = isaac;
|
2015-01-12 13:20:53 -05:00
|
|
|
|
|
|
|
template<typename T>
|
2015-09-30 15:31:41 -04:00
|
|
|
void test(T epsilon, simple_matrix_base<T> & cC, simple_matrix_base<T> const & cA, simple_matrix_base<T> const & cB,
|
2015-08-12 19:38:53 -07:00
|
|
|
sc::array & C, sc::array const & A, sc::array const & AT, sc::array const & B, sc::array const & BT,
|
2015-07-21 13:27:48 -04:00
|
|
|
interface_t interf, const char * prefix)
|
2015-01-12 13:20:53 -05:00
|
|
|
{
|
|
|
|
int failure_count = 0;
|
|
|
|
|
2015-08-12 19:38:53 -07:00
|
|
|
sc::int_t M = C.shape()[0];
|
|
|
|
sc::int_t N = C.shape()[1];
|
|
|
|
sc::int_t K = A.shape()[1];
|
2015-01-12 13:20:53 -05:00
|
|
|
|
2015-06-27 11:44:50 -04:00
|
|
|
T alpha = 1;
|
|
|
|
T beta = 0;
|
|
|
|
|
2015-08-12 19:38:53 -07:00
|
|
|
sc::driver::CommandQueue queue = sc::driver::backend::queues::get(C.context(),0);
|
2015-06-27 11:44:50 -04:00
|
|
|
|
2015-01-12 13:20:53 -05:00
|
|
|
for(int i = 0 ; i < M ; ++i)
|
|
|
|
{
|
|
|
|
for(int j = 0 ; j < N ; ++j)
|
|
|
|
{
|
|
|
|
T cij = 0;
|
|
|
|
for(int k = 0 ; k < K ; ++k)
|
|
|
|
cij += cA(i,k)*cB(k,j);
|
2015-06-30 17:55:57 -04:00
|
|
|
cC(i,j) = alpha*cij + beta*cC(i, j);
|
2015-01-12 13:20:53 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
std::vector<T> buffer(M*N);
|
2015-06-27 11:44:50 -04:00
|
|
|
|
2015-01-12 13:20:53 -05:00
|
|
|
#define RUN_TEST(NAME, GPU_OP)\
|
2015-06-27 15:22:26 -04:00
|
|
|
std::cout << "[" << prefix << "] \t" << NAME << "..." << std::flush;\
|
2015-01-12 13:20:53 -05:00
|
|
|
GPU_OP;\
|
2015-06-30 17:55:57 -04:00
|
|
|
queue.synchronize();\
|
2015-08-12 19:38:53 -07:00
|
|
|
sc::copy(C, buffer);\
|
2015-01-29 15:19:40 -05:00
|
|
|
if(diff(buffer, cCbuffer, epsilon))\
|
2015-01-12 13:20:53 -05:00
|
|
|
{\
|
|
|
|
failure_count++;\
|
|
|
|
std::cout << " [Failure!]" << std::endl;\
|
|
|
|
}\
|
|
|
|
else\
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
2015-08-21 13:06:20 -04:00
|
|
|
if(C.context().backend()==sc::driver::OPENCL && interf==clBLAS)
|
2015-06-27 11:44:50 -04:00
|
|
|
{
|
2015-07-25 21:00:18 -07:00
|
|
|
cl_command_queue clqueue = queue.handle().cl();
|
2015-06-27 15:22:26 -04:00
|
|
|
|
2015-07-21 14:40:38 -04:00
|
|
|
//// //Row-major
|
2015-07-11 11:29:28 -04:00
|
|
|
RUN_TEST("GEMM(ROW, N, N)", BLAS<T>::F(clblasSgemm,clblasDgemm)(clblasRowMajor, clblasNoTrans, clblasNoTrans, N, M, K, alpha, CHANDLE(B), OFF(B), LD(B),
|
|
|
|
CHANDLE(A), OFF(A), LD(A), beta, CHANDLE(C), OFF(C), LD(C), 1, &clqueue, 0, NULL, NULL));
|
|
|
|
RUN_TEST("GEMM(ROW, N, T)", BLAS<T>::F(clblasSgemm,clblasDgemm)(clblasRowMajor, clblasTrans, clblasNoTrans, N, M, K, alpha, CHANDLE(BT), OFF(BT), LD(BT),
|
|
|
|
CHANDLE(A), OFF(A), LD(A), beta, CHANDLE(C), OFF(C), LD(C), 1, &clqueue, 0, NULL, NULL));
|
|
|
|
RUN_TEST("GEMM(ROW, T, N)", BLAS<T>::F(clblasSgemm,clblasDgemm)(clblasRowMajor, clblasNoTrans, clblasTrans, N, M, K, alpha, CHANDLE(B), OFF(B), LD(B),
|
|
|
|
CHANDLE(AT), OFF(AT), LD(AT), beta, CHANDLE(C), OFF(C), LD(C), 1, &clqueue, 0, NULL, NULL));
|
|
|
|
RUN_TEST("GEMM(ROW, T, T)", BLAS<T>::F(clblasSgemm,clblasDgemm)(clblasRowMajor, clblasTrans, clblasTrans, N, M, K, alpha, CHANDLE(BT), OFF(BT), LD(BT),
|
|
|
|
CHANDLE(AT), OFF(AT), LD(AT), beta, CHANDLE(C), OFF(C), LD(C), 1, &clqueue, 0, NULL, NULL));
|
2015-06-27 15:22:26 -04:00
|
|
|
|
|
|
|
//Column-major
|
2015-07-11 11:29:28 -04:00
|
|
|
RUN_TEST("GEMM(COL, N, N)", BLAS<T>::F(clblasSgemm,clblasDgemm)(clblasColumnMajor, clblasNoTrans, clblasNoTrans, M, N, K, alpha, CHANDLE(A), OFF(A), LD(A),
|
|
|
|
CHANDLE(B), OFF(B), LD(B), beta, CHANDLE(C), OFF(C), LD(C), 1, &clqueue, 0, NULL, NULL));
|
2015-06-30 17:55:57 -04:00
|
|
|
|
2015-06-27 15:22:26 -04:00
|
|
|
RUN_TEST("GEMM(COL, N, T)", BLAS<T>::F(clblasSgemm,clblasDgemm)(clblasColumnMajor, clblasNoTrans, clblasTrans, M, N, K, alpha, CHANDLE(A), OFF(A), LD(A),
|
2015-06-27 13:53:31 -04:00
|
|
|
CHANDLE(BT), OFF(BT), LD(BT), beta, CHANDLE(C), OFF(C), LD(C), 1, &clqueue, 0, NULL, NULL));
|
2015-06-30 17:55:57 -04:00
|
|
|
|
2015-07-11 11:29:28 -04:00
|
|
|
RUN_TEST("GEMM(COL, T, N)", BLAS<T>::F(clblasSgemm,clblasDgemm)(clblasColumnMajor, clblasTrans, clblasNoTrans, M, N, K, alpha, CHANDLE(AT), OFF(AT), LD(AT),
|
|
|
|
CHANDLE(B), OFF(B), LD(B), beta, CHANDLE(C), OFF(C), LD(C), 1, &clqueue, 0, NULL, NULL));
|
|
|
|
RUN_TEST("GEMM(COL, T, T)", BLAS<T>::F(clblasSgemm,clblasDgemm)(clblasColumnMajor, clblasTrans, clblasTrans, M, N, K, alpha, CHANDLE(AT), OFF(AT), LD(AT),
|
|
|
|
CHANDLE(BT), OFF(BT), LD(BT), beta, CHANDLE(C), OFF(C), LD(C), 1, &clqueue, 0, NULL, NULL));
|
2015-07-09 15:03:55 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
2015-06-27 11:44:50 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RUN_TEST("C = A * B", C = dot(A,B))
|
|
|
|
RUN_TEST("C = A' * B", C = dot(trans(AT),B))
|
|
|
|
RUN_TEST("C = A * B'", C = dot(A,trans(BT)))
|
|
|
|
RUN_TEST("C = A' * B'", C = dot(trans(AT),trans(BT)))
|
|
|
|
}
|
2015-01-12 13:20:53 -05:00
|
|
|
|
|
|
|
if(failure_count>0)
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
2015-09-30 15:31:41 -04:00
|
|
|
void test(T epsilon, sc::driver::Context const & ctx)
|
2015-01-12 13:20:53 -05:00
|
|
|
{
|
2015-07-11 11:29:28 -04:00
|
|
|
int_t M = 173;
|
2015-07-20 22:51:39 -07:00
|
|
|
int_t N = 241;
|
2015-07-11 11:29:28 -04:00
|
|
|
int_t K = 293;
|
2015-01-12 13:20:53 -05:00
|
|
|
|
2015-07-18 13:09:38 -04:00
|
|
|
int_t SUBM = 7;
|
2015-07-21 14:40:38 -04:00
|
|
|
int_t SUBN = 11;
|
|
|
|
int_t SUBK = 29;
|
2015-01-12 13:20:53 -05:00
|
|
|
|
2015-06-29 21:52:50 -07:00
|
|
|
{
|
2015-07-09 10:52:54 -04:00
|
|
|
INIT_MATRIX(M, SUBM, 5, 1, N, SUBN, 7, 1, cC, C, ctx);
|
|
|
|
INIT_MATRIX(M, SUBM, 8, 1, K, SUBK, 4, 1, cA, A, ctx);
|
|
|
|
INIT_MATRIX(K, SUBK, 9, 1, N, SUBN, 6, 1, cB, B, ctx);
|
2015-09-30 15:31:41 -04:00
|
|
|
test(epsilon, cC_full, cA_full, cB_full, C_full, A_full, AT_full, B_full, BT_full, clBLAS, "BLAS, FULL");
|
|
|
|
test(epsilon, cC_slice, cA_slice, cB_slice, C_slice, A_slice, AT_slice, B_slice, BT_slice, clBLAS, "BLAS, SUB");
|
2015-06-29 21:52:50 -07:00
|
|
|
}
|
2015-06-27 15:22:26 -04:00
|
|
|
|
2015-06-29 21:52:50 -07:00
|
|
|
{
|
2015-07-09 10:52:54 -04:00
|
|
|
INIT_MATRIX(M, SUBM, 5, 2, N, SUBN, 7, 3, cC, C, ctx);
|
|
|
|
INIT_MATRIX(M, SUBM, 8, 2, K, SUBK, 4, 3, cA, A, ctx);
|
|
|
|
INIT_MATRIX(K, SUBK, 9, 4, N, SUBN, 6, 2, cB, B, ctx);
|
2015-09-30 15:31:41 -04:00
|
|
|
test(epsilon, cC_full, cA_full, cB_full, C_full, A_full, AT_full, B_full, BT_full, CPP, "C++, FULL");
|
|
|
|
test(epsilon, cC_slice, cA_slice, cB_slice, C_slice, A_slice, AT_slice, B_slice, BT_slice, CPP, "C++, SUB");
|
2015-06-29 21:52:50 -07:00
|
|
|
}
|
2015-07-09 10:52:54 -04:00
|
|
|
|
2015-01-12 13:20:53 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
2015-07-21 14:40:38 -04:00
|
|
|
clblasSetup();
|
2015-08-03 16:05:57 -07:00
|
|
|
std::list<isaac::driver::Context const *> data;
|
2015-08-12 19:38:53 -07:00
|
|
|
sc::driver::backend::contexts::get(data);
|
2015-07-31 15:47:41 -07:00
|
|
|
for(isaac::driver::Context const * context : data)
|
2015-01-19 14:40:13 -05:00
|
|
|
{
|
2015-08-12 19:38:53 -07:00
|
|
|
sc::driver::Device device = sc::driver::backend::queues::get(*context,0).device();
|
2015-08-13 13:43:26 -07:00
|
|
|
if(device.type() != sc::driver::Device::Type::GPU)
|
2015-07-27 11:37:19 -07:00
|
|
|
continue;
|
2015-04-29 15:50:57 -04:00
|
|
|
std::cout << "Device: " << device.name() << " on " << device.platform().name() << " " << device.platform().version() << std::endl;
|
2015-01-19 14:40:13 -05:00
|
|
|
std::cout << "---" << std::endl;
|
|
|
|
std::cout << ">> float" << std::endl;
|
2015-09-30 15:31:41 -04:00
|
|
|
test<float>(eps_float, *context);
|
2015-07-26 21:35:39 -07:00
|
|
|
if(device.fp64_support())
|
|
|
|
{
|
|
|
|
std::cout << ">> double" << std::endl;
|
2015-09-30 15:31:41 -04:00
|
|
|
test<double>(eps_double, *context);
|
2015-07-26 21:35:39 -07:00
|
|
|
}
|
2015-01-19 14:40:13 -05:00
|
|
|
std::cout << "---" << std::endl;
|
|
|
|
}
|
2015-06-30 17:55:57 -04:00
|
|
|
clblasTeardown();
|
2015-01-12 13:20:53 -05:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|