Skip to content
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

Functionality tests utils dev #203

Draft
wants to merge 49 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
8f3367c
Fix number of digits in test output.
pelesh Oct 5, 2024
347f490
Create a prototype for functionality test helper class.
pelesh Oct 8, 2024
affa478
Set correct norm of the exact solution.
pelesh Oct 15, 2024
c97a4f1
comments from ramp-up meeting
Oct 15, 2024
dfb4d39
default tol for testhelper, condensed 1st section in refactor test
Oct 15, 2024
6609676
initial migration of header to cpp
Oct 16, 2024
478fb07
migrated checkRelativeResidualNorm
Oct 16, 2024
154bf8b
moved over constructors and another function
Oct 16, 2024
ccd0d09
moved over print function
Oct 16, 2024
2a56bd0
moved over final function
Oct 16, 2024
4b439d0
removed extraneous comments
Oct 16, 2024
3a80caf
removed a header
Oct 16, 2024
d5d7692
removed all includes from FunctionalityTestHelper header
Oct 16, 2024
af71d46
added FunctionalityTestHelper to AMD GPU toolchain
Oct 16, 2024
71d92dc
CUDA breaks the CI, turning off
Oct 16, 2024
6aad298
a few style guidelines
Oct 16, 2024
2a2dd55
added cmath...
Oct 16, 2024
eda6049
updated some formatting
Oct 16, 2024
a988879
removed comment
Oct 17, 2024
a6d8414
minor formatting changes, removed comment
Oct 17, 2024
a933508
minor formatting changes
Oct 17, 2024
6e65a4c
creating more functions
Oct 21, 2024
07d1f50
migrated more functionality into shorter functions
Oct 21, 2024
a364dae
moved printing into functions
Oct 21, 2024
6ed75cd
moved a function
Oct 21, 2024
deaaaa8
invoked functions directly in test
Oct 21, 2024
80065e8
formatting - parens, spaces in if-statements, brackets in if statements
Oct 21, 2024
68a497f
missed a couple parens
Oct 21, 2024
9bd2275
addressed PR comments
Oct 22, 2024
119c394
calculate norms before attempting to check...
Oct 22, 2024
b322720
fixed test name
Oct 22, 2024
eab2bf8
fixed a function name
Oct 22, 2024
260d7fb
fixed remaining function names
Oct 22, 2024
f6f0079
fixed comments
Oct 22, 2024
51ef0fb
testhelper no longer owns the workspace
Oct 29, 2024
1ef2724
comment
Oct 29, 2024
671f5e6
re-ordered code blocks
Oct 29, 2024
f826911
empty shell for new class
Oct 29, 2024
96eaeaa
created a memory leak
Oct 29, 2024
c418cfd
intermediate state: axb problem constructed, not hooked into test yet
Oct 29, 2024
055d389
added axb problem class to test file with updateProblem() functionali…
Oct 29, 2024
60b1cd6
cleaned up comments
Oct 29, 2024
f47d914
pass problem object to calculateNorms instead of individual items
Oct 30, 2024
41eb33a
notes for phase II refactor
Oct 30, 2024
212e9ce
set C++ version to 14, use unique_ptrs for handlers
Oct 31, 2024
157c296
add some const correctness, break up long function into more files
Oct 31, 2024
6aa2ae0
fixed small bug
Oct 31, 2024
9dc1fa4
updated comment
Nov 1, 2024
1c1a2b5
Minor cleanup in functionality test helper.
pelesh Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions tests/functionality/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

]]

# Create functionality test helper
add_library(FunctionalityTestHelper SHARED FunctionalityTestHelper.cpp)
target_link_libraries(FunctionalityTestHelper PRIVATE ReSolve)

# Build basic version test
add_executable(version.exe testVersion.cpp)
target_link_libraries(version.exe PRIVATE ReSolve)
Expand Down Expand Up @@ -38,7 +42,7 @@ if(RESOLVE_USE_CUDA)

