diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b30889..b6a86a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,9 @@ add_executable(oputest src/tests/op_unit_test.cc ${MA_CC_FILES}) target_link_libraries(oputest ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) add_test(NAME oputest COMMAND oputest) +add_executable(opptest src/tests/op_perf_test.cc ${MA_CC_FILES}) +#target_link_libraries(oputest) + #install(TARGETS testm DESTINATION install) set(CMAKE_INSTALL_PREFIX ..) diff --git a/src/tests/op_perf_test.cc b/src/tests/op_perf_test.cc new file mode 100644 index 0000000..3e753ce --- /dev/null +++ b/src/tests/op_perf_test.cc @@ -0,0 +1,266 @@ +// -*- C++ -*- + +#include +#include +#include + +#include "multi_array_header.h" + +#include +#include + +namespace MAT = MultiArrayTools; + +namespace { + + double xround(double arg) + { + return roundf(arg * 100000.) / 100000.; + } + + using namespace MAT; + + template + void swapFactory(std::shared_ptr& fptr) + { + auto nptr = std::make_shared(); + fptr = nptr; + } + + template + void swapFactory(std::shared_ptr& fptr, std::initializer_list ilist) + { + std::vector tmp = ilist; + auto nptr = std::make_shared( tmp ); + fptr = nptr; + } + + template + void swapFactory(std::shared_ptr& fptr, std::vector& ilist) + { + std::vector tmp = ilist; + auto nptr = std::make_shared( tmp ); + fptr = nptr; + } + + + template + void swapMFactory(std::shared_ptr& fptr, const Rs&... rs) + { + auto nptr = std::make_shared( rs... ); + fptr = nptr; + } + + template + auto mkt(Ts&&... ts) -> decltype(std::make_tuple(ts...)) + { + return std::make_tuple(ts...); + } + + template + auto mkts(Ts&&... ts) -> decltype(std::make_tuple(ts...)) + { + return std::make_tuple(static_cast( ts )...); + } + + class OpTest_Performance + { + public: + + typedef SingleRangeFactory SRF; + typedef SRF::oType SRange; + + typedef MultiRangeFactory MRF; + typedef MRF::oType MRange; + + OpTest_Performance() + { + + std::vector initvec1(vs1); + cv1.resize(vs1); + for(size_t i = 0; i != vs1; ++i){ + initvec1[i] = i; + cv1[i] = sqrt( static_cast(i)*0.53 ); + } + + std::vector initvec2(vs2); + cv2.resize(vs2*vs1); + for(size_t i = 0; i != vs2; ++i){ + initvec2[i] = i; + for(size_t j = 0; j != vs1; ++j){ + cv2[i*vs1 + j] = static_cast(i) * sin(static_cast(j)*0.4); + } + } + + swapFactory(rfbptr, initvec1); + sr1ptr = std::dynamic_pointer_cast(rfbptr->create()); + + swapFactory(rfbptr, initvec2); + sr2ptr = std::dynamic_pointer_cast(rfbptr->create()); + + swapMFactory(rfbptr, sr2ptr, sr1ptr); + mrptr = std::dynamic_pointer_cast(rfbptr->create()); + } + + void PCheck(); + + + private: + //const size_t vs1 = 10000; + //const size_t vs2 = 1000; + const size_t vs1 = 4000; + const size_t vs2 = 2500; + + std::shared_ptr rfbptr; + std::shared_ptr sr1ptr; + std::shared_ptr sr2ptr; + std::shared_ptr mrptr; + + std::vector cv1; + std::vector cv2; + }; + + class OpTest_Spin + { + public: + + typedef SpinRF SRF; + typedef SpinRange SR; + typedef MultiRangeFactory SR8F; + typedef SR8F::oType SR8; + + static const size_t s = 65536; + + OpTest_Spin() + { + data.resize(s); + for(size_t i = 0; i != s; ++i){ + double arg = static_cast( i - s ) - 0.1; + data[i] = sin(arg)/arg; + } + SRF f; + sr = std::dynamic_pointer_cast(f.create()); + } + + void contract(); + + private: + + std::vector data; + std::shared_ptr sr; + }; + + void OpTest_Spin::contract() + { + MultiArray ma(sr, sr, sr, sr, sr, sr, sr, sr, data); + MultiArray res1( sr, sr ); + + auto alpha = MAT::getIndex(); + auto beta = MAT::getIndex(); + auto gamma = MAT::getIndex(); + auto delta = MAT::getIndex(); + auto deltap = MAT::getIndex(); + + auto mix = MAT::mkMIndex( alpha, beta, gamma ); + + std::clock_t begin = std::clock(); + res1(delta, deltap) = ma(delta, alpha, alpha, beta, beta, gamma, gamma, deltap).c(mix); + std::clock_t end = std::clock(); + std::cout << "MultiArray time: " << static_cast( end - begin ) / CLOCKS_PER_SEC + << std::endl; + + std::vector vres(4*4); + + std::clock_t begin2 = std::clock(); + for(size_t d = 0; d != 4; ++d){ + for(size_t p = 0; p != 4; ++p){ + const size_t tidx = d*4 + p; + vres[tidx] = 0.; + for(size_t a = 0; a != 4; ++a){ + for(size_t b = 0; b != 4; ++b){ + for(size_t c = 0; c != 4; ++c){ + const size_t sidx = d*4*4*4*4*4*4*4 + a*5*4*4*4*4 + b*5*4*4*4 + c*5*4 + p; + vres[tidx] += data[sidx]; + } + } + } + } + } + std::clock_t end2 = std::clock(); + + assert( xround(res1.at(mkts(0,0))) == xround(vres[0]) ); + assert( xround(res1.at(mkts(0,1))) == xround(vres[1]) ); + assert( xround(res1.at(mkts(0,2))) == xround(vres[2]) ); + assert( xround(res1.at(mkts(0,3))) == xround(vres[3]) ); + + assert( xround(res1.at(mkts(1,0))) == xround(vres[4]) ); + assert( xround(res1.at(mkts(1,1))) == xround(vres[5]) ); + assert( xround(res1.at(mkts(1,2))) == xround(vres[6]) ); + assert( xround(res1.at(mkts(1,3))) == xround(vres[7]) ); + + assert( xround(res1.at(mkts(2,0))) == xround(vres[8]) ); + assert( xround(res1.at(mkts(2,1))) == xround(vres[9]) ); + assert( xround(res1.at(mkts(2,2))) == xround(vres[10]) ); + assert( xround(res1.at(mkts(2,3))) == xround(vres[11]) ); + + assert( xround(res1.at(mkts(3,0))) == xround(vres[12]) ); + assert( xround(res1.at(mkts(3,1))) == xround(vres[13]) ); + assert( xround(res1.at(mkts(3,2))) == xround(vres[14]) ); + assert( xround(res1.at(mkts(3,3))) == xround(vres[15]) ); + + std::cout << "std::vector - for loop time: " << static_cast( end2 - begin2 ) / CLOCKS_PER_SEC + << std::endl; + std::cout << "ratio: " << static_cast( end - begin ) / static_cast( end2 - begin2 ) << std::endl; + } + + void OpTest_Performance::PCheck() + { + MultiArray ma2(mrptr, cv2); + MultiArray ma1(sr1ptr, cv1); + MultiArray res(mrptr); + + auto si1 = MAT::getIndex(sr1ptr); + auto si2 = MAT::getIndex(sr2ptr); + auto mi = MAT::getIndex(mrptr); + (*mi)(si2, si1); + + std::clock_t begin = std::clock(); + + res(mi) = ma2(mi) * ma1(si1); + + std::clock_t end = std::clock(); + std::cout << "MultiArray time: " << static_cast( end - begin ) / CLOCKS_PER_SEC + << std::endl; + + std::vector res2(vs1*vs2); + std::clock_t begin2 = std::clock(); + + for(size_t i = 0; i != vs2; ++i){ + for(size_t j = 0; j != vs1; ++j){ + res2[i*vs1 + j] = cv1[j] * cv2[i*vs1 + j]; + } + } + + std::clock_t end2 = std::clock(); + std::cout << "std::vector - for loop time: " << static_cast( end2 - begin2 ) / CLOCKS_PER_SEC + << std::endl; + + std::cout << "ratio: " << static_cast( end - begin ) / static_cast( end2 - begin2 ) << std::endl; + + assert( xround( res.at(mkt(7,9)) ) == xround(res2[7*vs1 + 9]) ); + //assert( xround( res.at(mkt(700,900)) ) == xround(res2[700*vs1 + 900]) ); + + } + +} // anonymous namspace + +int main(int argc, char** argv) +{ + OpTest_Performance pt; + OpTest_Spin st; + + st.contract(); + pt.PCheck(); + + return 0; +}