GTestSuite: Added Tests for DGEMMT

- Added API tests for DGEMMT.
  - Added Extreme Value Test cases (EVT) for DGEMMT.
    - Tests for various combinations of INFs
       and NANs for A and B matrix are added.
  - Added Invalid input test cases (IIT).
  - Added memory testing for DGEMMT API.

AMD-Internal: [CPUPL-4724]
Change-Id: Ib40802ea49417b4a4883831c2d971e59a2e093e5
This commit is contained in:
Shubham Sharma
2024-03-21 08:48:20 +00:00
parent 3687356530
commit 00b37f30a9
4 changed files with 652 additions and 63 deletions

View File

@@ -0,0 +1,297 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "common/testing_helpers.h"
#include "gemmt.h"
#include "inc/check_error.h"
#include "common/wrong_inputs_helpers.h"
template <typename T>
class GEMMT_IIT_ERS : public ::testing::Test {};
typedef ::testing::Types<float, double, scomplex, dcomplex> TypeParam; // The supported datatypes from BLAS calls for GEMMT
TYPED_TEST_SUITE(GEMMT_IIT_ERS, TypeParam); // Defining individual testsuites based on the datatype support.
// Adding namespace to get default parameters(valid case) from testinghelpers/common/wrong_input_helpers.h.
using namespace testinghelpers::IIT;
#if defined(TEST_BLAS) || defined(TEST_CBLAS)
/*
Incorrect Input Testing(IIT)
BLAS exceptions get triggered in the following cases(for GEMM):
1. When UPLO != 'L' || UPLO != 'U' (info = 1)
2. When TRANSA != 'N' || TRANSA != 'T' || TRANSA != 'C' (info = 2)
3. When TRANSB != 'N' || TRANSB != 'T' || TRANSB != 'C' (info = 3)
4. When n < 0 (info = 4)
5. When k < 0 (info = 5)
6. When lda < max(1, thresh) (info = 8), thresh set based on TRANSA value
7. When ldb < max(1, thresh) (info = 10), thresh set based on TRANSB value
8. When ldc < max(1, n) (info = 13)
*/
// When info == 1
TYPED_TEST(GEMMT_IIT_ERS, invalid_uploa)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, 'A', TRANS, TRANS, N, K, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When info == 2
TYPED_TEST(GEMMT_IIT_ERS, invalid_transa)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, 'A', TRANS, N, K, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When info == 3
TYPED_TEST(GEMMT_IIT_ERS, invalid_transb)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, 'A', N, K, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When info == 4
TYPED_TEST(GEMMT_IIT_ERS, n_lt_zero)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, TRANS, -1, K, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When info == 5
TYPED_TEST(GEMMT_IIT_ERS, k_lt_zero)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, TRANS, N, -1, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When info == 8
TYPED_TEST(GEMMT_IIT_ERS, invalid_lda)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, TRANS, N, K, &alpha, a.data(), LDA-1, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When info == 10
TYPED_TEST(GEMMT_IIT_ERS, invalid_ldb)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, TRANS, N, K, &alpha, a.data(), LDA, b.data(), LDB-1, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When info == 13
TYPED_TEST(GEMMT_IIT_ERS, invalid_ldc)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, TRANS, N, K, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC-1 );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
/*
Early Return Scenarios(ERS) :
The GEMMt API is expected to return early in the following cases:
1. When n == 0.
2. When (alpha == 0 or k == 0) and beta == 1.
*/
// When n is 0
TYPED_TEST(GEMMT_IIT_ERS, n_eq_zero)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, TRANS, 0, K, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When alpha is 0 and beta is 1
TYPED_TEST(GEMMT_IIT_ERS, alpha_zero_beta_one)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, TRANS, N, K, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
// When k is 0 and beta is 1
TYPED_TEST(GEMMT_IIT_ERS, k_zero_beta_one)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> c = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, N, LDC);
std::vector<T> a = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', N, K, LDA);
std::vector<T> b = testinghelpers::get_random_matrix<T>(-10, 10, STORAGE, 'N', K, N, LDB);
// Copy so that we check that the elements of C are not modified.
std::vector<T> c_ref(c);
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initone<T>( beta );
gemmt<T>( STORAGE, UPLO, TRANS, TRANS, N, 0, &alpha, a.data(), LDA, b.data(), LDB, &beta, c.data(), LDC );
computediff<T>( STORAGE, N, N, c.data(), c_ref.data(), LDC );
}
#endif

