From a551148124e47150ee9b7a551bfa2bdd28af96bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Zuzek?= Date: Mon, 14 Jun 2021 15:01:51 +0200 Subject: [PATCH] #9 Tests refactored + CSV output --- .../wiki/sparse/KokkosSparse_nga_bspmv.cpp | 267 +++++++++--------- 1 file changed, 141 insertions(+), 126 deletions(-) diff --git a/example/wiki/sparse/KokkosSparse_nga_bspmv.cpp b/example/wiki/sparse/KokkosSparse_nga_bspmv.cpp index 45ecc1163b..818a4a5a26 100644 --- a/example/wiki/sparse/KokkosSparse_nga_bspmv.cpp +++ b/example/wiki/sparse/KokkosSparse_nga_bspmv.cpp @@ -39,6 +39,10 @@ using MultiVector_Internal = namespace details { +} // namespace details + +namespace test { + const Scalar SC_ONE = Kokkos::ArithTraits::one(); const Scalar SC_ZERO = Kokkos::ArithTraits::zero(); @@ -334,106 +338,56 @@ void compare(const char fOp[], const mtx_t &myMatrix, } } -template -void test_matrix(const mtx_t &myMatrix, const int blockSize, const int repeat) { - const Scalar alpha = details::SC_ONE; - const Scalar beta = details::SC_ZERO; - - auto const numRows = myMatrix.numRows(); - - // - // Use BlockCrsMatrix format - // - bcrs_matrix_t_ myBlockMatrix = to_block_crs_matrix(myMatrix, blockSize); - - double error = 0.0, maxNorm = 0.0; - - // - // Assess y <- A * x - // - compare("N", myMatrix, myBlockMatrix, alpha, beta, error, maxNorm); - - std::cout << " Error BlockCrsMatrix " << error << " maxNorm " << maxNorm - << "\n"; - std::cout << " ------------------------ \n"; - - //--- - - std::chrono::duration dt_crs = - measure("N", myMatrix, alpha, beta, repeat); - - std::cout << " Total time for Crs Mat-Vec " << dt_crs.count() << " Avg. " - << dt_crs.count() / static_cast(repeat); - std::cout << " Flops (mult only) " - << myMatrix.nnz() * static_cast(repeat / dt_crs.count()) - << "\n"; - std::cout << " ------------------------ \n"; - - //--- - std::chrono::duration dt_bcrs = - measure_block("N", myBlockMatrix, alpha, beta, repeat); - - std::cout << " Total time for BlockCrs Mat-Vec " << dt_bcrs.count() - << " Avg. " << dt_bcrs.count() / static_cast(repeat); - std::cout << " Flops (mult only) " - << myMatrix.nnz() * static_cast(repeat / dt_bcrs.count()); - std::cout << "\n"; - // - std::cout << " Ratio = " << dt_bcrs.count() / dt_crs.count(); +template +class TestCase { +public: + using time_t = std::chrono::duration; + + struct RunInfo { + // options + const char *mode = "N"; // N/T/C/H + const Scalar alpha = SC_ONE; + const Scalar beta = SC_ZERO; + // results + double error = 0.0; + double maxNorm = 0.0; + time_t dt_crs; + time_t dt_bcrs; + }; - if (dt_bcrs.count() < dt_crs.count()) { - std::cout << " --- GOOD --- "; - } else { - std::cout << " ((( Not Faster ))) "; +public: + TestCase(std::string name, crs_matrix_t_ myMatrix, + const int blockSize, const int repeat = 1024): + name_(name), + myMatrix_(std::move(myMatrix)), + blockSize_(blockSize), + repeat_(repeat) + { + myBlockMatrix_ = to_block_crs_matrix(myMatrix_, blockSize_); // Use BlockCrsMatrix format } - std::cout << "\n"; - - std::cout << " ======================== \n"; // // Assess y <- A * x // - compare("T", myMatrix, myBlockMatrix, alpha, beta, error, maxNorm); - - std::cout << " Error Transpose BlockCrsMatrix " << error << " maxNorm " - << maxNorm << "\n"; - std::cout << " ------------------------ \n"; - - //--- - - dt_crs = measure("T", myMatrix, alpha, beta, repeat); - - std::cout << " Total time for Crs Mat^T-Vec " << dt_crs.count() << " Avg. " - << dt_crs.count() / static_cast(repeat); - std::cout << " Flops (mult only) " - << myMatrix.nnz() * static_cast(repeat / dt_crs.count()) - << "\n"; - std::cout << " ------------------------ \n"; - - //--- - dt_bcrs = measure_block("T", myBlockMatrix, alpha, beta, repeat); - - std::cout << " Total time for BlockCrs Mat^T-Vec " << dt_bcrs.count() - << " Avg. " << dt_bcrs.count() / static_cast(repeat); - std::cout << " Flops (mult only) " - << myMatrix.nnz() * static_cast(repeat / dt_bcrs.count()); - std::cout << "\n"; - // - std::cout << " Ratio = " << dt_bcrs.count() / dt_crs.count(); - - if (dt_bcrs.count() < dt_crs.count()) { - std::cout << " --- GOOD --- "; - } else { - std::cout << " ((( Not Faster ))) "; + bool execute(RunInfo &run) + { + compare(run.mode, myMatrix_, myBlockMatrix_, run.alpha, run.beta, run.error, run.maxNorm); + run.dt_crs = measure(run.mode, myMatrix_, run.alpha, run.beta, repeat_); + run.dt_bcrs = measure_block(run.mode, myBlockMatrix_, run.alpha, run.beta, repeat_); + return true; } - std::cout << "\n"; - std::cout << " ======================== \n"; -} +// private: + mtx_t myMatrix_; + bmtx_t myBlockMatrix_; // derived + int blockSize_; + int repeat_; + std::string name_; +}; -int test_random(const int repeat = 1024, const int minBlockSize = 1, - const int maxBlockSize = 12) { - int return_value = 0; +template +void test_random(std::vector &samples, const int repeat = 1024, + const int minBlockSize = 1, const int maxBlockSize = 12) { // The mat_structure view is used to generate a matrix using // finite difference (FD) or finite element (FE) discretization @@ -457,23 +411,18 @@ int test_random(const int repeat = 1024, const int minBlockSize = 1, std::vector mat_rowmap, mat_colidx; std::vector mat_val; - crs_matrix_t_ myMatrix = details::generate_crs_matrix( - "FD", mat_structure, blockSize, mat_rowmap, mat_colidx, mat_val); - - std::cout << " ======================== \n"; - std::cout << " Block Size " << blockSize; - std::cout << " Matrix Size " << myMatrix.numRows() << " nnz " - << myMatrix.nnz() << "\n"; - - test_matrix(myMatrix, blockSize, repeat); + samples.push_back({ + "rand-" + std::to_string(blockSize), + generate_crs_matrix( + "FD", mat_structure, blockSize, mat_rowmap, mat_colidx, mat_val), + blockSize, + repeat + }); } - return return_value; } -int test_samples(const int repeat = 3000) { - int return_value = 0; - - srand(17312837); +template +void test_samples(std::vector &samples, const int repeat = 3000) { const std::vector > SAMPLES{ // std::tuple(char* fileName, int blockSize) @@ -510,36 +459,102 @@ int test_samples(const int repeat = 3000) { }; // Loop over sample matrix files - std::for_each(SAMPLES.begin(), SAMPLES.end(), [=](auto const &sample) { + std::for_each(SAMPLES.begin(), SAMPLES.end(), [&](auto const &sample) { const char *fileName = std::get<0>(sample); - const int blockSize = std::get<1>(sample); - auto myMatrix = - KokkosKernels::Impl::read_kokkos_crst_matrix(fileName); - - std::cout << " ======================== \n"; - std::cout << " Sample: '" << fileName << "', Block Size " << blockSize; - std::cout << " Matrix Size " << myMatrix.numCols() << " x " - << myMatrix.numRows() << ", nnz " << myMatrix.nnz() << "\n"; - - test_matrix(myMatrix, blockSize, repeat); + samples.push_back({ + std::string(fileName), + KokkosKernels::Impl::read_kokkos_crst_matrix(fileName), + std::get<1>(sample), + repeat + }); }); - return return_value; } -} // namespace details +} // namespace test + +class CSVOutput +{ + public: + static constexpr const char* const sep = "\t"; + + void showHeader() { + std::cout << "no." << sep << "name" << sep << "size" << sep << "block" << sep << "nnz" // sample info + << sep << "mode" << sep << "alpha" << sep << "beta" // run info + << sep << "error" << sep << "maxNorm" + << sep << "crsTime" << sep << "crsAvg" << sep << "crsGFlops" + << sep << "bcrsTime" << sep << "bcrsAvg" << sep << "bcrsGFlops" + << sep << "ratio" << sep << "remarks" + << std::endl; + } + + template + void showRunInfo(Test &test, RunInfo &run, id_t sample_id, bool skipSample = false) { + std::cout << sample_id << sep; + if (skipSample) + std::cout << sep << "^" << sep << "^" << sep << "^" << sep << "^"; + else + std::cout << sep << test.name_ << sep << test.myMatrix_.numRows() + << sep << test.blockSize_ << sep << test.myMatrix_.nnz(); + std::cout << sep << run.mode << sep << run.alpha << sep << run.beta; + } -//#define TEST_RANDOM_BSPMV + template + void showRunResults(Test &test, RunInfo &run) { + std::cout << sep << run.error << sep << run.maxNorm; + auto const nnz = test.myMatrix_.nnz(); + showTime(run.dt_crs, nnz, test.repeat_); + showTime(run.dt_bcrs, nnz, test.repeat_); + auto const remarks = (run.dt_bcrs.count() < run.dt_crs.count()) ? "good" : "NOT_faster"; + std::cout << sep << (run.dt_bcrs.count() / run.dt_crs.count()) << sep << remarks; + std::cout << std::endl; + } + +private: + template + void showTime(const time_t &t, ord_t nnz, int repeat) { + auto const avg = (t.count() / static_cast(repeat)); + auto const flops = nnz * static_cast(repeat / t.count()); + std::cout << sep <; + std::vector samples; + test::test_random(samples); + test::test_samples(samples); + + // Prepare variants + std::vector variants; + variants.push_back({"N"}); + variants.push_back({"T"}); + + // Run samples + int sample_id = 0; + CSVOutput out; + out.showHeader(); + std::for_each(samples.begin(), samples.end(), [&](test_t &test) { + sample_id += 1; + int variant_id = 0; + std::for_each(variants.begin(), variants.end(), [&](test_t::RunInfo &run) { + ++variant_id; + auto const label = std::to_string(sample_id) + + ":" + std::to_string(variant_id) + + "/" + std::to_string(samples.size()); + out.showRunInfo(test, run, label, 1 != variant_id); + bool pass = test.execute(run); + failed = failed || !pass; + out.showRunResults(test, run); + }); + }); + } Kokkos::finalize(); - - return return_value; + return failed ? 1 : 0; } \ No newline at end of file