1 2 // ================================================================================================= 3 // This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This 4 // project loosely follows the Google C++ styleguide and uses a tab-size of two spaces and a max- 5 // width of 100 characters per line. 6 // 7 // Author(s): 8 // Cedric Nugteren <www.cedricnugteren.nl> 9 // 10 // This file implements a class with static methods to describe the Xgbmv routine. Examples of 11 // such 'descriptions' are how to calculate the size a of buffer or how to run the routine. These 12 // static methods are used by the correctness tester and the performance tester. 13 // 14 // ================================================================================================= 15 16 #ifndef CLBLAST_TEST_ROUTINES_XGBMV_H_ 17 #define CLBLAST_TEST_ROUTINES_XGBMV_H_ 18 19 #include "test/routines/common.hpp" 20 21 namespace clblast { 22 // ================================================================================================= 23 24 // See comment at top of file for a description of the class 25 template <typename T> 26 class TestXgbmv { 27 public: 28 29 // The BLAS level: 1, 2, or 3 BLASLevel()30 static size_t BLASLevel() { return 2; } 31 32 // The list of arguments relevant for this routine GetOptions()33 static std::vector<std::string> GetOptions() { 34 return {kArgM, kArgN, kArgKL, kArgKU, 35 kArgLayout, kArgATransp, 36 kArgALeadDim, kArgXInc, kArgYInc, 37 kArgAOffset, kArgXOffset, kArgYOffset, 38 kArgAlpha, kArgBeta}; 39 } BuffersIn()40 static std::vector<std::string> BuffersIn() { return {kBufMatA, kBufVecX, kBufVecY}; } BuffersOut()41 static std::vector<std::string> BuffersOut() { return {kBufVecY}; } 42 43 // Describes how to obtain the sizes of the buffers GetSizeX(const Arguments<T> & args)44 static size_t GetSizeX(const Arguments<T> &args) { 45 auto a_transposed = (args.a_transpose != Transpose::kNo); 46 auto n_real = (a_transposed) ? args.m : args.n; 47 return n_real * args.x_inc + args.x_offset; 48 } GetSizeY(const Arguments<T> & args)49 static size_t GetSizeY(const Arguments<T> &args) { 50 auto a_transposed = (args.a_transpose != Transpose::kNo); 51 auto m_real = (a_transposed) ? args.n : args.m; 52 return m_real * args.y_inc + args.y_offset; 53 } GetSizeA(const Arguments<T> & args)54 static size_t GetSizeA(const Arguments<T> &args) { 55 auto a_rotated = (args.layout == Layout::kRowMajor); 56 auto a_two = (a_rotated) ? args.m : args.n; 57 return a_two * args.a_ld + args.a_offset; 58 } 59 60 // Describes how to set the sizes of all the buffers SetSizes(Arguments<T> & args)61 static void SetSizes(Arguments<T> &args) { 62 args.a_size = GetSizeA(args); 63 args.x_size = GetSizeX(args); 64 args.y_size = GetSizeY(args); 65 } 66 67 // Describes what the default values of the leading dimensions of the matrices are DefaultLDA(const Arguments<T> & args)68 static size_t DefaultLDA(const Arguments<T> &args) { return args.n; } DefaultLDB(const Arguments<T> &)69 static size_t DefaultLDB(const Arguments<T> &) { return 1; } // N/A for this routine DefaultLDC(const Arguments<T> &)70 static size_t DefaultLDC(const Arguments<T> &) { return 1; } // N/A for this routine 71 72 // Describes which transpose options are relevant for this routine 73 using Transposes = std::vector<Transpose>; GetATransposes(const Transposes & all)74 static Transposes GetATransposes(const Transposes &all) { return all; } GetBTransposes(const Transposes &)75 static Transposes GetBTransposes(const Transposes &) { return {}; } // N/A for this routine 76 77 // Describes how to prepare the input data PrepareData(const Arguments<T> &,Queue &,const int,std::vector<T> &,std::vector<T> &,std::vector<T> &,std::vector<T> &,std::vector<T> &,std::vector<T> &,std::vector<T> &)78 static void PrepareData(const Arguments<T>&, Queue&, const int, std::vector<T>&, 79 std::vector<T>&, std::vector<T>&, std::vector<T>&, std::vector<T>&, 80 std::vector<T>&, std::vector<T>&) {} // N/A for this routine 81 82 // Describes how to run the CLBlast routine RunRoutine(const Arguments<T> & args,Buffers<T> & buffers,Queue & queue)83 static StatusCode RunRoutine(const Arguments<T> &args, Buffers<T> &buffers, Queue &queue) { 84 auto queue_plain = queue(); 85 auto event = cl_event{}; 86 auto status = Gbmv(args.layout, args.a_transpose, 87 args.m, args.n, args.kl, args.ku, args.alpha, 88 buffers.a_mat(), args.a_offset, args.a_ld, 89 buffers.x_vec(), args.x_offset, args.x_inc, args.beta, 90 buffers.y_vec(), args.y_offset, args.y_inc, 91 &queue_plain, &event); 92 if (status == StatusCode::kSuccess) { clWaitForEvents(1, &event); clReleaseEvent(event); } 93 return status; 94 } 95 96 // Describes how to run the clBLAS routine (for correctness/performance comparison) 97 #ifdef CLBLAST_REF_CLBLAS RunReference1(const Arguments<T> & args,Buffers<T> & buffers,Queue & queue)98 static StatusCode RunReference1(const Arguments<T> &args, Buffers<T> &buffers, Queue &queue) { 99 auto queue_plain = queue(); 100 auto event = cl_event{}; 101 auto status = clblasXgbmv(convertToCLBLAS(args.layout), 102 convertToCLBLAS(args.a_transpose), 103 args.m, args.n, args.kl, args.ku, args.alpha, 104 buffers.a_mat, args.a_offset, args.a_ld, 105 buffers.x_vec, args.x_offset, args.x_inc, args.beta, 106 buffers.y_vec, args.y_offset, args.y_inc, 107 1, &queue_plain, 0, nullptr, &event); 108 clWaitForEvents(1, &event); 109 return static_cast<StatusCode>(status); 110 } 111 #endif 112 113 // Describes how to run the CPU BLAS routine (for correctness/performance comparison) 114 #ifdef CLBLAST_REF_CBLAS RunReference2(const Arguments<T> & args,BuffersHost<T> & buffers_host,Queue &)115 static StatusCode RunReference2(const Arguments<T> &args, BuffersHost<T> &buffers_host, Queue &) { 116 cblasXgbmv(convertToCBLAS(args.layout), 117 convertToCBLAS(args.a_transpose), 118 args.m, args.n, args.kl, args.ku, args.alpha, 119 buffers_host.a_mat, args.a_offset, args.a_ld, 120 buffers_host.x_vec, args.x_offset, args.x_inc, args.beta, 121 buffers_host.y_vec, args.y_offset, args.y_inc); 122 return StatusCode::kSuccess; 123 } 124 #endif 125 126 // Describes how to run the cuBLAS routine (for correctness/performance comparison) 127 #ifdef CLBLAST_REF_CUBLAS RunReference3(const Arguments<T> & args,BuffersCUDA<T> & buffers,Queue &)128 static StatusCode RunReference3(const Arguments<T> &args, BuffersCUDA<T> &buffers, Queue &) { 129 auto status = cublasXgbmv(reinterpret_cast<cublasHandle_t>(args.cublas_handle), args.layout, 130 convertToCUBLAS(args.a_transpose), 131 args.m, args.n, args.kl, args.ku, args.alpha, 132 buffers.a_mat, args.a_offset, args.a_ld, 133 buffers.x_vec, args.x_offset, args.x_inc, args.beta, 134 buffers.y_vec, args.y_offset, args.y_inc); 135 if (status == CUBLAS_STATUS_SUCCESS) { return StatusCode::kSuccess; } else { return StatusCode::kUnknownError; } 136 } 137 #endif 138 139 // Describes how to download the results of the computation (more importantly: which buffer) DownloadResult(const Arguments<T> & args,Buffers<T> & buffers,Queue & queue)140 static std::vector<T> DownloadResult(const Arguments<T> &args, Buffers<T> &buffers, Queue &queue) { 141 std::vector<T> result(args.y_size, static_cast<T>(0)); 142 buffers.y_vec.Read(queue, args.y_size, result); 143 return result; 144 } 145 146 // Describes how to compute the indices of the result buffer ResultID1(const Arguments<T> & args)147 static size_t ResultID1(const Arguments<T> &args) { 148 auto a_transposed = (args.a_transpose != Transpose::kNo); 149 return (a_transposed) ? args.n : args.m; 150 } ResultID2(const Arguments<T> &)151 static size_t ResultID2(const Arguments<T> &) { return 1; } // N/A for this routine GetResultIndex(const Arguments<T> & args,const size_t id1,const size_t)152 static size_t GetResultIndex(const Arguments<T> &args, const size_t id1, const size_t) { 153 return id1*args.y_inc + args.y_offset; 154 } 155 156 // Describes how to compute performance metrics GetFlops(const Arguments<T> & args)157 static size_t GetFlops(const Arguments<T> &args) { 158 return 2 * args.m * args.n; 159 } GetBytes(const Arguments<T> & args)160 static size_t GetBytes(const Arguments<T> &args) { 161 auto a_rotated = (args.layout == Layout::kRowMajor); 162 auto a_one = (a_rotated) ? args.n : args.m; 163 auto a_two = (a_rotated) ? args.m : args.n; 164 return ((args.kl+args.ku+1)*a_two + 2*a_one + a_two) * sizeof(T); 165 } 166 }; 167 168 // ================================================================================================= 169 } // namespace clblast 170 171 // CLBLAST_TEST_ROUTINES_XGBMV_H_ 172 #endif 173