Negative parameter testing for ?COPY, ?AXPY and ?AXPBY APIs

- As per the standard compliance, the ?copy(), ?axpy() and
  ?axpby() APIs do not require invalid input testing(IIT)
  with respect to the input parameters they receive, as part
  of BLAS and CBLAS calls.

- Thus, test-cases have been added to verify early return scenarios
  (ERS) as per the compliance. The testsuite is type-parameterized,
  since the compliance for early return cases is the same across the
  datatypes.

- Updated the conditional directives in micro-kernel(ukr) test files
  to include the new set of macros generated as part of the
  buildsystem in GTestsuite.

- Updated the conditional macro to enable the appropriate code
  section for compilation of ref_axpbyv(), based on our choice
  of reference library when building GTestsuite.

AMD-Internal: [CPUPL-4402]
Change-Id: Ibea2bc34469b008f4d4558ce359717c08b92e978
This commit is contained in:
Vignesh Balasubramanian
2024-01-23 16:27:02 +05:30
committed by Vignesh Balasubramanian
parent 63be4c8ce4
commit ddec0c1de0
9 changed files with 386 additions and 28 deletions

View File

@@ -37,7 +37,7 @@
namespace testinghelpers {
#if !defined(REF_IS_OPENBLAS) || !defined(REF_IS_MKL)
#if !defined(REF_IS_OPENBLAS) && !defined(REF_IS_MKL)
template<typename T>
void ref_axpbyv( char conj_x, gtint_t n, T alpha, const T* x,
gtint_t incx, T beta, T* y, gtint_t incy )

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
@@ -39,58 +39,102 @@
#include "common/wrong_inputs_helpers.h"
template <typename T>
class Axpby_IIT_ERS_Test : public ::testing::Test {};
typedef ::testing::Types<float, double, scomplex, dcomplex> TypeParam; // The supported datatypes from BLAS calls for AXPBY
TYPED_TEST_SUITE(Axpby_IIT_ERS_Test, TypeParam); // Defining individual testsuites based on the datatype support.
class Axpbyv_IIT_ERS_Test : public ::testing::Test {};
typedef ::testing::Types<float, double, scomplex, dcomplex> TypeParam; // The supported datatypes from BLAS/CBLAS calls for AXPBY
TYPED_TEST_SUITE(Axpbyv_IIT_ERS_Test, 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)
/*
Early Return Scenarios(ERS) :
The early return cases for ?axpbyv are not defined under BLAS compliance.
Thus, the necessary cases to match the other standards are tested.
The AXPBY API is expected to return early in the following cases:
1. When n < 0.
1. When n <= 0.
*/
#ifdef TEST_BLAS
// Early return cases with non-unit strides on vectors
// When n < 0
TYPED_TEST(Axpby_IIT_ERS_Test, n_lt_zero)
TYPED_TEST(Axpbyv_IIT_ERS_Test, n_lt_zero_nonUnitStrides)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, INC );
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initzero<T>( beta );
// Copy so that we check that the elements of C are not modified.
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpbyv<T>( CONJ, -1, alpha, nullptr, INC, beta, y.data(), INC );
axpbyv<T>( CONJ, -1, alpha, x.data(), 5, beta, y.data(), 5 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), INC );
computediff( N, y.data(), y_ref.data(), 5 );
}
// When n = 0
TYPED_TEST(Axpby_IIT_ERS_Test, n_eq_zero)
TYPED_TEST(Axpbyv_IIT_ERS_Test, n_eq_zero_nonUnitStrides)
{
using T = TypeParam;
// Defining the C matrix with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, INC );
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initzero<T>( beta );
// Copy so that we check that the elements of C are not modified.
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpbyv<T>( CONJ, 0, alpha, nullptr, INC, beta, y.data(), INC );
axpbyv<T>( CONJ, 0, alpha, x.data(), 5, beta, y.data(), 5 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), INC );
computediff( N, y.data(), y_ref.data(), 5 );
}
#endif
// Early return cases with unit strides on vectors
// When n < 0
TYPED_TEST(Axpbyv_IIT_ERS_Test, n_lt_zero_unitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initzero<T>( beta );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpbyv<T>( CONJ, -1, alpha, x.data(), 1, beta, y.data(), 1 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 1 );
}
// When n = 0
TYPED_TEST(Axpbyv_IIT_ERS_Test, n_eq_zero_unitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
T alpha, beta;
testinghelpers::initone<T>( alpha );
testinghelpers::initzero<T>( beta );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpbyv<T>( CONJ, 0, alpha, x.data(), 1, beta, y.data(), 1 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 1 );
}
#endif

