// ================================================================================================= // This file is part of the CLBlast project. The project is licensed under the MIT license. This // project loosely follows the Google C++ styleguide and uses a tab-size of two spaces and a max- // width of 100 characters per line. // // Author(s): // Cedric Nugteren // // This file implements the TestAC class (see the header for information about the class). // // ================================================================================================= #include #include "correctness/testac.h" namespace clblast { // ================================================================================================= // Constructor, initializes the base class tester and input data template TestAC::TestAC(int argc, char *argv[], const bool silent, const std::string &name, const std::vector &options, const Routine clblast_lambda, const Routine clblas_lambda): Tester{argc, argv, silent, name, options}, clblast_lambda_(clblast_lambda), clblas_lambda_(clblas_lambda) { // Computes the maximum sizes. This allows for a single set of input/output buffers. auto max_dim = *std::max_element(kMatrixDims.begin(), kMatrixDims.end()); auto max_ld = *std::max_element(kMatrixDims.begin(), kMatrixDims.end()); auto max_offset = *std::max_element(kOffsets.begin(), kOffsets.end()); // Creates test input data a_source_.resize(max_dim*max_ld + max_offset); c_source_.resize(max_dim*max_ld + max_offset); PopulateVector(a_source_); PopulateVector(c_source_); } // =============================================================================================== // Tests the routine for a wide variety of parameters template void TestAC::TestRegular(Arguments &args, const std::string &name) { if (!PrecisionSupported()) { return; } TestStart("regular behaviour", name); // Computes whether or not the matrices are transposed. Note that we assume a default of // column-major and no-transpose. If one of them is different (but not both), then rotated // is considered true. auto a_rotated = (args.layout == Layout::kColMajor && args.a_transpose != Transpose::kNo) || (args.layout == Layout::kRowMajor && args.a_transpose == Transpose::kNo); auto c_rotated = (args.layout == Layout::kRowMajor); // Iterates over the matrix dimensions for (auto &n: kMatrixDims) { args.n = n; for (auto &k: kMatrixDims) { args.k = k; // Computes the second dimensions of the matrices taking the rotation into account auto a_two = (a_rotated) ? n : k; auto c_two = (c_rotated) ? n : n; // Iterates over the leading-dimension values and the offsets for (auto &a_ld: kMatrixDims) { args.a_ld = a_ld; for (auto &a_offset: kOffsets) { args.a_offset = a_offset; for (auto &c_ld: kMatrixDims) { args.c_ld = c_ld; for (auto &c_offset: kOffsets) { args.c_offset = c_offset; // Computes the buffer sizes auto a_size = a_two * a_ld + a_offset; auto c_size = c_two * c_ld + c_offset; if (a_size < 1 || c_size < 1) { continue; } // Creates the OpenCL buffers auto a_mat = Buffer(context_, CL_MEM_READ_WRITE, a_size*sizeof(T)); auto r_mat = Buffer(context_, CL_MEM_READ_WRITE, c_size*sizeof(T)); auto s_mat = Buffer(context_, CL_MEM_READ_WRITE, c_size*sizeof(T)); // Iterates over the values for alpha and beta for (auto &alpha: kAlphaValues) { args.alpha = alpha; for (auto &beta: kBetaValues) { args.beta = beta; // Runs the reference clBLAS code a_mat.WriteBuffer(queue_, a_size*sizeof(T), a_source_); r_mat.WriteBuffer(queue_, c_size*sizeof(T), c_source_); auto status1 = clblas_lambda_(args, a_mat, r_mat, queue_); // Runs the CLBlast code a_mat.WriteBuffer(queue_, a_size*sizeof(T), a_source_); s_mat.WriteBuffer(queue_, c_size*sizeof(T), c_source_); auto status2 = clblast_lambda_(args, a_mat, s_mat, queue_); // Tests for equality of the two status codes if (status1 != StatusCode::kSuccess || status2 != StatusCode::kSuccess) { TestErrorCodes(status1, status2, args); continue; } // Downloads the results std::vector r_result(c_size, static_cast(0)); std::vector s_result(c_size, static_cast(0)); r_mat.ReadBuffer(queue_, c_size*sizeof(T), r_result); s_mat.ReadBuffer(queue_, c_size*sizeof(T), s_result); // Checks for differences in the output auto errors = size_t{0}; for (auto idn0=size_t{0}; idn0 void TestAC::TestInvalidBufferSizes(Arguments &args, const std::string &name) { if (!PrecisionSupported()) { return; } TestStart("invalid buffer sizes", name); // Sets example test parameters args.m = kBufferSize; args.n = kBufferSize; args.k = kBufferSize; args.a_ld = kBufferSize; args.c_ld = kBufferSize; args.a_offset = 0; args.c_offset = 0; // Iterates over test buffer sizes const std::vector kBufferSizes = {0, kBufferSize*kBufferSize-1, kBufferSize*kBufferSize}; for (auto &a_size: kBufferSizes) { for (auto &c_size: kBufferSizes) { // Creates the OpenCL buffers. Note: we are not using the C++ version since we explicitly // want to be able to create invalid buffers (no error checking here). auto a = clCreateBuffer(context_(), CL_MEM_READ_WRITE, a_size*sizeof(T), nullptr, nullptr); auto a_mat = Buffer(a); auto r = clCreateBuffer(context_(), CL_MEM_READ_WRITE, c_size*sizeof(T), nullptr, nullptr); auto r_mat = Buffer(r); auto s = clCreateBuffer(context_(), CL_MEM_READ_WRITE, c_size*sizeof(T), nullptr, nullptr); auto s_mat = Buffer(s); // Runs the two routines auto status1 = clblas_lambda_(args, a_mat, r_mat, queue_); auto status2 = clblast_lambda_(args, a_mat, s_mat, queue_); // Tests for equality of the two status codes TestErrorCodes(status1, status2, args); } } TestEnd(); } // ================================================================================================= // Compiles the templated class template class TestAC; template class TestAC; template class TestAC; template class TestAC; // ================================================================================================= } // namespace clblast