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 Xgerc 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_XGERC_H_ 17 #define CLBLAST_TEST_ROUTINES_XGERC_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 TestXgerc { 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, 35 kArgLayout, 36 kArgALeadDim, kArgXInc, kArgYInc, 37 kArgAOffset, kArgXOffset, kArgYOffset, 38 kArgAlpha}; 39 } BuffersIn()40 static std::vector<std::string> BuffersIn() { return {kBufMatA, kBufVecX, kBufVecY}; } BuffersOut()41 static std::vector<std::string> BuffersOut() { return {kBufMatA}; } 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 return args.m * args.x_inc + args.x_offset; 46 } GetSizeY(const Arguments<T> & args)47 static size_t GetSizeY(const Arguments<T> &args) { 48 return args.n * args.y_inc + args.y_offset; 49 } GetSizeA(const Arguments<T> & args)50 static size_t GetSizeA(const Arguments<T> &args) { 51 auto a_rotated = (args.layout == Layout::kRowMajor); 52 auto a_two = (a_rotated) ? args.m : args.n; 53 return a_two * args.a_ld + args.a_offset; 54 } 55 56 // Describes how to set the sizes of all the buffers SetSizes(Arguments<T> & args)57 static void SetSizes(Arguments<T> &args) { 58 args.a_size = GetSizeA(args); 59 args.x_size = GetSizeX(args); 60 args.y_size = GetSizeY(args); 61 } 62 63 // Describes what the default values of the leading dimensions of the matrices are DefaultLDA(const Arguments<T> & args)64 static size_t DefaultLDA(const Arguments<T> &args) { return args.n; } DefaultLDB(const Arguments<T> &)65 static size_t DefaultLDB(const Arguments<T> &) { return 1; } // N/A for this routine DefaultLDC(const Arguments<T> &)66 static size_t DefaultLDC(const Arguments<T> &) { return 1; } // N/A for this routine 67 68 // Describes which transpose options are relevant for this routine 69 using Transposes = std::vector<Transpose>; GetATransposes(const Transposes &)70 static Transposes GetATransposes(const Transposes &) { return {}; } // N/A for this routine GetBTransposes(const Transposes &)71 static Transposes GetBTransposes(const Transposes &) { return {}; } // N/A for this routine 72 73 // 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> &)74 static void PrepareData(const Arguments<T>&, Queue&, const int, std::vector<T>&, 75 std::vector<T>&, std::vector<T>&, std::vector<T>&, std::vector<T>&, 76 std::vector<T>&, std::vector<T>&) {} // N/A for this routine 77 78 // Describes how to run the CLBlast routine RunRoutine(const Arguments<T> & args,Buffers<T> & buffers,Queue & queue)79 static StatusCode RunRoutine(const Arguments<T> &args, Buffers<T> &buffers, Queue &queue) { 80 auto queue_plain = queue(); 81 auto event = cl_event{}; 82 auto status = Gerc(args.layout, 83 args.m, args.n, args.alpha, 84 buffers.x_vec(), args.x_offset, args.x_inc, 85 buffers.y_vec(), args.y_offset, args.y_inc, 86 buffers.a_mat(), args.a_offset, args.a_ld, 87 &queue_plain, &event); 88 if (status == StatusCode::kSuccess) { clWaitForEvents(1, &event); clReleaseEvent(event); } 89 return status; 90 } 91 92 // Describes how to run the clBLAS routine (for correctness/performance comparison) 93 #ifdef CLBLAST_REF_CLBLAS RunReference1(const Arguments<T> & args,Buffers<T> & buffers,Queue & queue)94 static StatusCode RunReference1(const Arguments<T> &args, Buffers<T> &buffers, Queue &queue) { 95 auto queue_plain = queue(); 96 auto event = cl_event{}; 97 auto status = clblasXgerc(convertToCLBLAS(args.layout), 98 args.m, args.n, args.alpha, 99 buffers.x_vec, args.x_offset, args.x_inc, 100 buffers.y_vec, args.y_offset, args.y_inc, 101 buffers.a_mat, args.a_offset, args.a_ld, 102 1, &queue_plain, 0, nullptr, &event); 103 clWaitForEvents(1, &event); 104 return static_cast<StatusCode>(status); 105 } 106 #endif 107 108 // Describes how to run the CPU BLAS routine (for correctness/performance comparison) 109 #ifdef CLBLAST_REF_CBLAS RunReference2(const Arguments<T> & args,BuffersHost<T> & buffers_host,Queue &)110 static StatusCode RunReference2(const Arguments<T> &args, BuffersHost<T> &buffers_host, Queue &) { 111 cblasXgerc(convertToCBLAS(args.layout), 112 args.m, args.n, args.alpha, 113 buffers_host.x_vec, args.x_offset, args.x_inc, 114 buffers_host.y_vec, args.y_offset, args.y_inc, 115 buffers_host.a_mat, args.a_offset, args.a_ld); 116 return StatusCode::kSuccess; 117 } 118 #endif 119 120 // Describes how to run the cuBLAS routine (for correctness/performance comparison) 121 #ifdef CLBLAST_REF_CUBLAS RunReference3(const Arguments<T> & args,BuffersCUDA<T> & buffers,Queue &)122 static StatusCode RunReference3(const Arguments<T> &args, BuffersCUDA<T> &buffers, Queue &) { 123 auto status = cublasXgerc(reinterpret_cast<cublasHandle_t>(args.cublas_handle), args.layout, 124 args.m, args.n, args.alpha, 125 buffers.x_vec, args.x_offset, args.x_inc, 126 buffers.y_vec, args.y_offset, args.y_inc, 127 buffers.a_mat, args.a_offset, args.a_ld); 128 if (status == CUBLAS_STATUS_SUCCESS) { return StatusCode::kSuccess; } else { return StatusCode::kUnknownError; } 129 } 130 #endif 131 132 // Describes how to download the results of the computation (more importantly: which buffer) DownloadResult(const Arguments<T> & args,Buffers<T> & buffers,Queue & queue)133 static std::vector<T> DownloadResult(const Arguments<T> &args, Buffers<T> &buffers, Queue &queue) { 134 std::vector<T> result(args.a_size, static_cast<T>(0)); 135 buffers.a_mat.Read(queue, args.a_size, result); 136 return result; 137 } 138 139 // Describes how to compute the indices of the result buffer ResultID1(const Arguments<T> & args)140 static size_t ResultID1(const Arguments<T> &args) { return args.m; } ResultID2(const Arguments<T> & args)141 static size_t ResultID2(const Arguments<T> &args) { return args.n; } GetResultIndex(const Arguments<T> & args,const size_t id1,const size_t id2)142 static size_t GetResultIndex(const Arguments<T> &args, const size_t id1, const size_t id2) { 143 return (args.layout == Layout::kRowMajor) ? 144 id1*args.a_ld + id2 + args.a_offset: 145 id2*args.a_ld + id1 + args.a_offset; 146 } 147 148 // Describes how to compute performance metrics GetFlops(const Arguments<T> & args)149 static size_t GetFlops(const Arguments<T> &args) { 150 return 2 * args.m * args.n; 151 } GetBytes(const Arguments<T> & args)152 static size_t GetBytes(const Arguments<T> &args) { 153 return (2*args.m*args.n + args.m + args.n) * sizeof(T); 154 } 155 }; 156 157 // ================================================================================================= 158 } // namespace clblast 159 160 // CLBLAST_TEST_ROUTINES_XGERC_H_ 161 #endif 162