View File

@@ -0,0 +1,174 @@
/*
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 "common/testing_helpers.h"
#include "axpyv.h"
#include "inc/check_error.h"
#include "common/wrong_inputs_helpers.h"
template <typename T>
class Axpyv_IIT_ERS_Test : public ::testing::Test {};
typedef ::testing::Types<float, double, scomplex, dcomplex> TypeParam; // The supported datatypes from BLAS/CBLAS calls for AXPY
TYPED_TEST_SUITE(Axpyv_IIT_ERS_Test, 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)
/*
Early Return Scenarios(ERS) for BLAS/CBLAS compliance :
The AXPY API is expected to return early in the following cases:
1. When n <= 0 (BLAS compliance).
2. When alpha = 0 (BLAS compliance).
*/
// Early return cases with non-unit strides on vectors
// When n < 0
TYPED_TEST(Axpyv_IIT_ERS_Test, n_lt_zero_nonUnitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
T alpha;
testinghelpers::initone<T>( alpha );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpyv<T>( CONJ, -1, alpha, x.data(), 5, y.data(), 5 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 5 );
}
// When n = 0
TYPED_TEST(Axpyv_IIT_ERS_Test, n_eq_zero_nonUnitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
T alpha;
testinghelpers::initone<T>( alpha );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpyv<T>( CONJ, 0, alpha, x.data(), 5, y.data(), 5 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 5 );
}
// When alpha = 0
TYPED_TEST(Axpyv_IIT_ERS_Test, alpha_eq_zero_nonUnitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
T alpha;
testinghelpers::initzero<T>( alpha );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpyv<T>( CONJ, N, alpha, x.data(), 5, y.data(), 5 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 5 );
}
// Early return cases with unit strides on vectors
// When n < 0
TYPED_TEST(Axpyv_IIT_ERS_Test, n_lt_zero_unitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
T alpha;
testinghelpers::initone<T>( alpha );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpyv<T>( CONJ, -1, alpha, x.data(), 1, y.data(), 1 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 1 );
}
// When n = 0
TYPED_TEST(Axpyv_IIT_ERS_Test, n_eq_zero_unitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
T alpha;
testinghelpers::initone<T>( alpha );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpyv<T>( CONJ, 0, alpha, x.data(), 1, y.data(), 1 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 1 );
}
// When alpha = 0
TYPED_TEST(Axpyv_IIT_ERS_Test, alpha_eq_zero_unitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
T alpha;
testinghelpers::initzero<T>( alpha );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
axpyv<T>( CONJ, N, alpha, x.data(), 1, y.data(), 1 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 1 );
}
#endif

View File

@@ -0,0 +1,126 @@
/*
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 "common/testing_helpers.h"
#include "copyv.h"
#include "inc/check_error.h"
#include "common/wrong_inputs_helpers.h"
template <typename T>
class Copyv_IIT_ERS_Test : public ::testing::Test {};
typedef ::testing::Types<float, double, scomplex, dcomplex> TypeParam; // The supported datatypes from BLAS/CBLAS calls for COPYV
TYPED_TEST_SUITE(Copyv_IIT_ERS_Test, 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)
/*
Early Return Scenarios(ERS) for BLAS/CBLAS compliance:
The COPYV API is expected to return early in the following cases:
1. When n <= 0.
*/
// Early return cases with non-unit strides on vectors
// When n < 0
TYPED_TEST(Copyv_IIT_ERS_Test, n_lt_zero_nonUnitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Defining the y_vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
copyv<T>( CONJ, -1, x.data(), 5, y.data(), 5 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 5 );
}
// When n = 0
TYPED_TEST(Copyv_IIT_ERS_Test, n_eq_zero_nonUnitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 5 );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
copyv<T>( CONJ, 0, x.data(), 5, y.data(), 5 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 5 );
}
// Early return cases with unit strides on vectors
// When n < 0
TYPED_TEST(Copyv_IIT_ERS_Test, n_lt_zero_unitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Defining the y_vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
copyv<T>( CONJ, -1, x.data(), 1, y.data(), 1 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 1 );
}
// When n = 0
TYPED_TEST(Copyv_IIT_ERS_Test, n_eq_zero_unitStrides)
{
using T = TypeParam;
// Defining the x vector
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Defining the y vector with values for debugging purposes
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, N, 1 );
// Copy so that we check that the elements of y are not modified.
std::vector<T> y_ref(y);
copyv<T>( CONJ, 0, x.data(), 1, y.data(), 1 );
// Use bitwise comparison (no threshold).
computediff( N, y.data(), y_ref.data(), 1 );
}
#endif