View File

@@ -0,0 +1,175 @@
/*
BLIS
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name(s) of the copyright holder(s) nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <gtest/gtest.h>
#include "test_gemmt.h"
class dgemmtEVT :
public ::testing::TestWithParam<std::tuple<char, // storage format
char, // uplo
char, // transa
char, // transb
gtint_t, // n
gtint_t, // k
double, // alpha
double, // beta
gtint_t, // lda_inc
gtint_t, // ldb_inc
gtint_t, // ldc_inc
double, // exception value for A matrix
double, // exception value for B matrix
double>> {}; // exception value for C matrix
TEST_P( dgemmtEVT, NaNInfCheck )
{
using T = double;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// matrix storage format(row major, column major)
char storage = std::get<0>(GetParam());
// specifies if the upper or lower triangular part of C is used
char uplo = std::get<1>(GetParam());
// denotes whether matrix a is n,c,t,h
char transa = std::get<2>(GetParam());
// denotes whether matrix b is n,c,t,h
char transb = std::get<3>(GetParam());
// matrix size n
gtint_t n = std::get<4>(GetParam());
// matrix size k
gtint_t k = std::get<5>(GetParam());
// specifies alpha value
T alpha = std::get<6>(GetParam());
// specifies beta value
T beta = std::get<7>(GetParam());
// lda, ldb, ldc increments.
// If increments are zero, then the array size matches the matrix size.
// If increments are nonnegative, the array size is bigger than the matrix size.
gtint_t lda_inc = std::get<8>(GetParam());
gtint_t ldb_inc = std::get<9>(GetParam());
gtint_t ldc_inc = std::get<10>(GetParam());
T aexval = std::get<11>(GetParam());
T bexval = std::get<12>(GetParam());
T cexval = std::get<13>(GetParam());
// Set the threshold for the errors:
double thresh = 10*n*k*testinghelpers::getEpsilon<T>();
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
test_gemmt<T>( storage, uplo, transa, transb, n, k, lda_inc, ldb_inc, ldc_inc,
alpha, beta, thresh, false, true, aexval, bexval, cexval );
}
class dgemmtEVTPrint
{
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,char,char,gtint_t,gtint_t,double,double,gtint_t,gtint_t,gtint_t,double,double,double>> str) const {
char sfm = std::get<0>(str.param);
char uplo = std::get<1>(str.param);
char tsa = std::get<2>(str.param);
char tsb = std::get<3>(str.param);
gtint_t n = std::get<4>(str.param);
gtint_t k = std::get<5>(str.param);
double alpha = std::get<6>(str.param);
double beta = std::get<7>(str.param);
gtint_t lda_inc = std::get<8>(str.param);
gtint_t ldb_inc = std::get<9>(str.param);
gtint_t ldc_inc = std::get<10>(str.param);
double aexval = std::get<11>(str.param);
double bexval = std::get<12>(str.param);
double cexval = std::get<13>(str.param);
#ifdef TEST_BLAS
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_";
#endif
str_name = str_name + "_storage_" + sfm;
str_name = str_name + "_transa_" + tsa;
str_name = str_name + "_transb_" + tsb;
str_name = str_name + "_uploa_" + uplo;
str_name = str_name + "_n_" + std::to_string(n);
str_name = str_name + "_k_" + std::to_string(k);
std::string alpha_str = testinghelpers::get_value_string(alpha);
str_name = str_name + "_alpha_" + alpha_str;
std::string beta_str = testinghelpers::get_value_string(beta);
str_name = str_name + "_beta_" + beta_str;
gtint_t lda = testinghelpers::get_leading_dimension( sfm, tsa, n, k, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( sfm, tsb, k, n, ldb_inc );
gtint_t ldc = testinghelpers::get_leading_dimension( sfm, 'n', n, n, ldc_inc );
str_name = str_name + "_ex_a_" + testinghelpers::get_value_string(aexval);
str_name = str_name + "_ex_b_" + testinghelpers::get_value_string(bexval);
str_name = str_name + "_ex_c_" + testinghelpers::get_value_string(cexval);
str_name = str_name + "_ldb_" + std::to_string(lda);
str_name = str_name + "_ldb_" + std::to_string(ldb);
str_name = str_name + "_ldc_" + std::to_string(ldc);
return str_name;
}
};
static double AOCL_NAN = std::numeric_limits<double>::quiet_NaN();
static double AOCL_INF = std::numeric_limits<double>::infinity();
#ifndef TEST_BLIS_TYPED
INSTANTIATE_TEST_SUITE_P(
Native,
dgemmtEVT,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uplo u:upper, l:lower
::testing::Values('n','t'), // transa
::testing::Values('n','t'), // transb
::testing::Values(7, 800), // n
::testing::Values(7, 800), // k
::testing::Values(2.4, AOCL_NAN/*, AOCL_INF, -AOCL_INF*/), // alpha //commented values fail
::testing::Values(2.4/*, AOCL_NAN*/, AOCL_INF, -AOCL_INF), // beta //commented values fail
::testing::Values(gtint_t(0)), // increment to the leading dim of a
::testing::Values(gtint_t(0)), // increment to the leading dim of b
::testing::Values(gtint_t(0)), // increment to the leading dim of c
::testing::Values(0.0, AOCL_NAN, AOCL_INF, -AOCL_INF), // extreme value for A matrix
::testing::Values(0.0, AOCL_NAN, AOCL_INF, -AOCL_INF), // extreme value for B matrix
::testing::Values(0.0, AOCL_NAN, AOCL_INF, -AOCL_INF) // extreme value for B matrix
),
::dgemmtEVTPrint()
);
#endif

