Memory Tests for DDOTV kernels

- Utilized the memory testing feature in gtestsuite to add memory tests
  for DDOTV micro-kernels.

- Updated the test fixtures, loggers and instantiators to use the new
  testing interface for memory testing.

- Use --gtest_filter="*mem_test_disabled*" to disable memory tests or
  --gtest_filter="*mem_test_enabled" to run only memory tests.

AMD-Internal: [CPUPL-4406]
Change-Id: I887a89f33ca43e504479702263b6c66ddd7937de
This commit is contained in:
Arnav Sharma
2024-02-21 17:13:09 +05:30
committed by Arnav Sharma
parent 14ae6c78dd
commit 0b9e0ca31c
2 changed files with 99 additions and 51 deletions

View File

@@ -36,17 +36,18 @@
#include "test_dotv_ukr.h"
class ddotvUkrTest :
public ::testing::TestWithParam<std::tuple<ddotv_ker_ft,
char,
char,
gtint_t,
gtint_t,
gtint_t>> {};
public ::testing::TestWithParam<std::tuple<ddotv_ker_ft, // Function pointer for ddotv kernels
char, // conjx
char, // conjy
gtint_t, // n
gtint_t, // incx
gtint_t, // incy
bool>> {}; // is_memory_test
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ddotvUkrTest);
// Tests using random integers as vector elements.
TEST_P( ddotvUkrTest, RandomData )
TEST_P( ddotvUkrTest, FunctionalTest )
{
using T = double;
//----------------------------------------------------------
@@ -65,6 +66,8 @@ TEST_P( ddotvUkrTest, RandomData )
gtint_t incx = std::get<4>(GetParam());
// stride size for y:
gtint_t incy = std::get<5>(GetParam());
// enable/disable memory test:
bool is_memory_test = std::get<6>(GetParam());
// Set the threshold for the errors:
double thresh = n*testinghelpers::getEpsilon<T>();
@@ -72,7 +75,7 @@ TEST_P( ddotvUkrTest, RandomData )
//----------------------------------------------------------
// Call generic test body using those parameters
//----------------------------------------------------------
test_dotv_ukr<T>( ukr, conjx, conjy, n, incx, incy, thresh );
test_dotv_ukr<T>( ukr, conjx, conjy, n, incx, incy, thresh, is_memory_test );
}
// Used to generate a test case with a sensible name.
@@ -82,21 +85,23 @@ TEST_P( ddotvUkrTest, RandomData )
class ddotvUkrTestPrint {
public:
std::string operator()(
testing::TestParamInfo<std::tuple<ddotv_ker_ft,char,char,gtint_t,gtint_t,gtint_t>> str) const {
testing::TestParamInfo<std::tuple<ddotv_ker_ft,char,char,gtint_t,gtint_t,gtint_t, bool>> str) const {
char conjx = std::get<1>(str.param);
char conjy = std::get<2>(str.param);
gtint_t n = std::get<3>(str.param);
gtint_t incx = std::get<4>(str.param);
gtint_t incy = std::get<5>(str.param);
bool is_memory_test = std::get<6>(str.param);
std::string str_name = "ddotvUkrTest";
str_name += "_" + std::to_string(n);
str_name += "_" + std::string(&conjx, 1);
str_name += "_" + std::string(&conjy, 1);
std::string str_name = "ddotvUkr_";
str_name += "n_" + std::to_string(n);
str_name += "conjx_" + std::string(&conjx, 1);
str_name += "conjy_" + std::string(&conjy, 1);
std::string incx_str = ( incx > 0) ? std::to_string(incx) : "m" + std::to_string(std::abs(incx));
str_name += "_" + incx_str;
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_str;
str_name += "incy_" + incy_str;
str_name += ( is_memory_test ) ? "_mem_test_enabled" : "_mem_test_disabled";
return str_name;
}
@@ -142,7 +147,9 @@ INSTANTIATE_TEST_SUITE_P(
// incy: stride of y vector.
::testing::Values(
gtint_t(1) // unit stride
)
),
// is_memory_test: enable/disable memory tests
::testing::Values( false, true )
),
::ddotvUkrTestPrint()
);
@@ -167,7 +174,9 @@ INSTANTIATE_TEST_SUITE_P(
// incy: stride of y vector.
::testing::Values(
gtint_t(3), gtint_t(7) // few non-unit strides for sanity check
)
),
// is_memory_test: enable/disable memory tests
::testing::Values( false, true )
),
::ddotvUkrTestPrint()
);
@@ -224,7 +233,9 @@ INSTANTIATE_TEST_SUITE_P(
// incy: stride of y vector.
::testing::Values(
gtint_t(1) // unit stride
)
),
// is_memory_test: enable/disable memory tests
::testing::Values( false, true )
),
::ddotvUkrTestPrint()
);
@@ -249,7 +260,9 @@ INSTANTIATE_TEST_SUITE_P(
// incy: stride of y vector.
::testing::Values(
gtint_t(3), gtint_t(7) // few non-unit strides for sanity check
)
),
// is_memory_test: enable/disable memory tests
::testing::Values( false, true )
),
::ddotvUkrTestPrint()
);
@@ -309,7 +322,9 @@ INSTANTIATE_TEST_SUITE_P(
// incy: stride of y vector.
::testing::Values(
gtint_t(1) // unit stride
)
),
// is_memory_test: enable/disable memory tests
::testing::Values( false, true )
),
::ddotvUkrTestPrint()
);
@@ -334,7 +349,9 @@ INSTANTIATE_TEST_SUITE_P(
// incy: stride of y vector.
::testing::Values(
gtint_t(3), gtint_t(7) // few non-unit strides for sanity check
)
),
// is_memory_test: enable/disable memory tests
::testing::Values( false, true )
),
::ddotvUkrTestPrint()
);