View File

@@ -43,6 +43,9 @@ class daxpbyvUkrTest :
gtint_t, // incy
double, // alpha
double>> {}; // beta
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(daxpbyvUkrTest);
// Tests using random integers as vector elements.
TEST_P( daxpbyvUkrTest, AccuracyCheck )
{
@@ -106,7 +109,7 @@ public:
}
};
#ifdef BLIS_KERNELS_ZEN
#if defined(BLIS_KERNELS_ZEN) && defined(GTEST_AVX2FMA3)
/*
Unit testing for functionality of bli_daxpbyv_zen_int10 kernel.
The code structure for bli_daxpbyv_zen_int10( ... ) is as follows :

View File

@@ -43,6 +43,9 @@ class saxpbyvUkrTest :
gtint_t, // incy
float, // alpha
float>> {}; // beta
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(saxpbyvUkrTest);
// Tests using random integers as vector elements.
TEST_P( saxpbyvUkrTest, AccuracyCheck )
{
@@ -106,7 +109,7 @@ public:
}
};
#ifdef BLIS_KERNELS_ZEN
#if defined(BLIS_KERNELS_ZEN) && defined(GTEST_AVX2FMA3)
// Unit testing with unit stride
INSTANTIATE_TEST_SUITE_P(
bli_saxpbyv_zen_int10_unitStride,

View File

@@ -43,6 +43,9 @@ class zaxpbyvUkrTest :
gtint_t, // incy
dcomplex, // alpha
dcomplex>> {}; // beta
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(zaxpbyvUkrTest);
// Tests using random integers as vector elements.
TEST_P( zaxpbyvUkrTest, AccuracyCheck )
{
@@ -108,7 +111,7 @@ public:
}
};
#ifdef BLIS_KERNELS_ZEN
#if defined(BLIS_KERNELS_ZEN) && defined(GTEST_AVX2FMA3)
// Unit testing with unit stride
INSTANTIATE_TEST_SUITE_P(
bli_zaxpbyv_zen_int_unitStride,

View File

@@ -42,6 +42,9 @@ class daxpyvUkrTest :
gtint_t, // incx
gtint_t, // incy
double>> {}; // alpha
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(daxpyvUkrTest);
// Tests using random integers as vector elements.
TEST_P( daxpyvUkrTest, AccuracyCheck )
{
@@ -100,7 +103,7 @@ public:
}
};
#ifdef BLIS_KERNELS_ZEN
#if defined(BLIS_KERNELS_ZEN) && defined(GTEST_AVX2FMA3)
/*
Unit testing for functionality of bli_daxpyv_zen_int10 kernel.
The code structure for bli_daxpyv_zen_int10( ... ) is as follows :
@@ -203,7 +206,7 @@ INSTANTIATE_TEST_SUITE_P(
);
#endif
#ifdef BLIS_KERNELS_ZEN4
#if defined(BLIS_KERNELS_ZEN4) && defined(GTEST_AVX512)
/*
Unit testing for functionality of bli_daxpyv_zen_int_avx512 kernel.
The code structure for bli_daxpyv_zen_int_avx512( ... ) is as follows :

View File

@@ -42,6 +42,8 @@ class dcopyvUkrTest :
gtint_t,
gtint_t>> {};
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(dcopyvUkrTest);
// Tests using random integers as vector elements.
TEST_P( dcopyvUkrTest, AccuracyCheck )
{
@@ -93,7 +95,7 @@ public:
}
};
#ifdef BLIS_KERNELS_ZEN
#if defined(BLIS_KERNELS_ZEN) && defined(GTEST_AVX2FMA3)
/*
Unit testing for functionality of bli_dcopyv_zen_int kernel.
The code structure for bli_dcopyv_zen_int( ... ) is as follows :