From 0e48c78bce275b6dba9ddf9b9c0113fc312fffe0 Mon Sep 17 00:00:00 2001 From: Philippe Tillet Date: Fri, 16 Jan 2015 15:24:24 -0500 Subject: [PATCH] Bugfix in elementwise operations for matrices --- include/atidlas/array.h | 1 + lib/array.cpp | 16 +++- tests/CMakeLists.txt | 2 +- tests/maxpy.cpp | 184 ++++++++++++++++++---------------------- 4 files changed, 95 insertions(+), 108 deletions(-) diff --git a/include/atidlas/array.h b/include/atidlas/array.h index cac0f2daf..d8f3a39af 100644 --- a/include/atidlas/array.h +++ b/include/atidlas/array.h @@ -67,6 +67,7 @@ public: array& operator/=(array_expression const &); //Indexing operators + const scalar operator[](int_t) const; scalar operator[](int_t); array operator[](slice const &); array operator()(slice const &, slice const &); diff --git a/lib/array.cpp b/lib/array.cpp index 0799c5f54..b56adf80d 100644 --- a/lib/array.cpp +++ b/lib/array.cpp @@ -333,6 +333,14 @@ std::ostream & operator<<(std::ostream & os, scalar const & s) /*--- Binary Operators ----*/ //----------------------------------- +template +size4 elementwise_size(U const & u, V const & v) +{ + if(max(u.shape())==1) + return v.shape(); + return u.shape(); +} + template bool check_elementwise(U const & u, V const & v) { @@ -342,19 +350,19 @@ bool check_elementwise(U const & u, V const & v) #define DEFINE_ELEMENT_BINARY_OPERATOR(OP, OPNAME) \ array_expression OPNAME (array_expression const & x, array_expression const & y) \ { assert(check_elementwise(x, y));\ - return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), std::max(max(x.shape()), max(y.shape())) ); } \ + return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), elementwise_size(x, y) ); } \ \ array_expression OPNAME (array const & x, array_expression const & y) \ { assert(check_elementwise(x, y));\ - return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), std::max(max(x.shape()), max(y.shape()))); } \ + return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), elementwise_size(x, y)); } \ \ array_expression OPNAME (array_expression const & x, array const & y) \ { assert(check_elementwise(x, y));\ - return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), std::max(max(x.shape()), max(y.shape()))); } \ + return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), elementwise_size(x, y)); } \ \ array_expression OPNAME (array const & x, array const & y) \ { assert(check_elementwise(x, y));\ - return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), x.context(), x.dtype(), std::max(max(x.shape()), max(y.shape()))); }\ + return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), x.context(), x.dtype(), elementwise_size(x, y)); }\ \ array_expression OPNAME (array_expression const & x, value_scalar const & y) \ { return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OP), x.shape()); } \ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 80b9ac265..93779e5e0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,5 @@ get_property(ATIDLAS_PATH TARGET atidlas PROPERTY LOCATION) -foreach(PROG vaxpy reduction mreduction mproduct) +foreach(PROG maxpy vaxpy reduction mreduction mproduct) add_executable(${PROG}-test ${PROG}.cpp) add_test(${PROG} ${PROG}-test) target_link_libraries(${PROG}-test atidlas ${OPENCL_LIBRARIES}) diff --git a/tests/maxpy.cpp b/tests/maxpy.cpp index 21376530b..f82de526c 100644 --- a/tests/maxpy.cpp +++ b/tests/maxpy.cpp @@ -1,87 +1,86 @@ -#include "common.hpp" #include -#include "viennacl/matrix.hpp" +#include +#include "common.hpp" +#include "atidlas/array.h" -#include "atidlas/templates/matrix_axpy.hpp" -#include "atidlas/execute.hpp" +namespace ad = atidlas; +typedef atidlas::int_t int_t; -template -void test_element_wise_matrix(NumericT epsilon, AType & cA, BType & cB, CType & cC) +template +void test(T epsilon, simple_matrix_base & cA, simple_matrix_base& cB, simple_matrix_base& cC, + ad::array& A, ad::array& B, ad::array& C) { - using namespace viennacl::linalg; using namespace std; - atidlas::matrix_axpy_parameters parameters(1, 8, 8, 32, 32, atidlas::FETCH_FROM_GLOBAL_STRIDED); int failure_count = 0; - CType tmp = cC; - NumericT a = 3.12, b = 3.5; - viennacl::scalar da(a), db(b); + int_t M = cC.size1(); + int_t N = cC.size2(); - viennacl::matrix Atmp(cA.internal_size1(), cA.internal_size2()); - typename matrix_maker::result_type A = matrix_maker::make(Atmp, cA); - viennacl::matrix Btmp(cB.internal_size1(), cB.internal_size2()); - typename matrix_maker::result_type B = matrix_maker::make(Btmp, cB); - viennacl::matrix Ctmp(cC.internal_size1(), cC.internal_size2()); - typename matrix_maker::result_type C = matrix_maker::make(Ctmp, cC); + T aa = 3.12, bb=3.5; + atidlas::value_scalar a(aa), b(bb); + atidlas::scalar da(a), db(b); - -#define RUN_TEST(NAME, CPU_LOOP, GPU_STATEMENT) \ - cout << NAME "..." << flush;\ - for(int_t i = 0 ; i < cC.size1() ; ++i)\ - for(int_t j = 0 ; j < cC.size2() ; ++j)\ - CPU_LOOP;\ - atidlas::execute(atidlas::matrix_axpy_template(parameters),\ - GPU_STATEMENT,\ - viennacl::ocl::current_context(), true);\ - viennacl::copy(C, tmp);\ - if(failure_matrix(cC, tmp, epsilon))\ + simple_vector buffer(M*N); +#define RUN_TEST(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;\ + atidlas::copy(C, buffer.data());\ + std::vector 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(failure_vector(cCbuffer, buffer, epsilon))\ {\ failure_count++;\ - cout << " [Failure!]" << endl;\ + std::cout << " [Failure!]" << std::endl;\ }\ else\ - cout << endl; + std::cout << std::endl;\ + } - RUN_TEST("C = A", cC(i,j) = cA(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), A)) - RUN_TEST("C = A + B", cC(i,j) = cA(i,j) + cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), A + B)) - RUN_TEST("C = A - B", cC(i,j) = cA(i,j) - cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), A - B)) - RUN_TEST("C = A + B + C", cC(i,j) = cA(i,j) + cB(i,j) + cC(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), A + B + C)) + RUN_TEST("C = A", cC(i,j) = cA(i,j), C = A) + RUN_TEST("C = A + B", cC(i,j) = cA(i,j) + cB(i,j), C = A + B) + RUN_TEST("C = A - B", cC(i,j) = cA(i,j) - cB(i,j), C = A - B) + RUN_TEST("C = A + B + C", cC(i,j) = cA(i,j) + cB(i,j) + cC(i,j), C = A + B + C) - RUN_TEST("C = a*A", cC(i,j) = a*cA(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), a*A)) - RUN_TEST("C = da*A", cC(i,j) = a*cA(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), da*A)) - RUN_TEST("C = a*A + b*B", cC(i,j) = a*cA(i,j) + b*cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), a*A + b*B)) - RUN_TEST("C = da*A + b*B", cC(i,j) = a*cA(i,j) + b*cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), da*A + b*B)) - RUN_TEST("C = a*A + db*B", cC(i,j) = a*cA(i,j) + b*cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), a*A + db*B)) - RUN_TEST("C = da*A + db*B", cC(i,j) = a*cA(i,j) + b*cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), da*A + db*B)) + RUN_TEST("C = a*A", cC(i,j) = aa*cA(i,j), C = a*A) + RUN_TEST("C = da*A", cC(i,j) = aa*cA(i,j), C = da*A) + RUN_TEST("C = a*A + b*B", cC(i,j) = aa*cA(i,j) + bb*cB(i,j), C= a*A + b*B) + RUN_TEST("C = da*A + b*B", cC(i,j) = aa*cA(i,j) + bb*cB(i,j), C= da*A + b*B) + RUN_TEST("C = a*A + db*B", cC(i,j) = aa*cA(i,j) + bb*cB(i,j), C= a*A + db*B) + RUN_TEST("C = da*A + db*B", cC(i,j) = aa*cA(i,j) + bb*cB(i,j), C= da*A + db*B) -// RUN_TEST("C = abs(A)", cC(i,j) = abs(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_abs(A))) - RUN_TEST("C = acos(A)", cC(i,j) = acos(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_acos(A))) - RUN_TEST("C = asin(A)", cC(i,j) = asin(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_asin(A))) - RUN_TEST("C = atan(A)", cC(i,j) = atan(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_atan(A))) - RUN_TEST("C = ceil(A)", cC(i,j) = ceil(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_ceil(A))) - RUN_TEST("C = cos(A)", cC(i,j) = cos(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_cos(A))) - RUN_TEST("C = cosh(A)", cC(i,j) = cosh(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_cosh(A))) - RUN_TEST("C = exp(A)", cC(i,j) = exp(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_exp(A))) - RUN_TEST("C = fabs(A)", cC(i,j) = fabs(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_fabs(A))) - RUN_TEST("C = floor(A)", cC(i,j) = floor(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_floor(A))) - RUN_TEST("C = log(A)", cC(i,j) = log(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_log(A))) - RUN_TEST("C = log10(A)", cC(i,j) = log10(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_log10(A))) - RUN_TEST("C = sin(A)", cC(i,j) = sin(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_sin(A))) - RUN_TEST("C = sinh(A)", cC(i,j) = sinh(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_sinh(A))) - RUN_TEST("C = sqrt(A)", cC(i,j) = sqrt(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_sqrt(A))) - RUN_TEST("C = tan(A)", cC(i,j) = tan(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_tan(A))) - RUN_TEST("C = tanh(A)", cC(i,j) = tanh(cA(i,j)), viennacl::symbolic_expression(C, viennacl::op_assign(), element_tanh(A))) + RUN_TEST("C = exp(A)", cC(i,j) = exp(cA(i,j)), C= exp(A)) + RUN_TEST("C = abs(A)", cC(i,j) = abs(cA(i,j)), C= abs(A)) + RUN_TEST("C = acos(A)", cC(i,j) = acos(cA(i,j)), C= acos(A)) + RUN_TEST("C = asin(A)", cC(i,j) = asin(cA(i,j)), C= asin(A)) + RUN_TEST("C = atan(A)", cC(i,j) = atan(cA(i,j)), C= atan(A)) + RUN_TEST("C = ceil(A)", cC(i,j) = ceil(cA(i,j)), C= ceil(A)) + RUN_TEST("C = cos(A)", cC(i,j) = cos(cA(i,j)), C= cos(A)) + RUN_TEST("C = cosh(A)", cC(i,j) = cosh(cA(i,j)), C= cosh(A)) + RUN_TEST("C = floor(A)", cC(i,j) = floor(cA(i,j)), C= floor(A)) + RUN_TEST("C = log(A)", cC(i,j) = log(cA(i,j)), C= log(A)) + RUN_TEST("C = log10(A)", cC(i,j) = log10(cA(i,j)), C= log10(A)) + RUN_TEST("C = sin(A)", cC(i,j) = sin(cA(i,j)), C= sin(A)) + RUN_TEST("C = sinh(A)", cC(i,j) = sinh(cA(i,j)), C= sinh(A)) + RUN_TEST("C = sqrt(A)", cC(i,j) = sqrt(cA(i,j)), C= sqrt(A)) + RUN_TEST("C = tan(A)", cC(i,j) = tan(cA(i,j)), C= tan(A)) + RUN_TEST("C = tanh(A)", cC(i,j) = tanh(cA(i,j)), C= tanh(A)) - RUN_TEST("C = A./B", cC(i,j) = cA(i,j)/cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), element_div(A,B))) - RUN_TEST("C = A==B", cC(i,j) = cA(i,j)==cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), element_eq(A,B))) - RUN_TEST("C = A>=B", cC(i,j) = cA(i,j)>=cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), element_geq(A,B))) - RUN_TEST("C = A>B", cC(i,j) = cA(i,j)>cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), element_greater(A,B))) - RUN_TEST("C = A<=B", cC(i,j) = cA(i,j)<=cB(i,j), viennacl::symbolic_expression(C, viennacl::op_assign(), element_leq(A,B))) - RUN_TEST("C = A=y", cC(i,j) = cA(i,j)>=cB(i,j), C= A>=B) + RUN_TEST("z = x>y", cC(i,j) = cA(i,j)>cB(i,j), C= A>B) + RUN_TEST("z = x<=y", cC(i,j) = cA(i,j)<=cB(i,j), C= A<=B) + RUN_TEST("z = x -void test_impl(NumericT epsilon) +template +void test_impl(T epsilon) { - int_t M = 241; - int_t N = 278; - INIT_MATRIX_AND_PROXIES(M, 4, 5, N, 7, 6, C); - INIT_MATRIX_AND_PROXIES(M, 2, 4, N, 5, 8, A); - INIT_MATRIX_AND_PROXIES(M, 2, 3, N, 3, 4, B); + using atidlas::_; -#define TEST_OPERATIONS(CTYPE, ATYPE, BTYPE)\ - std::cout << "> C : " #CTYPE " | A : " #ATYPE " | B : " #BTYPE << std::endl;\ - test_element_wise_matrix(epsilon, A_ ## ATYPE, B_ ## BTYPE, C_ ## CTYPE);\ + int_t M = 1324; + int_t N = 1143; + int_t SUBM = 184; + int_t SUBN = 145; - TEST_OPERATIONS(matrix, matrix, matrix) - TEST_OPERATIONS(matrix, matrix, range) - TEST_OPERATIONS(matrix, matrix, slice) - TEST_OPERATIONS(matrix, range, matrix) - TEST_OPERATIONS(matrix, range, range) - TEST_OPERATIONS(matrix, range, slice) - TEST_OPERATIONS(matrix, slice, matrix) - TEST_OPERATIONS(matrix, slice, range) - TEST_OPERATIONS(matrix, slice, slice) + INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cA, A); + INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cB, B); + INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cC, C); - TEST_OPERATIONS(range, matrix, matrix) - TEST_OPERATIONS(range, matrix, range) - TEST_OPERATIONS(range, matrix, slice) - TEST_OPERATIONS(range, range, matrix) - TEST_OPERATIONS(range, range, range) - TEST_OPERATIONS(range, range, slice) - TEST_OPERATIONS(range, slice, matrix) - TEST_OPERATIONS(range, slice, range) - TEST_OPERATIONS(range, slice, slice) +#define TEST_OPERATIONS(XTYPE, YTYPE, ZTYPE)\ + test(epsilon, cA_ ## XTYPE, cB_ ## YTYPE, cC_ ## ZTYPE, A_ ## XTYPE, B_ ## YTYPE, C_ ## ZTYPE);\ - TEST_OPERATIONS(slice, matrix, matrix) - TEST_OPERATIONS(slice, matrix, range) - TEST_OPERATIONS(slice, matrix, slice) - TEST_OPERATIONS(slice, range, matrix) - TEST_OPERATIONS(slice, range, range) - TEST_OPERATIONS(slice, range, slice) - TEST_OPERATIONS(slice, slice, matrix) - TEST_OPERATIONS(slice, slice, range) - TEST_OPERATIONS(slice, slice, slice) + std::cout << "> standard..." << std::endl; + TEST_OPERATIONS(matrix, matrix, matrix); + std::cout << "> slice..." << std::endl; + TEST_OPERATIONS(slice, slice, slice); } int main()