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 Xherk 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_XHERK_H_ 17 #define CLBLAST_TEST_ROUTINES_XHERK_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, typename U> 26 class TestXherk { 27 public: 28 29 // The BLAS level: 1, 2, or 3 BLASLevel()30 static size_t BLASLevel() { return 3; } 31 32 // The list of arguments relevant for this routine GetOptions()33 static std::vector<std::string> GetOptions() { 34 return {kArgN, kArgK, 35 kArgLayout, kArgTriangle, kArgATransp, 36 kArgALeadDim, kArgCLeadDim, 37 kArgAOffset, kArgCOffset, 38 kArgAlpha, kArgBeta}; 39 } BuffersIn()40 static std::vector<std::string> BuffersIn() { return {kBufMatA, kBufMatC}; } BuffersOut()41 static std::vector<std::string> BuffersOut() { return {kBufMatC}; } 42 43 // Describes how to obtain the sizes of the buffers GetSizeA(const Arguments<U> & args)44 static size_t GetSizeA(const Arguments<U> &args) { 45 auto a_rotated = (args.layout == Layout::kColMajor && args.a_transpose != Transpose::kNo) || 46 (args.layout == Layout::kRowMajor && args.a_transpose == Transpose::kNo); 47 auto a_two = (a_rotated) ? args.n : args.k; 48 return a_two * args.a_ld + args.a_offset; 49 } GetSizeC(const Arguments<U> & args)50 static size_t GetSizeC(const Arguments<U> &args) { 51 return args.n * args.c_ld + args.c_offset; 52 } 53 54 // Describes how to set the sizes of all the buffers SetSizes(Arguments<U> & args)55 static void SetSizes(Arguments<U> &args) { 56 args.a_size = GetSizeA(args); 57 args.c_size = GetSizeC(args); 58 } 59 60 // Describes what the default values of the leading dimensions of the matrices are DefaultLDA(const Arguments<U> & args)61 static size_t DefaultLDA(const Arguments<U> &args) { return args.k; } DefaultLDB(const Arguments<U> &)62 static size_t DefaultLDB(const Arguments<U> &) { return 1; } // N/A for this routine DefaultLDC(const Arguments<U> & args)63 static size_t DefaultLDC(const Arguments<U> &args) { return args.n; } 64 65 // Describes which transpose options are relevant for this routine 66 using Transposes = std::vector<Transpose>; GetATransposes(const Transposes &)67 static Transposes GetATransposes(const Transposes &) { return {Transpose::kNo, Transpose::kConjugate}; } GetBTransposes(const Transposes &)68 static Transposes GetBTransposes(const Transposes &) { return {}; } // N/A for this routine 69 70 // Describes how to prepare the input data PrepareData(const Arguments<U> &,Queue &,const int,std::vector<T> &,std::vector<T> &,std::vector<T> &,std::vector<T> &,std::vector<T> &,std::vector<T> &,std::vector<T> &)71 static void PrepareData(const Arguments<U>&, Queue&, const int, std::vector<T>&, 72 std::vector<T>&, std::vector<T>&, std::vector<T>&, std::vector<T>&, 73 std::vector<T>&, std::vector<T>&) {} // N/A for this routine 74 75 // Describes how to run the CLBlast routine RunRoutine(const Arguments<U> & args,Buffers<T> & buffers,Queue & queue)76 static StatusCode RunRoutine(const Arguments<U> &args, Buffers<T> &buffers, Queue &queue) { 77 auto queue_plain = queue(); 78 auto event = cl_event{}; 79 auto status = Herk(args.layout, args.triangle, args.a_transpose, 80 args.n, args.k, args.alpha, 81 buffers.a_mat(), args.a_offset, args.a_ld, args.beta, 82 buffers.c_mat(), args.c_offset, args.c_ld, 83 &queue_plain, &event); 84 if (status == StatusCode::kSuccess) { clWaitForEvents(1, &event); clReleaseEvent(event); } 85 return status; 86 } 87 88 // Describes how to run the clBLAS routine (for correctness/performance comparison) 89 #ifdef CLBLAST_REF_CLBLAS RunReference1(const Arguments<U> & args,Buffers<T> & buffers,Queue & queue)90 static StatusCode RunReference1(const Arguments<U> &args, Buffers<T> &buffers, Queue &queue) { 91 auto queue_plain = queue(); 92 auto event = cl_event{}; 93 auto status = clblasXherk(convertToCLBLAS(args.layout), 94 convertToCLBLAS(args.triangle), 95 convertToCLBLAS(args.a_transpose), 96 args.n, args.k, args.alpha, 97 buffers.a_mat, args.a_offset, args.a_ld, args.beta, 98 buffers.c_mat, args.c_offset, args.c_ld, 99 1, &queue_plain, 0, nullptr, &event); 100 clWaitForEvents(1, &event); 101 return static_cast<StatusCode>(status); 102 } 103 #endif 104 105 // Describes how to run the CPU BLAS routine (for correctness/performance comparison) 106 #ifdef CLBLAST_REF_CBLAS RunReference2(const Arguments<U> & args,BuffersHost<T> & buffers_host,Queue &)107 static StatusCode RunReference2(const Arguments<U> &args, BuffersHost<T> &buffers_host, Queue&) { 108 cblasXherk(convertToCBLAS(args.layout), 109 convertToCBLAS(args.triangle), 110 convertToCBLAS(args.a_transpose), 111 args.n, args.k, args.alpha, 112 buffers_host.a_mat, args.a_offset, args.a_ld, args.beta, 113 buffers_host.c_mat, args.c_offset, args.c_ld); 114 return StatusCode::kSuccess; 115 } 116 #endif 117 118 // Describes how to run the cuBLAS routine (for correctness/performance comparison) 119 #ifdef CLBLAST_REF_CUBLAS RunReference3(const Arguments<U> & args,BuffersCUDA<T> & buffers,Queue &)120 static StatusCode RunReference3(const Arguments<U> &args, BuffersCUDA<T> &buffers, Queue &) { 121 auto status = cublasXherk(reinterpret_cast<cublasHandle_t>(args.cublas_handle), args.layout, 122 convertToCUBLAS(args.triangle), 123 convertToCUBLAS(args.a_transpose), 124 args.n, args.k, args.alpha, 125 buffers.a_mat, args.a_offset, args.a_ld, args.beta, 126 buffers.c_mat, args.c_offset, args.c_ld); 127 if (status == CUBLAS_STATUS_SUCCESS) { return StatusCode::kSuccess; } else { return StatusCode::kUnknownError; } 128 } 129 #endif 130 131 // Describes how to download the results of the computation (more importantly: which buffer) DownloadResult(const Arguments<U> & args,Buffers<T> & buffers,Queue & queue)132 static std::vector<T> DownloadResult(const Arguments<U> &args, Buffers<T> &buffers, Queue &queue) { 133 std::vector<T> result(args.c_size, static_cast<T>(0)); 134 buffers.c_mat.Read(queue, args.c_size, result); 135 return result; 136 } 137 138 // Describes how to compute the indices of the result buffer ResultID1(const Arguments<U> & args)139 static size_t ResultID1(const Arguments<U> &args) { return args.n; } ResultID2(const Arguments<U> & args)140 static size_t ResultID2(const Arguments<U> &args) { return args.n; } GetResultIndex(const Arguments<U> & args,const size_t id1,const size_t id2)141 static size_t GetResultIndex(const Arguments<U> &args, const size_t id1, const size_t id2) { 142 return id1*args.c_ld + id2 + args.c_offset; 143 } 144 145 // Describes how to compute performance metrics GetFlops(const Arguments<U> & args)146 static size_t GetFlops(const Arguments<U> &args) { 147 return args.n * args.n * args.k; 148 } GetBytes(const Arguments<U> & args)149 static size_t GetBytes(const Arguments<U> &args) { 150 return (args.n*args.k + args.n*args.n) * sizeof(T); 151 } 152 }; 153 154 // ================================================================================================= 155 } // namespace clblast 156 157 // CLBLAST_TEST_ROUTINES_XHERK_H_ 158 #endif 159