View File

@@ -4,7 +4,7 @@
An object-based framework for developing high-performance BLAS-like
libraries.
Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved.
Copyright (C) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -35,22 +35,23 @@
#include <gtest/gtest.h>
#include "test_gemmt.h"
class dgemmtTest :
public ::testing::TestWithParam<std::tuple<char,
char,
char,
char,
gtint_t,
gtint_t,
double,
double,
gtint_t,
gtint_t,
gtint_t>> {};
class dgemmtAPI :
public ::testing::TestWithParam<std::tuple<char, // storage
char, // uplo
char, // transa
char, // transb
gtint_t, // n
gtint_t, // k
double, // alpha
double, // beta
gtint_t, // lda_inc
gtint_t, // ldb_inc
gtint_t, // ldc_inc
bool>> {}; // is memory test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(dgemmtTest);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(dgemmtAPI);
TEST_P(dgemmtTest, RandomData)
TEST_P(dgemmtAPI, FunctionalTest)
{
using T = double;
//----------------------------------------------------------
@@ -79,6 +80,7 @@ TEST_P(dgemmtTest, RandomData)
gtint_t lda_inc = std::get<8>(GetParam());
gtint_t ldb_inc = std::get<9>(GetParam());
gtint_t ldc_inc = std::get<10>(GetParam());
bool is_mem_test = std::get<11>(GetParam());
// Set the threshold for the errors:
double thresh = 10*n*k*testinghelpers::getEpsilon<T>();
@@ -86,17 +88,17 @@ TEST_P(dgemmtTest, RandomData)
//----------------------------------------------------------
// Call test body using these parameters
//----------------------------------------------------------
test_gemmt<T>( storage, uplo, transa, transb, n, k, lda_inc, ldb_inc, ldc_inc, alpha, beta, thresh );
test_gemmt<T>( storage, uplo, transa, transb, n, k, lda_inc, ldb_inc, ldc_inc, alpha, beta, thresh, is_mem_test );
}
class dgemmtTestPrint {
class dgemmtPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,char,char,char,gtint_t,gtint_t,double,double,gtint_t,gtint_t,gtint_t>> str) const {
testing::TestParamInfo<std::tuple<char,char,char,char,gtint_t,gtint_t,double,double,gtint_t,gtint_t,gtint_t,bool>> str) const {
char sfm = std::get<0>(str.param);
char tsa = std::get<1>(str.param);
char tsb = std::get<2>(str.param);
char uplo = std::get<3>(str.param);
char uplo = std::get<1>(str.param);
char tsa = std::get<2>(str.param);
char tsb = std::get<3>(str.param);
gtint_t n = std::get<4>(str.param);
gtint_t k = std::get<5>(str.param);
double alpha = std::get<6>(str.param);
@@ -104,51 +106,105 @@ public:
gtint_t lda_inc = std::get<8>(str.param);
gtint_t ldb_inc = std::get<9>(str.param);
gtint_t ldc_inc = std::get<10>(str.param);
bool is_mem_test = std::get<11>(str.param);
#ifdef TEST_BLAS
std::string str_name = "dgemmt_";
std::string str_name = "blas_";
#elif TEST_CBLAS
std::string str_name = "cblas_dgemmt";
std::string str_name = "cblas_";
#else //#elif TEST_BLIS_TYPED
std::string str_name = "bli_dgemmt";
std::string str_name = "bli_";
#endif
str_name = str_name + "_" + sfm+sfm+sfm;
str_name = str_name + "_" + tsa + tsb;
str_name = str_name + "_" + uplo;
str_name = str_name + "_" + std::to_string(n);
str_name = str_name + "_" + std::to_string(k);
std::string alpha_str = ( alpha > 0) ? std::to_string(int(alpha)) : "m" + std::to_string(int(std::abs(alpha)));
str_name = str_name + "_a" + alpha_str;
std::string beta_str = ( beta > 0) ? std::to_string(int(beta)) : "m" + std::to_string(int(std::abs(beta)));
str_name = str_name + "_b" + beta_str;
str_name = str_name + "_" + std::to_string(lda_inc);
str_name = str_name + "_" + std::to_string(ldb_inc);
str_name = str_name + "_" + std::to_string(ldc_inc);
str_name = str_name + "_storage_" + sfm;
str_name = str_name + "_transa_" + tsa;
str_name = str_name + "_transb_" + tsb;
str_name = str_name + "_uploa_" + uplo;
str_name = str_name + "_n_" + std::to_string(n);
str_name = str_name + "_k_" + std::to_string(k);
std::string alpha_str = testinghelpers::get_value_string(alpha);
str_name = str_name + "_alpha_" + alpha_str;
std::string beta_str = testinghelpers::get_value_string(beta);
str_name = str_name + "_beta_" + beta_str;
gtint_t lda = testinghelpers::get_leading_dimension( sfm, tsa, n, k, lda_inc );
gtint_t ldb = testinghelpers::get_leading_dimension( sfm, tsb, k, n, ldb_inc );
gtint_t ldc = testinghelpers::get_leading_dimension( sfm, 'n', n, n, ldc_inc );
str_name = str_name + "_lda_" + std::to_string(lda);
str_name = str_name + "_ldb_" + std::to_string(ldb);
str_name = str_name + "_ldc_" + std::to_string(ldc);
str_name = str_name + (is_mem_test ? "_mem_test_enabled" : "_mem_test_disabled");
return str_name;
}
};
// Disable tests for BLIS_TYPED case due to compiler errors.
#ifndef TEST_BLIS_TYPED
// Black box testing.
INSTANTIATE_TEST_SUITE_P(
Blackbox,
dgemmtTest,
skinny_fringe_cases,
dgemmtAPI,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS
,'r'
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uplo u:upper, l:lower
::testing::Values('n','c','t'), // transa
::testing::Values('n','c','t'), // transb
::testing::Range(gtint_t(10), gtint_t(31), 10), // n
::testing::Range(gtint_t(10), gtint_t(31), 10), // k
::testing::Values(2.0), // alpha
::testing::Values(3.0), // beta
::testing::Values(gtint_t(0), gtint_t(4)), // increment to the leading dim of a
::testing::Values(gtint_t(0), gtint_t(1)), // increment to the leading dim of b
::testing::Values(gtint_t(0), gtint_t(2)) // increment to the leading dim of c
::testing::Values('n','t'), // transa
::testing::Values('n','t'), // transb
::testing::Range(gtint_t(1), gtint_t(30), 1), // n
::testing::Range(gtint_t(1), gtint_t(30), 1), // k
::testing::Values(1.0, 0.0, -2.4, 3.1), // alpha
::testing::Values(1.0, 0.0, -2.4, 3.1), // beta
::testing::Values(gtint_t(0), gtint_t(153)), // increment to the leading dim of a
::testing::Values(gtint_t(0), gtint_t(122)), // increment to the leading dim of b
::testing::Values(gtint_t(0), gtint_t(195)), // increment to the leading dim of c
::testing::Values(true, false) // is memory test
),
::dgemmtTestPrint()
::dgemmtPrint()
);
INSTANTIATE_TEST_SUITE_P(
skinny,
dgemmtAPI,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uplo u:upper, l:lower
::testing::Values('n','t'), // transa
::testing::Values('n','t'), // transb
::testing::Values(35, 537, 799), // n
::testing::Values(35, 537, 799), // k
::testing::Values(1.0, 0.0, -2.4, 3.1), // alpha
::testing::Values(1.0, 0.0, -2.4, 3.1), // beta
::testing::Values(gtint_t(0), gtint_t(153)), // increment to the leading dim of a
::testing::Values(gtint_t(0), gtint_t(122)), // increment to the leading dim of b
::testing::Values(gtint_t(0), gtint_t(195)), // increment to the leading dim of c
::testing::Values(true, false) // is memory test
),
::dgemmtPrint()
);
INSTANTIATE_TEST_SUITE_P(
large,
dgemmtAPI,
::testing::Combine(
::testing::Values('c'
#ifndef TEST_BLAS
,'r'
#endif
), // storage format
::testing::Values('u','l'), // uplo u:upper, l:lower
::testing::Values('n','t'), // transa
::testing::Values('n','t'), // transb
::testing::Values(800, 1500), // n
::testing::Values(800, 1500), // k
::testing::Values(1.0, 0.0, -2.4, 3.1), // alpha
::testing::Values(1.0, 0.0, -2.4, 3.1), // beta
::testing::Values(gtint_t(0), gtint_t(153)), // increment to the leading dim of a
::testing::Values(gtint_t(0), gtint_t(122)), // increment to the leading dim of b
::testing::Values(gtint_t(0), gtint_t(195)), // increment to the leading dim of c
::testing::Values(true, false) // is memory test
),
::dgemmtPrint()
);
#endif