# System solver test with cusolver rf and iterative refinement
add_executable(sys_refactor_cuda_test.exe testSysRefactor.cpp)
target_link_libraries(sys_refactor_cuda_test.exe PRIVATE ReSolve)
target_link_libraries(sys_refactor_cuda_test.exe PRIVATE ReSolve FunctionalityTestHelper)

# Build KLU+GLU test
add_executable(klu_glu_test.exe testKLU_GLU.cpp)
Expand Down Expand Up @@ -69,7 +73,7 @@ if(RESOLVE_USE_HIP)

# System solver test with rocm rf and iterative refinement
add_executable(sys_refactor_hip_test.exe testSysRefactor.cpp)
target_link_libraries(sys_refactor_hip_test.exe PRIVATE ReSolve)
target_link_libraries(sys_refactor_hip_test.exe PRIVATE ReSolve FunctionalityTestHelper )
endif(RESOLVE_USE_KLU)

# Build randSolver test
Expand Down
328 changes: 328 additions & 0 deletions tests/functionality/FunctionalityTestHelper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>

#include <resolve/vector/Vector.hpp>
#include <resolve/matrix/io.hpp>
#include <resolve/matrix/Coo.hpp>
#include <resolve/matrix/Csr.hpp>
#include <resolve/matrix/Csc.hpp>
#include <resolve/matrix/MatrixHandler.hpp>
#include <resolve/vector/VectorHandler.hpp>
#include "resolve/Common.hpp"
#include <resolve/LinSolverIterativeFGMRES.hpp>
#include <resolve/workspace/LinAlgWorkspace.hpp>
#include <resolve/SystemSolver.hpp>
#if defined RESOLVE_USE_KLU
#include <resolve/LinSolverDirectKLU.hpp>
#endif
#if defined (RESOLVE_USE_CUDA)
#include <resolve/LinSolverDirectCuSolverRf.hpp>
using workspace_type = ReSolve::LinAlgWorkspaceCUDA;
std::string memory_space("cuda");
#elif defined (RESOLVE_USE_HIP)
#include <resolve/LinSolverDirectRocSolverRf.hpp>
using workspace_type = ReSolve::LinAlgWorkspaceHIP;
std::string memory_space("hip");
#else
using workspace_type = ReSolve::LinAlgWorkspaceCpu;
std::string memory_space("cpu");
#endif
#include "FunctionalityTestHelper.hpp"

