From f10d6eced64f2877be7dd9693c26a874274dfdc2 Mon Sep 17 00:00:00 2001 From: Harsh Dave Date: Thu, 7 Mar 2024 23:06:31 +0530 Subject: [PATCH] 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 --- .../testinghelpers/inc/level1/ref_axpyf.h | 64 +++++++ .../testinghelpers/src/level1/ref_axpyf.cpp | 162 ++++++++++++++++++ gtestsuite/testsuite/level1/axpyf/axpyf.h | 113 ++++++++++++ .../testsuite/level1/axpyf/daxpyf_generic.cpp | 134 +++++++++++++++ .../testsuite/level1/axpyf/test_axpyf.h | 93 ++++++++++ 5 files changed, 566 insertions(+) create mode 100644 gtestsuite/testinghelpers/inc/level1/ref_axpyf.h create mode 100644 gtestsuite/testinghelpers/src/level1/ref_axpyf.cpp create mode 100644 gtestsuite/testsuite/level1/axpyf/axpyf.h create mode 100644 gtestsuite/testsuite/level1/axpyf/daxpyf_generic.cpp create mode 100644 gtestsuite/testsuite/level1/axpyf/test_axpyf.h diff --git a/gtestsuite/testinghelpers/inc/level1/ref_axpyf.h b/gtestsuite/testinghelpers/inc/level1/ref_axpyf.h new file mode 100644 index 000000000..c9fd6197e --- /dev/null +++ b/gtestsuite/testinghelpers/inc/level1/ref_axpyf.h @@ -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 +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 diff --git a/gtestsuite/testinghelpers/src/level1/ref_axpyf.cpp b/gtestsuite/testinghelpers/src/level1/ref_axpyf.cpp new file mode 100644 index 000000000..cb53f9f35 --- /dev/null +++ b/gtestsuite/testinghelpers/src/level1/ref_axpyf.cpp @@ -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 +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( conja, m, alpha_chi1, a1, inca, y1, incy ); + } + } + +template void ref_axpyf( + 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( + 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( + 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( + 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 + ); +} + + diff --git a/gtestsuite/testsuite/level1/axpyf/axpyf.h b/gtestsuite/testsuite/level1/axpyf/axpyf.h new file mode 100644 index 000000000..1c14ee165 --- /dev/null +++ b/gtestsuite/testsuite/level1/axpyf/axpyf.h @@ -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 +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::value) + bli_saxpyf(conj_a, conj_x, m, b, alpha, A, inca, lda, x, incx, y, incy); + else if constexpr (std::is_same::value) + bli_daxpyf( conj_a, conj_x, m, b, alpha, A, inca, lda, x, incx, y, incy ); + else if constexpr (std::is_same::value) + bli_caxpyf( conj_a, conj_x, m, b, alpha, A, inca, lda, x, incx, y, incy ); + else if constexpr (std::is_same::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 +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(std::toupper(static_cast(conja))); + conjx = static_cast(std::toupper(static_cast(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( + conja, + conjx, + m, + b, + alpha, + A, + inca, + lda, + x, + incx, + y, + incy ); +} diff --git a/gtestsuite/testsuite/level1/axpyf/daxpyf_generic.cpp b/gtestsuite/testsuite/level1/axpyf/daxpyf_generic.cpp new file mode 100644 index 000000000..1f1b2d399 --- /dev/null +++ b/gtestsuite/testsuite/level1/axpyf/daxpyf_generic.cpp @@ -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 +#include "test_axpyf.h" + +class daxpyfGenericTest : + public ::testing::TestWithParam> {}; +// 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( 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> 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() + ); + diff --git a/gtestsuite/testsuite/level1/axpyf/test_axpyf.h b/gtestsuite/testsuite/level1/axpyf/test_axpyf.h new file mode 100644 index 000000000..8e6c09d6d --- /dev/null +++ b/gtestsuite/testsuite/level1/axpyf/test_axpyf.h @@ -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 +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 A = testinghelpers::get_random_matrix( -2, 8, 'c', 'n', m, b, lda ); + + std::vector x = testinghelpers::get_random_vector( -10, 10, m, incx ); + std::vector y = testinghelpers::get_random_vector( -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 y_ref(y); + // conj_t, conj_t, long, long, double, double*, long, long, double*, long, double*, long) + testinghelpers::ref_axpyf( conja, conjx, m, b, alpha, A.data(), inca, lda, x.data(), incx, y_ref.data(), incy ); + + //---------------------------------------------------------- + // Call BLIS function. + //---------------------------------------------------------- + axpyf( conja, conjx, m, b, alpha, A.data(), inca, lda, x.data(), incx, y.data(), incy ); + + //--------------------------------------------------------- + // Compute component-wise error. + //---------------------------------------------------------- + double thresh = testinghelpers::getEpsilon(); + computediff( m, y.data(), y_ref.data(), incy, thresh, true ); +}