summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt12
-rw-r--r--test/correctness/testaxy.cc209
-rw-r--r--test/correctness/testaxy.h85
3 files changed, 305 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f93079d9..b6697ac3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -96,8 +96,9 @@ include_directories(${clblast_SOURCE_DIR}/include ${OPENCL_INCLUDE_DIRS})
set(KERNELS copy pad transpose padtranspose xaxpy xgemv xgemm)
set(SAMPLE_PROGRAMS sgemm)
set(ROUTINES_XY xaxpy)
+set(ROUTINES_AXY )
set(ROUTINES_ABC xgemm xsymm)
-set(ROUTINES ${ROUTINES_XY} ${ROUTINES_ABC})
+set(ROUTINES ${ROUTINES_XY} ${ROUTINES_AXY} ${ROUTINES_ABC})
# ==================================================================================================
@@ -169,6 +170,7 @@ if(TESTS)
# Creates the common correctness-tests objects (requires CMake 2.8.8)
add_library(test_correctness_common OBJECT test/correctness/tester.cc)
add_library(test_correctness_xy OBJECT test/correctness/testxy.cc)
+ add_library(test_correctness_axy OBJECT test/correctness/testaxy.cc)
add_library(test_correctness_abc OBJECT test/correctness/testabc.cc)
# Compiles the correctness-tests
@@ -180,6 +182,14 @@ if(TESTS)
target_link_libraries(test_${ROUTINE} clBLAS clblast ${OPENCL_LIBRARIES})
install(TARGETS test_${ROUTINE} DESTINATION bin)
endforeach()
+ foreach(ROUTINE ${ROUTINES_AXY})
+ add_executable(test_${ROUTINE}
+ $<TARGET_OBJECTS:test_correctness_common>
+ $<TARGET_OBJECTS:test_correctness_axy>
+ test/correctness/routines/${ROUTINE}.cc)
+ target_link_libraries(test_${ROUTINE} clBLAS clblast ${OPENCL_LIBRARIES})
+ install(TARGETS test_${ROUTINE} DESTINATION bin)
+ endforeach()
foreach(ROUTINE ${ROUTINES_ABC})
add_executable(test_${ROUTINE}
$<TARGET_OBJECTS:test_correctness_common>
diff --git a/test/correctness/testaxy.cc b/test/correctness/testaxy.cc
new file mode 100644
index 00000000..1e01a0e8
--- /dev/null
+++ b/test/correctness/testaxy.cc
@@ -0,0 +1,209 @@
+
+// =================================================================================================
+// 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 <www.cedricnugteren.nl>
+//
+// This file implements the TestAXY class (see the header for information about the class).
+//
+// =================================================================================================
+
+#include <algorithm>
+
+#include "correctness/testaxy.h"
+
+namespace clblast {
+// =================================================================================================
+
+// Constructor, initializes the base class tester and input data
+template <typename T>
+TestAXY<T>::TestAXY(const size_t platform_id, const size_t device_id,
+ const std::string &name, const std::vector<std::string> &options,
+ const Routine clblast_lambda, const Routine clblas_lambda):
+ Tester<T>{platform_id, device_id, 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(kMatrixVectorDims.begin(), kMatrixVectorDims.end());
+ auto max_ld = *std::max_element(kMatrixVectorDims.begin(), kMatrixVectorDims.end());
+ auto max_inc = *std::max_element(kIncrements.begin(), kIncrements.end());
+ auto max_offset = *std::max_element(kOffsets.begin(), kOffsets.end());
+
+ // Creates test input data
+ a_source_.resize(max_dim*max_ld + max_offset);
+ x_source_.resize(max_dim*max_inc + max_offset);
+ y_source_.resize(max_dim*max_inc + max_offset);
+ PopulateVector(a_source_);
+ PopulateVector(x_source_);
+ PopulateVector(y_source_);
+}
+
+// ===============================================================================================
+
+// Tests the routine for a wide variety of parameters
+template <typename T>
+void TestAXY<T>::TestRegular(Arguments<T> &args, const std::string &name) {
+ TestStart("regular behaviour", name);
+
+ // Computes whether or not the matrix is 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);
+
+ // Iterates over the dimension for the matrix and vectors
+ for (auto &m: kMatrixVectorDims) {
+ args.m = m;
+ for (auto &n: kMatrixVectorDims) {
+ args.n = n;
+
+ // Computes the second dimension of the matrix taking the rotation into account
+ auto a_two = (a_rotated) ? m : n;
+
+ // Iterates over the leading-dimension values and the offsets of the matrix
+ for (auto &a_ld: kMatrixVectorDims) {
+ args.a_ld = a_ld;
+ for (auto &a_offset: kOffsets) {
+ args.a_offset = a_offset;
+
+ // Iterates over the increment-values and the offsets of the vectors
+ for (auto &x_inc: kIncrements) {
+ args.x_inc = x_inc;
+ for (auto &x_offset: kOffsets) {
+ args.x_offset = x_offset;
+ for (auto &y_inc: kIncrements) {
+ args.y_inc = y_inc;
+ for (auto &y_offset: kOffsets) {
+ args.y_offset = y_offset;
+
+ // Computes the buffer sizes
+ auto a_size = a_two * a_ld + a_offset;
+ auto x_size = n * x_inc + x_offset;
+ auto y_size = n * y_inc + y_offset;
+ if (a_size < 1 || x_size < 1 || y_size < 1) { continue; }
+
+ // Creates the OpenCL buffers
+ auto a_mat = Buffer(context_, CL_MEM_READ_WRITE, a_size*sizeof(T));
+ auto x_vec = Buffer(context_, CL_MEM_READ_WRITE, x_size*sizeof(T));
+ auto r_vec = Buffer(context_, CL_MEM_READ_WRITE, y_size*sizeof(T));
+ auto s_vec = Buffer(context_, CL_MEM_READ_WRITE, y_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_);
+ x_vec.WriteBuffer(queue_, x_size*sizeof(T), x_source_);
+ r_vec.WriteBuffer(queue_, y_size*sizeof(T), y_source_);
+ auto status1 = clblas_lambda_(args, a_mat, x_vec, r_vec, queue_);
+
+ // Runs the CLBlast code
+ a_mat.WriteBuffer(queue_, a_size*sizeof(T), a_source_);
+ x_vec.WriteBuffer(queue_, x_size*sizeof(T), x_source_);
+ s_vec.WriteBuffer(queue_, y_size*sizeof(T), y_source_);
+ auto status2 = clblast_lambda_(args, a_mat, x_vec, s_vec, 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<T> r_result(y_size, static_cast<T>(0));
+ std::vector<T> s_result(y_size, static_cast<T>(0));
+ r_vec.ReadBuffer(queue_, y_size*sizeof(T), r_result);
+ s_vec.ReadBuffer(queue_, y_size*sizeof(T), s_result);
+
+ // Checks for differences in the output
+ auto errors = size_t{0};
+ for (auto idn=size_t{0}; idn<n; ++idn) {
+ auto index = idn*y_inc + y_offset;
+ if (!TestSimilarity(r_result[index], s_result[index], kErrorMargin)) {
+ errors++;
+ }
+ }
+
+ // Tests the error count (should be zero)
+ TestErrorCount(errors, n, args);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ TestEnd();
+}
+
+// =================================================================================================
+
+// Tests the routine for cases with invalid OpenCL memory buffer sizes. Tests only on return-types,
+// does not test for results (if any).
+template <typename T>
+void TestAXY<T>::TestInvalidBufferSizes(Arguments<T> &args, const std::string &name) {
+ TestStart("invalid buffer sizes", name);
+
+ // Sets example test parameters
+ args.m = kBufferSize;
+ args.n = kBufferSize;
+ args.a_ld = kBufferSize;
+
+ // Iterates over test buffer sizes
+ const std::vector<size_t> kMatrixSizes = {0, kBufferSize*kBufferSize-1, kBufferSize*kBufferSize};
+ const std::vector<size_t> kVectorSizes = {0, kBufferSize - 1, kBufferSize};
+ for (auto &a_size: kMatrixSizes) {
+ for (auto &x_size: kVectorSizes) {
+ for (auto &y_size: kVectorSizes) {
+
+ // Iterates over test increments
+ for (auto &x_inc: kInvalidIncrements) {
+ args.x_inc = x_inc;
+ for (auto &y_inc: kInvalidIncrements) {
+ args.y_inc = y_inc;
+
+ // 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 x = clCreateBuffer(context_(), CL_MEM_READ_WRITE, x_size*sizeof(T), nullptr, nullptr);
+ auto x_vec = Buffer(x);
+ auto r = clCreateBuffer(context_(), CL_MEM_READ_WRITE, y_size*sizeof(T), nullptr, nullptr);
+ auto r_vec = Buffer(r);
+ auto s = clCreateBuffer(context_(), CL_MEM_READ_WRITE, y_size*sizeof(T), nullptr, nullptr);
+ auto s_vec = Buffer(s);
+
+ // Runs the two routines
+ auto status1 = clblas_lambda_(args, a_mat, x_vec, r_vec, queue_);
+ auto status2 = clblast_lambda_(args, a_mat, x_vec, s_vec, queue_);
+
+ // Tests for equality of the two status codes
+ TestErrorCodes(status1, status2, args);
+ }
+ }
+ }
+ }
+ }
+ TestEnd();
+}
+
+// =================================================================================================
+
+// Compiles the templated class
+template class TestAXY<float>;
+template class TestAXY<double>;
+template class TestAXY<float2>;
+template class TestAXY<double2>;
+
+// =================================================================================================
+} // namespace clblast
diff --git a/test/correctness/testaxy.h b/test/correctness/testaxy.h
new file mode 100644
index 00000000..14cc22f4
--- /dev/null
+++ b/test/correctness/testaxy.h
@@ -0,0 +1,85 @@
+
+// =================================================================================================
+// 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 <www.cedricnugteren.nl>
+//
+// This file tests any mat-vec-vec (A,X,Y) routine. It contains two types of tests: one testing
+// all sorts of input combinations, and one deliberatly testing with invalid values.
+//
+// =================================================================================================
+
+#ifndef CLBLAST_TEST_CORRECTNESS_TESTAXY_H_
+#define CLBLAST_TEST_CORRECTNESS_TESTAXY_H_
+
+#include <vector>
+#include <string>
+
+#include "correctness/tester.h"
+
+namespace clblast {
+// =================================================================================================
+
+// See comment at top of file for a description of the class
+template <typename T>
+class TestAXY: public Tester<T> {
+ public:
+
+ // Uses several variables from the Tester class
+ using Tester<T>::context_;
+ using Tester<T>::queue_;
+ using Tester<T>::kErrorMargin;
+
+ // Uses several helper functions from the Tester class
+ using Tester<T>::TestStart;
+ using Tester<T>::TestEnd;
+ using Tester<T>::TestSimilarity;
+ using Tester<T>::TestErrorCount;
+ using Tester<T>::TestErrorCodes;
+ using Tester<T>::GetExampleScalars;
+
+ // Test settings for the regular test. Append to this list in case more tests are required.
+ const std::vector<size_t> kMatrixVectorDims = { 7, 64 };
+ const std::vector<size_t> kOffsets = { 0, 10 };
+ const std::vector<size_t> kIncrements = { 1, 2 };
+ const std::vector<T> kAlphaValues = GetExampleScalars();
+ const std::vector<T> kBetaValues = GetExampleScalars();
+
+ // Test settings for the invalid test
+ const std::vector<size_t> kInvalidIncrements = { 0, 1 };
+ const size_t kBufferSize = 64;
+
+ // Shorthand for a BLAS routine
+ using Routine = std::function<StatusCode(const Arguments<T>&,
+ const Buffer&, const Buffer&, const Buffer&,
+ CommandQueue&)>;
+
+ // Constructor, initializes the base class tester and input data
+ TestAXY(const size_t platform_id, const size_t device_id,
+ const std::string &name, const std::vector<std::string> &options,
+ const Routine clblast_lambda, const Routine clblas_lambda);
+
+ // The test functions, taking no inputs
+ void TestRegular(Arguments<T> &args, const std::string &name);
+ void TestInvalidBufferSizes(Arguments<T> &args, const std::string &name);
+
+ private:
+
+ // Source data to test with
+ std::vector<T> a_source_;
+ std::vector<T> x_source_;
+ std::vector<T> y_source_;
+
+ // The routines to test
+ Routine clblast_lambda_;
+ Routine clblas_lambda_;
+};
+
+// =================================================================================================
+} // namespace clblast
+
+// CLBLAST_TEST_CORRECTNESS_TESTAXY_H_
+#endif