namespace ReSolve
{

namespace tests
{

real_type FunctionalityTestHelper::
calculate_solution_vector_norm(ReSolve::vector::Vector& vec_x)
{
using namespace memory;

// set member variable and also return in case this function is used outside of this class
norm_solution_vector_ = sqrt(vh_->dot(&vec_x, &vec_x, DEVICE));

return norm_solution_vector_;
}

real_type FunctionalityTestHelper::
calculate_rhs_vector_norm(ReSolve::vector::Vector& vec_rhs)
{
using namespace memory;

// set member variable and also return in case this function is used outside of this class
rhs_norm_ = sqrt(vh_->dot(&vec_rhs, &vec_rhs, DEVICE));

return rhs_norm_;
}

real_type FunctionalityTestHelper::
calculate_residual_norm(ReSolve::vector::Vector& vec_r)
{
using namespace memory;

// set member variable and also return in case this function is used outside of this class
residual_norm_ = sqrt(vh_->dot(&vec_r, &vec_r, DEVICE));

return residual_norm_;
}

real_type FunctionalityTestHelper::
calculate_diff_norm(ReSolve::matrix::Csr& A, ReSolve::vector::Vector& vec_x)
{
using namespace memory;
using namespace ReSolve::constants;

index_type n = A.getNumRows();

ReSolve::vector::Vector vec_diff(n);

vec_diff.setToConst(1.0, DEVICE);

// why does this not return an error status if it fails?
vh_->axpy(&MINUSONE, &vec_x, &vec_diff, DEVICE);

diff_norm_ = sqrt(vh_->dot(&vec_diff, &vec_diff, DEVICE));

return diff_norm_;
}

real_type FunctionalityTestHelper::
calculate_true_norm(ReSolve::matrix::Csr& A, ReSolve::vector::Vector& vec_rhs)
{
using namespace memory;
using namespace ReSolve::constants;

index_type n = A.getNumRows();

ReSolve::vector::Vector vec_test(n);
ReSolve::vector::Vector vec_tmp(n);

//compute the residual using exact solution
vec_test.setToConst(1.0, DEVICE);
vec_tmp.update(vec_rhs.getData(HOST), HOST, DEVICE);
int status = mh_->matvec(&A, &vec_test, &vec_tmp, &ONE, &MINUSONE, DEVICE);

if (status != 0) {
std::cout << "matvec failed" << std::endl;

std::exit( status );
}

true_residual_norm_ = sqrt(vh_->dot(&vec_tmp, &vec_tmp, DEVICE));

return true_residual_norm_;
}

ReSolve::vector::Vector FunctionalityTestHelper::
generate_residual_vector(ReSolve::matrix::Csr& A,
ReSolve::vector::Vector& vec_x,
ReSolve::vector::Vector& vec_rhs)
{
using namespace memory;
using namespace ReSolve::constants;

index_type n = A.getNumRows();

ReSolve::vector::Vector vec_r(n);

vec_r.update(vec_rhs.getData(HOST), HOST, DEVICE);

mh_->setValuesChanged(true, DEVICE);

int status = mh_->matvec(&A, &vec_x, &vec_r, &ONE, &MINUSONE, DEVICE);

if (status != 0) {
std::cout << "matvec from matrixhandler failed" << std::endl;

std::exit(status);
}

return vec_r;
}

void FunctionalityTestHelper::printNorms(std::string &testname)
{
std::cout << "Results for " << testname << ":\n\n";

std::cout << std::scientific << std::setprecision(16);

std::cout << "\t ||b-A*x||_2 : "
<< residual_norm_
<< " (residual norm)\n";

std::cout << "\t ||b-A*x||_2/||b||_2 : "
<< residual_norm_/rhs_norm_
<< " (relative residual norm)\n";

std::cout << "\t ||x-x_true||_2 : "
<< diff_norm_
<< " (solution error)\n";

std::cout << "\t ||x-x_true||_2/||x_true||_2 : "
<< diff_norm_/norm_solution_vector_
<< " (relative solution error)\n";

std::cout << "\t ||b-A*x_exact||_2 : "
<< true_residual_norm_
<< " (control; residual norm with exact solution)\n";
}

int FunctionalityTestHelper::checkResidualNorm()
{
int error_sum = 0;

if (!std::isfinite(residual_norm_/rhs_norm_)) {
std::cout << "Result is not a finite number!\n";
error_sum++;
}

if (residual_norm_/rhs_norm_ > tol_) {
std::cout << "Result inaccurate!\n";
error_sum++;
}

return error_sum;
}

int FunctionalityTestHelper::checkResultNorms(ReSolve::matrix::Csr& A,
ReSolve::vector::Vector& vec_rhs,
ReSolve::vector::Vector& vec_x,
ReSolve::SystemSolver& solver,
std::string testname)
{
using namespace memory;
using namespace ReSolve::constants;

int status = 0;
int error_sum = 0;

calculate_solution_vector_norm(vec_x);

// Compute residual norm for the second system
ReSolve::vector::Vector vec_r = generate_residual_vector(A, vec_x, vec_rhs);

calculate_residual_norm(vec_r);

//for testing only - control
calculate_rhs_vector_norm(vec_rhs);

//compute ||x_diff|| = ||x - x_true|| norm
calculate_diff_norm(A, vec_x);

calculate_true_norm(A, vec_rhs);

printNorms(testname);

printIterativeSolverStats(solver);

error_sum += checkResidualNorm();

return error_sum;
}

FunctionalityTestHelper::FunctionalityTestHelper(
ReSolve::real_type tol_init)
:
tol_(tol_init)
{
workspace_.initializeHandles();

mh_ = new ReSolve::MatrixHandler(&workspace_);

vh_ = new ReSolve::VectorHandler(&workspace_);
}

FunctionalityTestHelper::~FunctionalityTestHelper()
{
delete mh_;

delete vh_;
}

void FunctionalityTestHelper::printIterativeSolverStats(SystemSolver& solver)
{
// Get solver parameters
real_type tol = solver.getIterativeSolver().getTol();
index_type restart = solver.getIterativeSolver().getRestart();
index_type maxit = solver.getIterativeSolver().getMaxit();

// note: these are the solver's tolerance, different from the testhelper's tolerance

// Get solver stats
index_type num_iter = solver.getIterativeSolver().getNumIter();
real_type init_rnorm = solver.getIterativeSolver().getInitResidualNorm();
real_type final_rnorm = solver.getIterativeSolver().getFinalResidualNorm();

std::cout << "\t IR iterations : " << num_iter << " (max " << maxit << ", restart " << restart << ")\n";
std::cout << "\t IR starting res. norm : " << init_rnorm << "\n";
std::cout << "\t IR final res. norm : " << final_rnorm << " (tol " << std::setprecision(2) << tol << ")\n\n";
}

int FunctionalityTestHelper::checkNormOfScaledResiduals(ReSolve::matrix::Csr& A,
ReSolve::vector::Vector& vec_rhs,
ReSolve::vector::Vector& vec_x,
ReSolve::SystemSolver& solver)
{
using namespace ReSolve::constants;
using namespace memory;
int error_sum = 0;

// Compute residual norm for the second system
ReSolve::vector::Vector vec_r = generate_residual_vector( A, vec_x, vec_rhs );

// Compute norm of scaled residuals for the second system
real_type inf_norm_A = 0.0;
mh_->matrixInfNorm(&A, &inf_norm_A, DEVICE);
real_type inf_norm_x = vh_->infNorm(&vec_x, DEVICE);
real_type inf_norm_r = vh_->infNorm(&vec_r, DEVICE);
real_type nsr_norm = inf_norm_r / (inf_norm_A * inf_norm_x);
real_type nsr_system = solver.getNormOfScaledResiduals(&vec_rhs, &vec_x);
real_type error = std::abs(nsr_system - nsr_norm)/nsr_norm;

if (error > 10.0*std::numeric_limits<real_type>::epsilon()) {
std::cout << "Norm of scaled residuals computation failed:\n";
std::cout << std::scientific << std::setprecision(16)
<< "\tMatrix inf norm : " << inf_norm_A << "\n"
<< "\tResidual inf norm : " << inf_norm_r << "\n"
<< "\tSolution inf norm : " << inf_norm_x << "\n"
<< "\tNorm of scaled residuals : " << nsr_norm << "\n"
<< "\tNorm of scaled residuals (system): " << nsr_system << "\n\n";
error_sum++;
}

return error_sum;
}


int FunctionalityTestHelper::checkRelativeResidualNorm(ReSolve::vector::Vector& vec_rhs,
ReSolve::vector::Vector& vec_x,
ReSolve::SystemSolver& solver)
{
using namespace memory;

int error_sum = 0;

real_type rel_residual_norm = solver.getResidualNorm(&vec_rhs, &vec_x);

real_type error = std::abs(rhs_norm_ * rel_residual_norm - residual_norm_)/residual_norm_;

if (error > 10.0*std::numeric_limits<real_type>::epsilon()) {

std::cout << "Relative residual norm computation failed:\n";

std::cout << std::scientific << std::setprecision(16)
<< "\tTest value : " << residual_norm_/rhs_norm_ << "\n"
<< "\tSystemSolver computed : " << rel_residual_norm << "\n\n";

error_sum++;
}

return error_sum;
}

} //namespace tests
} //namespace ReSolve
Loading