View File

@@ -39,11 +39,13 @@
#include "inc/check_error.h"
#include <stdexcept>
#include <algorithm>
#include "common/testing_helpers.h"
template<typename T>
void test_gemmt( char storage, char uplo, char trnsa, char trnsb, gtint_t n,
gtint_t k, gtint_t lda_inc, gtint_t ldb_inc, gtint_t ldc_inc, T alpha,
T beta, double thresh )
T beta, double thresh, bool is_mem_test=false, bool is_evt_test=false,
T evt_a=T{0.0}, T evt_b=T{0.0}, T evt_c=T{0.0} )
{
// Compute the leading dimensions of a, b, and c.
gtint_t lda = testinghelpers::get_leading_dimension( storage, trnsa, n, k, lda_inc );
@@ -53,27 +55,86 @@ void test_gemmt( char storage, char uplo, char trnsa, char trnsb, gtint_t n,
//----------------------------------------------------------
// Initialize matrics with random numbers
//----------------------------------------------------------
std::vector<T> a = testinghelpers::get_random_matrix<T>( -2, 8, storage, trnsa, n, k, lda );
std::vector<T> b = testinghelpers::get_random_matrix<T>( -5, 2, storage, trnsb, k, n, ldb );
std::vector<T> c = testinghelpers::get_random_matrix<T>( -3, 5, storage, 'n', n, n, ldc );
T *a_ptr, *b_ptr, *c_ptr;
dim_t size_a = testinghelpers::matsize(storage, trnsa, n, k, lda) * sizeof(T);
testinghelpers::ProtectedBuffer a(size_a, false, is_mem_test );
a_ptr = (T*)a.greenzone_1;
testinghelpers::datagenerators::randomgenerators<T>( -2, 8, storage, n, k, a_ptr, trnsa, lda);
dim_t size_b = testinghelpers::matsize(storage, trnsb, k, n, ldb) * sizeof(T);
testinghelpers::ProtectedBuffer b(size_b, false, is_mem_test );
b_ptr = (T*)b.greenzone_1;
testinghelpers::datagenerators::randomgenerators<T>( -5, 2, storage, k, n, b_ptr, trnsb, ldb);
dim_t size_c = testinghelpers::matsize(storage, 'n', n, n, ldc) * sizeof(T);
testinghelpers::ProtectedBuffer c(size_c, false, is_mem_test );
c_ptr = (T*)c.greenzone_1;
testinghelpers::datagenerators::randomgenerators<T>( -3, 5, storage, n, n, c_ptr, 'n', ldc);
if ( is_evt_test )
{
dim_t n_rand = rand() % std::min(n, k);
dim_t k_rand = rand() % std::min(n, k);
a_ptr[n_rand + k_rand * lda] = evt_a;
}
if ( is_evt_test )
{
dim_t n_rand = rand() % std::min(n, k);
dim_t k_rand = rand() % std::min(n, k);
b_ptr[n_rand + k_rand * lda] = evt_a;
}
if ( is_evt_test )
{
dim_t n_rand = rand() % std::min(n, k);
dim_t k_rand = rand() % std::min(n, k);
b_ptr[n_rand + k_rand * lda] = evt_a;
}
// Create a copy of c so that we can check reference results.
std::vector<T> c_ref(c);
std::vector<T> c_ref(testinghelpers::matsize(storage, 'n', n, n, ldc));
memcpy(c_ref.data(), c_ptr, size_c);
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
gemmt<T>( storage, uplo, trnsa, trnsb, n, k, &alpha, a.data(), lda,
b.data(), ldb, &beta, c.data(), ldc );
// add signal handler for segmentation fault
testinghelpers::ProtectedBuffer::start_signal_handler();
try
{
//----------------------------------------------------------
// Call BLIS function
//----------------------------------------------------------
gemmt<T>( storage, uplo, trnsa, trnsb, n, k, &alpha, a_ptr, lda,
b_ptr, ldb, &beta, c_ptr, ldc );
if (is_mem_test)
{
memcpy(a.greenzone_2, a.greenzone_1, size_a);
memcpy(b.greenzone_2, b.greenzone_1, size_b);
memcpy(c.greenzone_2, c_ref.data(), size_c);
gemmt<T>( storage, uplo, trnsa, trnsb, n, k, &alpha, (T*)a.greenzone_2, lda,
(T*)b.greenzone_2, ldb, &beta, (T*)c.greenzone_2, ldc );
}
}
catch(const std::exception& e)
{
// reset to default signal handler
testinghelpers::ProtectedBuffer::stop_signal_handler();
// show failure in case seg fault was detected
FAIL() << "Memory Test Failed";
}
// reset to default signal handler
testinghelpers::ProtectedBuffer::stop_signal_handler();
//----------------------------------------------------------
// Call reference implementation.
//----------------------------------------------------------
testinghelpers::ref_gemmt<T>( storage, uplo, trnsa, trnsb, n, k, alpha,
a.data(), lda, b.data(), ldb, beta, c_ref.data(), ldc );
a_ptr, lda, b_ptr, ldb, beta, c_ref.data(), ldc );
//----------------------------------------------------------
// check component-wise error.
//----------------------------------------------------------
computediff<T>( storage, n, n, c.data(), c_ref.data(), ldc, thresh );
computediff<T>( storage, n, n, c_ptr, c_ref.data(), ldc, thresh, is_evt_test );
}