View File

@@ -34,9 +34,11 @@
#pragma once
#include <stdexcept>
#include "level1/dotv/dotv.h"
#include "level1/ref_dotv.h"
#include "inc/check_error.h"
#include "common/testing_helpers.h"
/**
* @brief Microkernel test body for dotv operation.
@@ -44,52 +46,81 @@
template<typename T, typename FT>
static void test_dotv_ukr( FT ukr, char conjx, char conjy, gtint_t n, gtint_t incx,
gtint_t incy, double thresh )
gtint_t incy, double thresh, bool is_memory_test = false )
{
//----------------------------------------------------------
// Initialize vectors with random numbers.
//----------------------------------------------------------
// Obtain and allocate memory for vectors.
T *x, *y, *y_ref;
gtint_t size_x = testinghelpers::buff_dim( n, incx );
gtint_t size_y = testinghelpers::buff_dim( n, incy );
x = ( T* )malloc( sizeof( T ) * size_x );
y = ( T* )malloc( sizeof( T ) * size_y );
y_ref = ( T* )malloc( sizeof( T ) * size_y );
testinghelpers::ProtectedBuffer x_buf( size_x * sizeof( T ), false, is_memory_test );
testinghelpers::ProtectedBuffer y_buf( size_y * sizeof( T ), false, is_memory_test );
// No redzones are required for y_ref buffer thus, we pass is_memory_test = false.
testinghelpers::ProtectedBuffer y_ref_buf( size_y * sizeof( T ), false, false );
// Acquire the first set of greenzones for x and y
x = ( T* )x_buf.greenzone_1;
y = ( T* )y_buf.greenzone_1;
y_ref = ( T* )y_ref_buf.greenzone_1; // For y_ref, there is no greenzone_2
// Initialize the vectors with random data.
testinghelpers::datagenerators::randomgenerators( -10, 10, n, incx, x );
testinghelpers::datagenerators::randomgenerators( -10, 10, n, incy, y );
// Copying y to y_ref, for comparision after computation
for( gtint_t i = 0; i < size_y; i += 1 )
*( y_ref + i ) = *( y + i );
// Copying the contents of y to y_ref, for comparision after computation.
memcpy( y_ref, y, size_y * sizeof( T ) );
//----------------------------------------------------------
// Call reference implementation to get ref results.
//----------------------------------------------------------
// Create a copy of y so that we can check reference results.
T rho;
// Create a copy of rho so that we can check reference results.
T rho_ref;
// conj? conversion to BLIS conjugate type.
conj_t blis_conjx, blis_conjy;
testinghelpers::char_to_blis_conj( conjx, &blis_conjx );
testinghelpers::char_to_blis_conj( conjy, &blis_conjy );
// Add signal handler for Segmentation Faults.
testinghelpers::ProtectedBuffer::start_signal_handler();
try
{
// Invoking BLIS ukr.
// This will check for out of bounds access within first redzone.
ukr( blis_conjx, blis_conjy, n, x, incx, y, incy, &rho, nullptr );
if ( is_memory_test )
{
// Acquire the pointers near the second redzone.
x = ( T* )x_buf.greenzone_2;
y = ( T* )y_buf.greenzone_2;
// Copy the data for x and y accordingly.
memcpy( x, x_buf.greenzone_1, size_x * sizeof( T ) );
memcpy( y, y_ref_buf.greenzone_1, size_y * sizeof( T ) );
// Inoking BLIS ukr to check with the second redzone.
ukr( blis_conjx, blis_conjy, n, x, incx, y, incy, &rho, nullptr );
}
}
catch( const std::exception& e )
{
// Reset to default signal handler.
testinghelpers::ProtectedBuffer::stop_signal_handler();
// Show failure in case Segmentation Fault was detected.
FAIL() << "Memory Test Failed";
}
// Reset to default signal handler.
testinghelpers::ProtectedBuffer::stop_signal_handler();
// Invoking the reference implementation to get reference results.
if constexpr (testinghelpers::type_info<T>::is_real)
testinghelpers::ref_dotv<T>( n, x, incx, y_ref, incy, &rho_ref );
else
testinghelpers::ref_dotv<T>( conjx, conjy, n, x, incx, y_ref, incy, &rho_ref );
//----------------------------------------------------------
// Call BLIS function.
//----------------------------------------------------------
T rho;
conj_t blis_conjx, blis_conjy;
testinghelpers::char_to_blis_conj( conjx, &blis_conjx );
testinghelpers::char_to_blis_conj( conjy, &blis_conjy );
ukr( blis_conjx, blis_conjy, n, x, incx, y, incy, &rho, nullptr );
//----------------------------------------------------------
// Compute error.
//----------------------------------------------------------
// Compute component-wise error.
computediff<T>( rho, rho_ref, thresh );
free( x );
free( y );
free( y_ref );
}