-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add functionality to print hashes and computed errors in tests #778
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -263,6 +263,8 @@ void sygvx_hegvx_initData(const rocblas_handle handle, | |
// for testing purposes, we start with a reduced matrix M for the standard equivalent problem | ||
// with spectrum in a desired range (-20, 20). Then we construct the generalized pair | ||
// (A, B) from there. | ||
|
||
[[maybe_unused]] volatile auto mptr = memset(hB[b], 0, n * ldb * sizeof(T)); | ||
for(rocblas_int i = 0; i < n; i++) | ||
{ | ||
// scale matrices and set hA = M (symmetric/hermitian), hB = U (upper triangular) | ||
|
@@ -424,6 +426,16 @@ void sygvx_hegvx_getError(const rocblas_handle handle, | |
sygvx_hegvx_initData<true, true, T>(handle, itype, evect, n, dA, lda, stA, dB, ldb, stB, bc, hA, | ||
hB, A, B, true, singular); | ||
|
||
// | ||
// Compute input data hash (combine matrices A and B) | ||
// | ||
std::size_t input_hash = 0; | ||
for(rocblas_int b = 0; b < bc; ++b) | ||
{ | ||
input_hash = hash_combine(input_hash, hA[0], lda * n); | ||
input_hash = hash_combine(input_hash, hB[0], ldb * n); | ||
} | ||
|
||
// execute computations | ||
// GPU lapack | ||
CHECK_ROCBLAS_ERROR(rocsolver_sygvx_hegvx(STRIDED, handle, itype, evect, erange, uplo, n, | ||
|
@@ -472,6 +484,41 @@ void sygvx_hegvx_getError(const rocblas_handle handle, | |
*max_err += 1; | ||
} | ||
|
||
// | ||
// Compute output hashes | ||
// | ||
std::size_t rocsolver_eigenvalues_hash = 0; | ||
std::size_t rocsolver_eigenvectors_hash = 0; | ||
|
||
for(rocblas_int b = 0; b < bc; ++b) | ||
{ | ||
if(hInfo[b][0] == 0) | ||
{ | ||
rocsolver_eigenvalues_hash | ||
= hash_combine(rocsolver_eigenvalues_hash, hWRes[b], hNevRes[b][0]); | ||
|
||
if(evect == rocblas_evect_original) | ||
{ | ||
rocsolver_eigenvectors_hash | ||
= hash_combine(rocsolver_eigenvectors_hash, hZRes[b], hNevRes[b][0] * ldz); | ||
} | ||
} | ||
} | ||
|
||
// | ||
// Print hashes | ||
// | ||
ROCSOLVER_GTEST_MSG_PRINTER << "Input matrix hash: " << input_hash << std::endl << std::flush; | ||
ROCSOLVER_GTEST_MSG_PRINTER << "Rocsolver eigenvalues hash: " << rocsolver_eigenvalues_hash | ||
<< std::endl | ||
<< std::flush; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if(evect == rocblas_evect_original) | ||
{ | ||
ROCSOLVER_GTEST_MSG_PRINTER | ||
<< "Rocsolver eigenvectors hash: " << rocsolver_eigenvectors_hash << std::endl | ||
<< std::flush; | ||
} | ||
|
||
double err; | ||
|
||
for(rocblas_int b = 0; b < bc; ++b) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,8 +51,49 @@ namespace fs = std::experimental::filesystem; | |
#define USE_ROCBLAS_REALLOC_ON_DEMAND true | ||
|
||
#ifdef ROCSOLVER_CLIENTS_TEST | ||
#define ROCSOLVER_TEST_CHECK(T, max_error, tol) ASSERT_LE((max_error), (tol)*get_epsilon<T>()) | ||
|
||
#ifdef ROCSOLVER_CLIENTS_TEST_PRINT_EXTRA_MESSAGES | ||
// Format output similarly as GTEST messages | ||
#define ANSI_CODE_GTEST_GREEN "\033[0;32m" | ||
#define ANSI_CODE_NORMAL_TERM "\033[0;0m" | ||
Comment on lines
+57
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're going to print with colour, we should follow Google Test's lead by obeying the gtest_color option and using TTY detection for the default. I'd suggest printing without colour for now, as that is a bit of a distraction from the main purpose of this change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, the fmtlib that we use in rocsolver has a color API. https://fmt.dev/11.0/api/#color-api |
||
// Macro ROCSOLVER_GTEST_MSG_PRINTER is also used to print hashes in tests | ||
#define ROCSOLVER_GTEST_MSG_PRINTER \ | ||
std::cout << ANSI_CODE_GTEST_GREEN << "[ ] " << ANSI_CODE_NORMAL_TERM | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use fmt. We added it as a dependency to do atomic prints and avoid the iostreams interfaces where the printing of a line may be split into multiple function calls. It's not that important at the moment, but it's an invariant we inherited from rocfft / rocblas and I want to retain it in case we do ever run tests in parallel. |
||
// Print computed errors for all tests, making sure that there are sufficient digits to uniquely | ||
// represent all distinct `double` values. | ||
#define ROCSOLVER_STRNGFY(s) #s | ||
#define ROCSOLVER_PRINT_TEST_ERROR(T, max_error, tol) ROCSOLVER_PRINT_TEST_ERROR2(T, max_error, tol) | ||
#define ROCSOLVER_PRINT_TEST_ERROR2(T, max_error, tol) \ | ||
do \ | ||
{ \ | ||
const auto default_precision{std::cout.precision()}; \ | ||
constexpr auto max_precision{std::numeric_limits<double>::max_digits10 + 1}; \ | ||
double tol_ = static_cast<double>(tol) * static_cast<double>(get_epsilon<T>()); \ | ||
double max_error_ = static_cast<double>(max_error); \ | ||
ROCSOLVER_GTEST_MSG_PRINTER \ | ||
<< "Computed error: " << ROCSOLVER_STRNGFY(max_error) << " / " \ | ||
<< ROCSOLVER_STRNGFY(((tol)*get_epsilon<T>())) << " = " \ | ||
<< std::setprecision(max_precision) \ | ||
<< ((max_error_ >= 0.) && (tol_ > 0.) ? max_error_ / tol_ : -1.) \ | ||
<< std::setprecision(default_precision) << std::endl \ | ||
<< std::flush; \ | ||
Comment on lines
+73
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be so much nicer using the fmtlib interface. |
||
} while(0) | ||
#else // #ifdef ROCSOLVER_CLIENTS_TEST_PRINT_EXTRA_MESSAGES | ||
static std::stringstream rocsolver_discard_tests_extra_messages; | ||
#define ROCSOLVER_GTEST_MSG_PRINTER rocsolver_discard_tests_extra_messages | ||
#define ROCSOLVER_PRINT_TEST_ERROR(T, max_error, tol) | ||
#endif // #ifdef ROCSOLVER_CLIENTS_TEST_PRINT_EXTRA_MESSAGES | ||
|
||
#define ROCSOLVER_TEST_CHECK(T, max_error, tol) \ | ||
do \ | ||
{ \ | ||
ASSERT_LE((max_error), (tol)*get_epsilon<T>()); \ | ||
ROCSOLVER_PRINT_TEST_ERROR(T, max_error, tol); \ | ||
} while(0) | ||
|
||
#else // ROCSOLVER_CLIENTS_BENCH | ||
static std::stringstream rocsolver_discard_tests_extra_messages; | ||
#define ROCSOLVER_GTEST_MSG_PRINTER rocsolver_discard_tests_extra_messages | ||
#define ROCSOLVER_TEST_CHECK(T, max_error, tol) | ||
#endif | ||
|
||
|
@@ -158,3 +199,57 @@ inline std::ostream& operator<<(std::ostream& os, printable_char x) | |
|
||
// location of the sparse data directory for the re-factorization tests | ||
fs::path get_sparse_data_dir(); | ||
|
||
/// Combines `seed` with the hash of `value`, following the spirit of | ||
/// `boost::hash_combine`. | ||
/// | ||
/// Extends `std::hash` to combine the hashes of multiple values (e.g., | ||
/// from an array). | ||
/// | ||
/// Attention: hash_combine(0, T(0)) != 0 | ||
template <typename T> | ||
std::size_t hash_combine(std::size_t seed, T value) | ||
{ | ||
using S = decltype(std::real(T{})); | ||
auto hasher = std::hash<S>(); | ||
|
||
if constexpr(rocblas_is_complex<T>) | ||
{ | ||
seed ^= hasher(std::real(value)) + 0x9e3779b9 + (seed << 6) + (seed >> 2); | ||
seed ^= hasher(std::imag(value)) + 0x9e3779b9 + (seed << 6) + (seed >> 2); | ||
} | ||
else | ||
{ | ||
seed ^= hasher(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2); | ||
} | ||
|
||
return seed; | ||
} | ||
|
||
/// Hash contents of the given array. | ||
/// | ||
/// If seed == 0 and array_size == 0, then hash_combine(seed, _, array_size) == 0 | ||
template <typename T> | ||
std::size_t hash_combine(std::size_t seed, T const* array, std::size_t array_size) | ||
{ | ||
std::size_t hash = 0; | ||
if(array_size > 0) | ||
{ | ||
hash = hash_combine(seed, array_size); | ||
for(std::size_t i = 0; i < array_size; ++i) | ||
{ | ||
hash = hash_combine(hash, array[i]); | ||
} | ||
} | ||
|
||
return hash; | ||
} | ||
|
||
/// Hash contents of the given array. | ||
/// | ||
/// If seed == 0 and array.size() == 0, then hash_combine(seed, array) == 0 | ||
template <typename T> | ||
std::size_t hash_combine(std::size_t seed, const std::vector<T>& array) | ||
{ | ||
return hash_combine(seed, array.data(), array.size()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume the
volatile auto mptr
is an attempt to ensure that memset is not optimized out, but I'm not sure that's guaranteed. Why is this needed?