Added axpyf reference implementation for gtestsuite

- axpyf is a blis specific kernel, which performs axpy 
operation but in multiple of fused factors to speed up
the operations.

- So axpyf reference function is implemented for gtestsuite,
where axpyf computation compared against computation done by
looping over axpy function.

AMD-Internal: [CPUPL-4763]
Change-Id: I4713fd0b0d9e9cf688c9aaa82ac0e6ae07a05989
This commit is contained in:
Harsh Dave
2024-03-07 23:06:31 +05:30
parent da8fd8c301
commit f10d6eced6
5 changed files with 566 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
/*
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.
*/
#pragma once
#include "common/testing_helpers.h"
/*
* ==========================================================================
* AXPYV performs vector operations
* y := y + alpha * conjx(x)
* where x and y are vectors of length n, and alpha is a scalar
* ==========================================================================
**/
namespace testinghelpers {
template<typename T>
void ref_axpyf( conj_t conja,
conj_t conjx,
gint_t m,
gint_t b_n,
T *alpha,
T* a,
gint_t inca,
gint_t lda,
T* x,
gint_t incx,
T* y,
gint_t incy
);
} //end of namespace testinghelpers

View File

@@ -0,0 +1,162 @@
/*
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 "blis.h"
#include "level1/ref_axpyv.h"
#include "level1/ref_axpyf.h"
namespace testinghelpers {
float bli_cpyscal(conj_t conjx, float *chi1, float *alpha )
{
float alpha_chi1;
bli_scopycjs( conjx, *chi1, alpha_chi1 );
bli_sscals( *alpha, alpha_chi1 );
return alpha_chi1;
}
double bli_cpyscal(conj_t conjx, double *chi1, double *alpha )
{
double alpha_chi1;
bli_dcopycjs( conjx, *chi1, alpha_chi1 );
bli_dscals( *alpha, alpha_chi1 );
return alpha_chi1;
}
scomplex bli_cpyscal(conj_t conjx, scomplex *chi1, scomplex *alpha )
{
scomplex alpha_chi1;
bli_ccopycjs( conjx, *chi1, alpha_chi1 );
bli_cscals( *alpha, alpha_chi1 );
return alpha_chi1;
}
dcomplex bli_cpyscal(conj_t conjx, dcomplex *chi1, dcomplex *alpha )
{
dcomplex alpha_chi1;
bli_zcopycjs( conjx, *chi1, alpha_chi1 );
bli_zscals( *alpha, alpha_chi1 );
return alpha_chi1;
}
template<typename T>
void ref_axpyf( conj_t conja,
conj_t conjx,
gint_t m,
gint_t b,
T *alpha,
T* A,
gint_t inca,
gint_t lda,
T* x,
gint_t incx,
T* y,
gint_t incy
)
{
for (gint_t i = 0; i < b; ++i )
{
T* a1 = A + (0 )*inca + (i )*lda;
T* chi1 = x + (i )*incx;
T* y1 = y + (0 )*incy;
T alpha_chi1 = bli_cpyscal( conjx, chi1, alpha );
testinghelpers::ref_axpyv<T>( conja, m, alpha_chi1, a1, inca, y1, incy );
}
}
template void ref_axpyf<float>(
conj_t conja,
conj_t conjx,
gint_t m,
gint_t b,
float *alpha,
float* A,
gint_t inca,
gint_t lda,
float* x,
gint_t incx,
float* y,
gint_t incy
);
template void ref_axpyf<double>(
conj_t conja,
conj_t conjx,
gint_t m,
gint_t b,
double *alpha,
double* A,
gint_t inca,
gint_t lda,
double* x,
gint_t incx,
double* y,
gint_t incy
);
template void ref_axpyf<scomplex>(
conj_t conja,
conj_t conjx,
gint_t m,
gint_t b,
scomplex *alpha,
scomplex* A,
gint_t inca,
gint_t lda,
scomplex* x,
gint_t incx,
scomplex* y,
gint_t incy
);
template void ref_axpyf<dcomplex>(
conj_t conja,
conj_t conjx,
gint_t m,
gint_t b,
dcomplex *alpha,
dcomplex* A,
gint_t inca,
gint_t lda,
dcomplex* x,
gint_t incx,
dcomplex* y,
gint_t incy
);
}

View File

@@ -0,0 +1,113 @@
/*
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.
*/
#pragma once
#include "blis.h"
#include "common/testing_helpers.h"
template<typename T>
static void typed_axpyf(
conj_t conja,
conj_t conjx,
gint_t m,
gint_t b,
T *alpha,
T* A,
gint_t inca,
gint_t lda,
T* x,
gint_t incx,
T* y,
gint_t incy)
{
conj_t conj_a;
conj_t conj_x;
// Map parameter characters to BLIS constants.
testinghelpers::char_to_blis_conj( conja, &conj_a );
testinghelpers::char_to_blis_conj( conjx, &conj_x );
if constexpr (std::is_same<T, float>::value)
bli_saxpyf(conj_a, conj_x, m, b, alpha, A, inca, lda, x, incx, y, incy);
else if constexpr (std::is_same<T, double>::value)
bli_daxpyf( conj_a, conj_x, m, b, alpha, A, inca, lda, x, incx, y, incy );
else if constexpr (std::is_same<T, scomplex>::value)
bli_caxpyf( conj_a, conj_x, m, b, alpha, A, inca, lda, x, incx, y, incy );
else if constexpr (std::is_same<T, dcomplex>::value)
bli_zaxpyf( conj_a, conj_x, m, b, alpha, A, inca, lda, x, incx, y, incy );
else
throw std::runtime_error("Error in testsuite/level1/axpyv.h: Invalid typename in typed_axpyv().");
}
template<typename T>
static void axpyf(
conj_t conja,
conj_t conjx,
gint_t m,
gint_t b,
T *alpha,
T* A,
gint_t inca,
gint_t lda,
T* x,
gint_t incx,
T* y,
gint_t incy
)
{
#ifdef TEST_UPPERCASE_ARGS
conja = static_cast<char>(std::toupper(static_cast<unsigned char>(conja)));
conjx = static_cast<char>(std::toupper(static_cast<unsigned char>(conjx)));
#endif
/**
* axpyf operation is defined as :
* y := y + alpha * conja(A) * conjx(x)
* where A is an m x b matrix, and y and x are vectors.
* Matrix should be represented as "A" instead of "a" to distinguish it from vector.
*/
typed_axpyf<T>(
conja,
conjx,
m,
b,
alpha,
A,
inca,
lda,
x,
incx,
y,
incy );
}

View File

@@ -0,0 +1,134 @@
/*
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_axpyf.h"
class daxpyfGenericTest :
public ::testing::TestWithParam<std::tuple<char, // conjx
char, // conja
gtint_t, // m
gtint_t, // b
double, // alpha
gtint_t, // inca
gtint_t, // lda
gtint_t, // incx
gtint_t // incy
>> {};
// Tests using random integers as vector elements.
TEST_P( daxpyfGenericTest, FunctionalTest )
{
using T = double;
//----------------------------------------------------------
// Initialize values from the parameters passed through
// test suite instantiation (INSTANTIATE_TEST_SUITE_P).
//----------------------------------------------------------
// denotes whether x or conj(x) will be added to y:
char conj_x = std::get<0>(GetParam());
conj_t conjx;
testinghelpers::char_to_blis_conj( conj_x, &conjx );
char conj_a = std::get<1>(GetParam());
conj_t conja;
testinghelpers::char_to_blis_conj( conj_a, &conja );
gint_t m = std::get<2>(GetParam());
gint_t b = std::get<3>(GetParam());
T alpha = std::get<4>(GetParam());
// stride size for x:
gtint_t inca = std::get<5>(GetParam());
// stride size for y:
gtint_t lda = std::get<6>(GetParam());
gtint_t incx = std::get<7>(GetParam());
gtint_t incy = std::get<8>(GetParam());
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
test_axpyf<T>( conjx, conja, m, b, &alpha, inca, lda, incx, incy );
}
// Test-case logger : Used to print the test-case details
class daxpyfGenericTestPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<char,
char,
gtint_t,
gtint_t,
double,
gtint_t,
gtint_t,
gtint_t,
gtint_t>> str) const {
char conja = std::get<0>(str.param);
char conjx = std::get<1>(str.param);
gtint_t m = std::get<2>(str.param);
gtint_t b = std::get<3>(str.param);
double alpha = std::get<4>(str.param);
gtint_t incx = std::get<7>(str.param);
gtint_t incy = std::get<8>(str.param);
std::string str_name = "bli_";
str_name += ( conja == 'n' )? "_conja_n" : "_conja_t";
str_name += ( conjx == 'n' )? "_conjx_n" : "_conjx_t";
str_name += "_m" + std::to_string(m);
str_name += "_b" + std::to_string(b);
std::string alpha_str = ( alpha >= 0) ? std::to_string(int(alpha)) : "m" + std::to_string(int(std::abs(alpha)));
str_name = str_name + "_alpha" + alpha_str;
std::string incx_str = ( incx >= 0) ? std::to_string(incx) : "m" + std::to_string(std::abs(incx));
str_name += "_incx" + incx_str;
std::string incy_str = ( incy >= 0) ? std::to_string(incy) : "m" + std::to_string(std::abs(incy));
str_name += "_incy" + incy_str;
return str_name;
}
};
// Black box testing for generic and main use of daxpy.
INSTANTIATE_TEST_SUITE_P(
FunctionalTest,
daxpyfGenericTest,
::testing::Combine(
::testing::Values('n'), // n: use x, not conj(x) (since it is real)
::testing::Values('n'), // n: use x, not conj(x) (since it is real)
::testing::Range(gtint_t(10), gtint_t(101), 10), // m size of matrix
::testing::Range(gtint_t(6), gtint_t(10), 1), // b size of matrix
::testing::Values(double(0.0), double(1.0), double(2.3)), // alpha
::testing::Values(gtint_t(0)), // lda increament
::testing::Values(gtint_t(1)), // stride size for a
::testing::Values(gtint_t(1)), // stride size for x
::testing::Values(gtint_t(1)) // stride size for y
),
::daxpyfGenericTestPrint()
);

View File

@@ -0,0 +1,93 @@
/*
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.
*/
#pragma once
#include "axpyf.h"
#include "level1/ref_axpyf.h"
#include "inc/check_error.h"
/**
* axpyf operation is defined as :
* y := y + alpha * conja(A) * conjx(x)
* where A is an m x b matrix, and y and x are vectors.
* Matrix should be represented as "A" instead of "a" to distinguish it from vector.
*/
template<typename T>
static void test_axpyf(
conj_t conja,
conj_t conjx,
gint_t m,
gint_t b,
T *alpha,
gint_t inca,
gint_t lda_inc,
gint_t incx,
gint_t incy
)
{
//----------------------------------------------------------
// Initialize vectors with random numbers.
//----------------------------------------------------------
// Compute the leading dimensions of A matrix.
gtint_t lda = testinghelpers::get_leading_dimension( 'c', 'n', m, b, lda_inc );
//----------------------------------------------------------
// Initialize matrics with random numbers
//----------------------------------------------------------
std::vector<T> A = testinghelpers::get_random_matrix<T>( -2, 8, 'c', 'n', m, b, lda );
std::vector<T> x = testinghelpers::get_random_vector<T>( -10, 10, m, incx );
std::vector<T> y = testinghelpers::get_random_vector<T>( -10, 10, m, incy );
//----------------------------------------------------------
// Call reference implementation to get ref results.
//----------------------------------------------------------
// Create a copy of y so that we can check reference results.
std::vector<T> y_ref(y);
// conj_t, conj_t, long, long, double, double*, long, long, double*, long, double*, long)
testinghelpers::ref_axpyf<T>( conja, conjx, m, b, alpha, A.data(), inca, lda, x.data(), incx, y_ref.data(), incy );
//----------------------------------------------------------
// Call BLIS function.
//----------------------------------------------------------
axpyf<T>( conja, conjx, m, b, alpha, A.data(), inca, lda, x.data(), incx, y.data(), incy );
//---------------------------------------------------------
// Compute component-wise error.
//----------------------------------------------------------
double thresh = testinghelpers::getEpsilon<T>();
computediff<T>( m, y.data(), y_ref.data(), incy, thresh, true );
}