From 707faaf67b6e5c14d69553e3047b8ad6e7bc9edb Mon Sep 17 00:00:00 2001 From: James Sandham <33790278+jsandham@users.noreply.github.com> Date: Thu, 11 Mar 2021 07:06:54 -0800 Subject: [PATCH] Remove boost from benchmarks (#193) * remove boost from benchmarks * fixing memory bugs * allow adding multiple options separated by column * using program_options.hpp from rocBLAS * removing boost as a dependency Co-authored-by: jsandham --- CMakeLists.txt | 2 +- README.md | 3 - clients/CMakeLists.txt | 4 +- clients/benchmarks/CMakeLists.txt | 15 +- clients/benchmarks/client.cpp | 111 +++---- clients/benchmarks/program_options.hpp | 385 +++++++++++++++++++++++++ clients/include/rocsparse_data.hpp | 46 ++- clients/include/testing_spmv.hpp | 13 +- clients/testings/testing_bsrmm.cpp | 13 - clients/tests/CMakeLists.txt | 14 +- docs/source/usermanual.rst | 6 +- 11 files changed, 488 insertions(+), 124 deletions(-) create mode 100644 clients/benchmarks/program_options.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fc7f4b4..406be19f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) # Build options option(BUILD_SHARED_LIBS "Build rocSPARSE as a shared library" ON) option(BUILD_CLIENTS_TESTS "Build tests (requires googletest)" OFF) -option(BUILD_CLIENTS_BENCHMARKS "Build benchmarks (requires boost)" OFF) +option(BUILD_CLIENTS_BENCHMARKS "Build benchmarks" OFF) option(BUILD_CLIENTS_SAMPLES "Build examples" ON) option(BUILD_VERBOSE "Output additional build information" OFF) option(BUILD_CODE_COVERAGE "Build rocSPARSE with code coverage enabled" OFF) diff --git a/README.md b/README.md index 6fd3f830..04579925 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,6 @@ Optional: * Required for tests. * Use GTEST_ROOT to specify GTest location. * If [GTest][] is not found, it will be downloaded and built automatically. -* [Boost][] - * Required for benchmarks. ## Quickstart rocSPARSE build and install @@ -92,7 +90,6 @@ The [license file][] can be found in the main repository. [ROCm]: https://github.com/RadeonOpenCompute/ROCm [HIP]: https://github.com/GPUOpen-ProfessionalCompute-Tools/HIP/ [GTest]: https://github.com/google/googletest -[Boost]: https://www.boost.org/ [the issue tracker]: https://github.com/ROCmSoftwarePlatform/rocSPARSE/issues [license file]: https://github.com/ROCmSoftwarePlatform/rocSPARSE [here]: https://rocsparse.readthedocs.io diff --git a/clients/CMakeLists.txt b/clients/CMakeLists.txt index d3ac7f82..eb5ed227 100644 --- a/clients/CMakeLists.txt +++ b/clients/CMakeLists.txt @@ -1,5 +1,5 @@ # ######################################################################## -# Copyright (c) 2018-2020 Advanced Micro Devices, Inc. +# Copyright (c) 2018-2021 Advanced Micro Devices, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -65,7 +65,7 @@ if(NOT TARGET rocsparse) find_package(rocsparse REQUIRED CONFIG PATHS /opt/rocm/rocsparse) option(BUILD_CLIENTS_TESTS "Build tests (requires googletest)" OFF) - option(BUILD_CLIENTS_BENCHMARKS "Build benchmarks (requires boost)" OFF) + option(BUILD_CLIENTS_BENCHMARKS "Build benchmarks" OFF) option(BUILD_CLIENTS_SAMPLES "Build examples" ON) endif() diff --git a/clients/benchmarks/CMakeLists.txt b/clients/benchmarks/CMakeLists.txt index 9a52f6d3..664625a8 100644 --- a/clients/benchmarks/CMakeLists.txt +++ b/clients/benchmarks/CMakeLists.txt @@ -21,19 +21,6 @@ # # ######################################################################## -set(Boost_USE_MULTITHREADED ON) -set(Boost_DETAILED_FAILURE_MSG ON) -set(Boost_ADDITIONAL_VERSIONS 1.65.1 1.65) -set(Boost_USE_STATIC_LIBS OFF) - -find_package(Boost COMPONENTS program_options) - -if(NOT Boost_FOUND) - message(STATUS "Dynamic boost libraries not found. Attempting to find static libraries...") - set(Boost_USE_STATIC_LIBS ON) - find_package(Boost REQUIRED COMPONENTS program_options) -endif() - set(ROCSPARSE_BENCHMARK_SOURCES client.cpp ) @@ -130,7 +117,7 @@ target_compile_options(rocsparse-bench PRIVATE -Wno-unused-command-line-argument target_include_directories(rocsparse-bench PRIVATE $) # Target link libraries -target_link_libraries(rocsparse-bench PRIVATE Boost::program_options roc::rocsparse hip::host) +target_link_libraries(rocsparse-bench PRIVATE roc::rocsparse hip::host) # Add OpenMP if available if(OPENMP_FOUND) diff --git a/clients/benchmarks/client.cpp b/clients/benchmarks/client.cpp index a0aa9f6c..e6ebf293 100644 --- a/clients/benchmarks/client.cpp +++ b/clients/benchmarks/client.cpp @@ -102,11 +102,11 @@ #include "testing_sparse_to_dense_csc.hpp" #include "testing_sparse_to_dense_csr.hpp" -#include #include #include +#include -namespace po = boost::program_options; +#include "program_options.hpp" int main(int argc, char* argv[]) { @@ -142,128 +142,134 @@ int main(int argc, char* argv[]) rocsparse_int dir; rocsparse_int order; - std::vector laplace(3, 0); - rocsparse_int device_id; - po::options_description desc("rocsparse client command line options"); - desc.add_options()("help,h", "produces this help message") + // clang-format off + + options_description desc("rocsparse client command line options"); + desc.add_options() ("help,h", "produces this help message") // clang-format off ("sizem,m", - po::value(&arg.M)->default_value(128), + value(&arg.M)->default_value(128), "Specific matrix size testing: sizem is only applicable to SPARSE-2 " "& SPARSE-3: the number of rows.") ("sizen,n", - po::value(&arg.N)->default_value(128), + value(&arg.N)->default_value(128), "Specific matrix/vector size testing: SPARSE-1: the length of the " "dense vector. SPARSE-2 & SPARSE-3: the number of columns") ("sizek,k", - po::value(&arg.K)->default_value(128), + value(&arg.K)->default_value(128), "Specific matrix/vector size testing: SPARSE-3: the number of columns") ("sizennz,z", - po::value(&arg.nnz)->default_value(32), + value(&arg.nnz)->default_value(32), "Specific vector size testing, LEVEL-1: the number of non-zero elements " "of the sparse vector.") ("blockdim", - po::value(&arg.block_dim)->default_value(2), + value(&arg.block_dim)->default_value(2), "BSR block dimension (default: 2)") ("row-blockdimA", - po::value(&arg.row_block_dimA)->default_value(2), + value(&arg.row_block_dimA)->default_value(2), "General BSR row block dimension (default: 2)") ("col-blockdimA", - po::value(&arg.col_block_dimA)->default_value(2), + value(&arg.col_block_dimA)->default_value(2), "General BSR col block dimension (default: 2)") ("row-blockdimB", - po::value(&arg.row_block_dimB)->default_value(2), + value(&arg.row_block_dimB)->default_value(2), "General BSR row block dimension (default: 2)") ("col-blockdimB", - po::value(&arg.col_block_dimB)->default_value(2), + value(&arg.col_block_dimB)->default_value(2), "General BSR col block dimension (default: 2)") ("mtx", - po::value(&filename)->default_value(""), "read from matrix " + value(&filename)->default_value(""), "read from matrix " "market (.mtx) format. This will override parameters -m, -n, and -z.") ("rocalution", - po::value(&rocalution)->default_value(""), + value(&rocalution)->default_value(""), "read from rocalution matrix binary file. This will override parameter --mtx") - ("laplacian-dim", - po::value >(&laplace)->multitoken(), "assemble " + ("dimx", + value(&arg.dimx)->default_value(0.0), "assemble " + "laplacian matrix with dimensions . dimz is optional. This " + "will override parameters -m, -n, -z and --mtx.") + + ("dimy", + value(&arg.dimy)->default_value(0.0), "assemble " + "laplacian matrix with dimensions . dimz is optional. This " + "will override parameters -m, -n, -z and --mtx.") + + ("dimz", + value(&arg.dimz)->default_value(0.0), "assemble " "laplacian matrix with dimensions . dimz is optional. This " "will override parameters -m, -n, -z and --mtx.") ("alpha", - po::value(&arg.alpha)->default_value(1.0), "specifies the scalar alpha") + value(&arg.alpha)->default_value(1.0), "specifies the scalar alpha") ("beta", - po::value(&arg.beta)->default_value(0.0), "specifies the scalar beta") + value(&arg.beta)->default_value(0.0), "specifies the scalar beta") ("threshold", - po::value(&arg.threshold)->default_value(1.0), "specifies the scalar threshold") + value(&arg.threshold)->default_value(1.0), "specifies the scalar threshold") ("percentage", - po::value(&arg.percentage)->default_value(0.0), "specifies the scalar percentage") + value(&arg.percentage)->default_value(0.0), "specifies the scalar percentage") ("transposeA", - po::value(&transA)->default_value('N'), + value(&transA)->default_value('N'), "N = no transpose, T = transpose, C = conjugate transpose") ("transposeB", - po::value(&transB)->default_value('N'), + value(&transB)->default_value('N'), "N = no transpose, T = transpose, C = conjugate transpose, (default = N)") ("indexbaseA", - po::value(&baseA)->default_value(0), + value(&baseA)->default_value(0), "0 = zero-based indexing, 1 = one-based indexing, (default: 0)") ("indexbaseB", - po::value(&baseB)->default_value(0), + value(&baseB)->default_value(0), "0 = zero-based indexing, 1 = one-based indexing, (default: 0)") ("indexbaseC", - po::value(&baseC)->default_value(0), + value(&baseC)->default_value(0), "0 = zero-based indexing, 1 = one-based indexing, (default: 0)") ("indexbaseD", - po::value(&baseD)->default_value(0), + value(&baseD)->default_value(0), "0 = zero-based indexing, 1 = one-based indexing, (default: 0)") ("action", - po::value(&action)->default_value(0), + value(&action)->default_value(0), "0 = rocsparse_action_numeric, 1 = rocsparse_action_symbolic, (default: 0)") ("hybpart", - po::value(&part)->default_value(0), + value(&part)->default_value(0), "0 = rocsparse_hyb_partition_auto, 1 = rocsparse_hyb_partition_user,\n" "2 = rocsparse_hyb_partition_max, (default: 0)") ("diag", - po::value(&diag)->default_value('N'), + value(&diag)->default_value('N'), "N = non-unit diagonal, U = unit diagonal, (default = N)") ("uplo", - po::value(&uplo)->default_value('L'), + value(&uplo)->default_value('L'), "L = lower fill, U = upper fill, (default = L)") ("apolicy", - po::value(&apol)->default_value('R'), + value(&apol)->default_value('R'), "R = reuse meta data, F = force re-build, (default = R)") -// ("spolicy", -// po::value(&spol)->default_value('A'), -// "A = auto, (default = A)") - ("function,f", - po::value(&function)->default_value("axpyi"), + value(&function)->default_value("axpyi"), "SPARSE function to test. Options:\n" " Level1: axpyi, doti, dotci, gthr, gthrz, roti, sctr\n" " Level2: bsrmv, bsrsv, coomv, coomv_aos, csrmv, csrmv_managed, csrsv, ellmv, hybmv, gebsrmv\n" @@ -278,41 +284,41 @@ int main(int argc, char* argv[]) " Misc: identity, nnz") ("indextype", - po::value(&indextype)->default_value('s'), + value(&indextype)->default_value('s'), "Specify index types to be int32_t (s), int64_t (d) or mixed (m). Options: s,d,m") ("precision,r", - po::value(&precision)->default_value('s'), "Options: s,d,c,z") + value(&precision)->default_value('s'), "Options: s,d,c,z") ("verify,v", - po::value(&arg.unit_check)->default_value(0), + value(&arg.unit_check)->default_value(0), "Validate GPU results with CPU? 0 = No, 1 = Yes (default: No)") ("iters,i", - po::value(&arg.iters)->default_value(10), + value(&arg.iters)->default_value(10), "Iterations to run inside timing loop") ("device,d", - po::value(&device_id)->default_value(0), + value(&device_id)->default_value(0), "Set default device to be used for subsequent program runs") ("direction", - po::value(&dir)->default_value(rocsparse_direction_row), + value(&dir)->default_value(rocsparse_direction_row), "Indicates whether a dense matrix should be parsed by rows or by columns, assuming column-major storage: row = 0, column = 1 (default: 0)") ("order", - po::value(&order)->default_value(rocsparse_order_column), + value(&order)->default_value(rocsparse_order_column), "Indicates whether a dense matrix is laid out in column-major storage: 1, or row-major storage 0 (default: 1)") ("denseld", - po::value(&arg.denseld)->default_value(128), + value(&arg.denseld)->default_value(128), "Indicates the leading dimension of a dense matrix >= M, assuming a column-oriented storage."); // clang-format on - po::variables_map vm; - po::store(po::parse_command_line(argc, argv, desc), vm); - po::notify(vm); + variables_map vm; + store(parse_command_line(argc, argv, desc), vm); + notify(vm); if(vm.count("help")) { @@ -388,11 +394,6 @@ int main(int argc, char* argv[]) = (dir == rocsparse_direction_row) ? rocsparse_direction_row : rocsparse_direction_column; arg.order = (order == rocsparse_order_row) ? rocsparse_order_row : rocsparse_order_column; - // Set laplace dimensions - arg.dimx = laplace[0]; - arg.dimy = laplace[1]; - arg.dimz = laplace[2]; - // rocALUTION parameter overrides filename parameter if(rocalution != "") { diff --git a/clients/benchmarks/program_options.hpp b/clients/benchmarks/program_options.hpp new file mode 100644 index 00000000..85219c69 --- /dev/null +++ b/clients/benchmarks/program_options.hpp @@ -0,0 +1,385 @@ +/* ************************************************************************ + * Copyright (c) 2020-2021 Advanced Micro Devices, Inc. + * ************************************************************************ */ +// This emulates the required functionality of boost::program_options + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Regular expression for token delimiters (whitespace and commas) +static const std::regex program_options_regex{"[, \\f\\n\\r\\t\\v]+", + std::regex_constants::optimize}; + +// variables_map is a set of seen options +using variables_map = std::set; + +// Polymorphic base class to use with dynamic_cast +class value_base +{ +protected: + bool m_has_default = false; + +public: + bool has_default() const + { + return m_has_default; + } + + virtual ~value_base() = default; +}; + +// Value parameters +template +class value : public value_base +{ + T* m_var; // Pointer to variable to be modified + +public: + // Constructor + explicit value(T* var) + : m_var(var) + { + } + + // Pointer to variable + T* get_ptr() const + { + return m_var; + } + + // Allows default_value() + value* operator->() + { + return this; + } + + // Set default value + value& default_value(T val) + { + *m_var = std::move(val); + m_has_default = true; + return *this; + } +}; + +// bool_switch is a value, which is handled specially +using bool_switch = value; + +class options_description +{ + // desc_option describes a particular option + class desc_option + { + std::string m_opts; + value_base* m_val; + std::string m_desc; + + public: + // Constructor with options, value and description + template + desc_option(std::string opts, value val, std::string desc) + : m_opts(std::move(opts)) + , m_val(new auto(std::move(val))) + , m_desc(std::move(desc)) + { + } + + // Constructor with options and description + desc_option(std::string opts, std::string desc) + : m_opts(std::move(opts)) + , m_val(nullptr) + , m_desc(std::move(desc)) + { + } + + // Copy constructor is deleted + desc_option(const desc_option&) = delete; + + // Move constructor + desc_option(desc_option&& other) + : m_opts(std::move(other.m_opts)) + , m_val(other.m_val) + , m_desc(std::move(other.m_desc)) + { + other.m_val = nullptr; + } + + // Destructor + ~desc_option() + { + delete m_val; + } + + // Accessors + const std::string& get_opts() const + { + return m_opts; + } + + const value_base* get_val() const + { + return m_val; + } + + const std::string& get_desc() const + { + return m_desc; + } + + // Set a value + void set_val(int& argc, char**& argv) const + { + // We test all supported types with dynamic_cast and parse accordingly + bool match = false; + if(dynamic_cast*>(m_val)) + { + auto* val = dynamic_cast*>(m_val)->get_ptr(); + match = argc && sscanf(*argv, "%" SCNd32, val) == 1; + } + else if(dynamic_cast*>(m_val)) + { + auto* val = dynamic_cast*>(m_val)->get_ptr(); + match = argc && sscanf(*argv, "%" SCNu32, val) == 1; + } + else if(dynamic_cast*>(m_val)) + { + auto* val = dynamic_cast*>(m_val)->get_ptr(); + match = argc && sscanf(*argv, "%" SCNd64, val) == 1; + } + else if(dynamic_cast*>(m_val)) + { + auto* val = dynamic_cast*>(m_val)->get_ptr(); + match = argc && sscanf(*argv, "%" SCNu64, val) == 1; + } + else if(dynamic_cast*>(m_val)) + { + auto* val = dynamic_cast*>(m_val)->get_ptr(); + match = argc && sscanf(*argv, "%f", val) == 1; + } + else if(dynamic_cast*>(m_val)) + { + auto* val = dynamic_cast*>(m_val)->get_ptr(); + match = argc && sscanf(*argv, "%lf", val) == 1; + } + else if(dynamic_cast*>(m_val)) + { + auto* val = dynamic_cast*>(m_val)->get_ptr(); + match = argc && sscanf(*argv, " %c", val) == 1; + } + else if(dynamic_cast*>(m_val)) + { + // We handle bool specially, setting the value to true without argument + auto* val = dynamic_cast*>(m_val)->get_ptr(); + *val = true; + return; + } + else if(dynamic_cast*>(m_val)) + { + if(argc) + { + *dynamic_cast*>(m_val)->get_ptr() = *argv; + match = true; + } + } + else + { + throw std::logic_error("Internal error: Unsupported data type"); + } + + if(!match) + throw std::invalid_argument(argc ? *argv : "Missing required argument"); + + // Skip past the argument's value + ++argv; + --argc; + } + }; + + // Description and option list + std::string m_desc; + std::vector m_optlist; + + // desc_optionlist allows chains of options to be parenthesized + class desc_optionlist + { + std::vector& m_list; + + public: + explicit desc_optionlist(std::vector& list) + : m_list(list) + { + } + + template + desc_optionlist operator()(Ts&&... arg) + { + m_list.push_back(desc_option(std::forward(arg)...)); + return *this; + } + }; + +public: + // Constructor + explicit options_description(std::string desc) + : m_desc(std::move(desc)) + { + } + + // Start a desc_optionlist chain + desc_optionlist add_options() & + { + return desc_optionlist(m_optlist); + } + + // Parse an option at the current (argc, argv) position + void parse_option(int& argc, char**& argv, variables_map& vm, bool ignoreUnknown = false) const + { + // Iterate across all options + for(const auto& opt : m_optlist) + { + // Canonical name used for map + std::string canonical_name; + + // Iterate across tokens in the opts + for(std::sregex_token_iterator tok{ + opt.get_opts().begin(), opt.get_opts().end(), program_options_regex, -1}; + tok != std::sregex_token_iterator(); + ++tok) + { + // The first option in a list of options is the canonical name + if(!canonical_name.length()) + canonical_name = tok->str(); + + // If the length of the option is 1, it is single-dash; otherwise double-dash + const char* prefix = tok->length() == 1 ? "-" : "--"; + + // If option matches + if(*argv == prefix + tok->str()) + { + ++argv; + --argc; + + // If option has a value, set it; otherwise indicate option in set + if(opt.get_val()) + opt.set_val(argc, argv); + else + vm.insert(canonical_name); + return; // Return successfully + } + } + } + + // No options were matched + if(ignoreUnknown) + { + ++argv; + --argc; + } + else + { + throw std::invalid_argument(*argv); + } + } + + // Formatted output of command-line arguments description + friend std::ostream& operator<<(std::ostream& os, const options_description& d) + { + // Iterate across all options + for(const auto& opt : d.m_optlist) + { + bool first = true; + const char* delim = ""; + std::ostringstream left; + + // Iterate across tokens in the opts + for(std::sregex_token_iterator tok{opt.get_opts().begin(), + opt.get_opts().end(), + program_options_regex, + -1}; + tok != std::sregex_token_iterator(); + ++tok, first = false, delim = " ") + { + // If the length of the option is 1, it is single-dash; otherwise double-dash + const char* prefix = tok->length() == 1 ? "-" : "--"; + left << delim << (first ? "" : "[ ") << prefix << tok->str() << (first ? "" : " ]"); + } + + // Print the default value of the variable type if it exists + // We do not print the default value for bool + const value_base* val = opt.get_val(); + if(val && !dynamic_cast*>(val)) + { + left << " arg"; + if(val->has_default()) + { + // We test all supported types with dynamic_cast and print accordingly + left << " (="; + if(dynamic_cast*>(val)) + left << *dynamic_cast*>(val)->get_ptr(); + else if(dynamic_cast*>(val)) + left << *dynamic_cast*>(val)->get_ptr(); + else if(dynamic_cast*>(val)) + left << *dynamic_cast*>(val)->get_ptr(); + else if(dynamic_cast*>(val)) + left << *dynamic_cast*>(val)->get_ptr(); + else if(dynamic_cast*>(val)) + left << *dynamic_cast*>(val)->get_ptr(); + else if(dynamic_cast*>(val)) + left << *dynamic_cast*>(val)->get_ptr(); + else if(dynamic_cast*>(val)) + left << *dynamic_cast*>(val)->get_ptr(); + else if(dynamic_cast*>(val)) + left << *dynamic_cast*>(val)->get_ptr(); + else + throw std::logic_error("Internal error: Unsupported data type"); + left << ")"; + } + } + os << std::setw(36) << std::left << left.str() << " " << opt.get_desc() << "\n\n"; + } + return os << std::flush; + } +}; + +// Class representing command line parser +class parse_command_line +{ + variables_map m_vm; + +public: + parse_command_line(int argc, + char** argv, + const options_description& desc, + bool ignoreUnknown = false) + { + ++argv; // Skip argv[0] + --argc; + while(argc) + desc.parse_option(argc, argv, m_vm, ignoreUnknown); + } + + // Copy the variables_map + friend void store(const parse_command_line& p, variables_map& vm) + { + vm = p.m_vm; + } + + // Move the variables_map + friend void store(parse_command_line&& p, variables_map& vm) + { + vm = std::move(p.m_vm); + } +}; + +// We can define the notify() function as a no-op for our purposes +inline void notify(const variables_map&) {} diff --git a/clients/include/rocsparse_data.hpp b/clients/include/rocsparse_data.hpp index 30d67f44..a43250e3 100644 --- a/clients/include/rocsparse_data.hpp +++ b/clients/include/rocsparse_data.hpp @@ -1,6 +1,6 @@ /*! \file */ /* ************************************************************************ - * Copyright (c) 2019-2020 Advanced Micro Devices, Inc. + * Copyright (c) 2019-2021 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,6 @@ #include "rocsparse_arguments.hpp" #include "test_cleanup.hpp" -#include #include #include #include @@ -48,11 +47,46 @@ class RocSPARSE_TestData return filename; } -public: // filter iterator - using iterator = boost::filter_iterator, - std::istream_iterator>; + class iterator : public std::istream_iterator + { + bool (*const filter)(const Arguments&) = nullptr; + + // Skip entries for which filter is false + void skip_filter() + { + if(filter) + while(*this != std::istream_iterator{} && !filter(**this)) + ++*static_cast*>(this); + } + + public: + // Constructor takes a filter and iterator + iterator(bool filter(const Arguments&), std::istream_iterator iter) + : std::istream_iterator(iter) + , filter(filter) + { + skip_filter(); + } + + // Default end iterator and nullptr filter + iterator() = default; + // Preincrement iterator operator with filtering + iterator& operator++() + { + ++*static_cast*>(this); + skip_filter(); + return *this; + } + + // We do not need a postincrement iterator operator + // We delete it here so that the base class's isn't silently called + // To implement it, use "auto old = *this; ++*this; return old;" + iterator operator++(int) = delete; + }; + +public: // Initialize filename, optionally removing it at exit static void set_filename(std::string name, bool remove_atexit = false) { @@ -66,7 +100,7 @@ class RocSPARSE_TestData } // begin() iterator which accepts an optional filter. - static iterator begin(std::function filter = [](auto) { return true; }) + static iterator begin(bool filter(const Arguments&) = nullptr) { static std::ifstream* ifs; diff --git a/clients/include/testing_spmv.hpp b/clients/include/testing_spmv.hpp index 19d6f0f0..8ebf415c 100644 --- a/clients/include/testing_spmv.hpp +++ b/clients/include/testing_spmv.hpp @@ -419,25 +419,14 @@ struct testing_spmv_dispatch } device_sparse_matrix dA(hA); - if(!arg.unit_check) - { - hA.~host_sparse_matrix(); - } host_dense_matrix hx(N, 1); rocsparse_matrix_utils::init_exact(hx); device_dense_matrix dx(hx); - if(!arg.unit_check) - { - hx.~host_dense_matrix(); - } host_dense_matrix hy(M, 1); rocsparse_matrix_utils::init_exact(hy); - if(!arg.unit_check) - { - hy.~host_dense_matrix(); - } + device_dense_matrix dy(hy); rocsparse_local_spmat A(dA); diff --git a/clients/testings/testing_bsrmm.cpp b/clients/testings/testing_bsrmm.cpp index b4ffcd79..4a97f965 100644 --- a/clients/testings/testing_bsrmm.cpp +++ b/clients/testings/testing_bsrmm.cpp @@ -223,11 +223,6 @@ void testing_bsrmm(const Arguments& arg) matrix_factory.init_bsr(hA, dA, Mb, Kb); - if(!arg.unit_check) - { - hA.~host_gebsr_matrix(); - } - M = Mb * dA.row_block_dim; K = Kb * dA.col_block_dim; @@ -240,10 +235,6 @@ void testing_bsrmm(const Arguments& arg) rocsparse_matrix_utils::init(hB); device_dense_matrix dB(hB); - if(!arg.unit_check) - { - hB.~host_dense_matrix(); - } // // C @@ -251,10 +242,6 @@ void testing_bsrmm(const Arguments& arg) host_dense_matrix hC(M, N); rocsparse_matrix_utils::init(hC); device_dense_matrix dC(hC); - if(!arg.unit_check) - { - hC.~host_dense_matrix(); - } #define PARAMS(alpha_, dA_, dB_, beta_, dC_) \ handle, direction, transA, transB, Mb, N, Kb, dA_.nnzb, alpha_.val, descr, dA_.val, dA_.ptr, \ diff --git a/clients/tests/CMakeLists.txt b/clients/tests/CMakeLists.txt index 19c0e895..dfe97ff8 100644 --- a/clients/tests/CMakeLists.txt +++ b/clients/tests/CMakeLists.txt @@ -21,19 +21,7 @@ # # ######################################################################## -set(Boost_USE_MULTITHREADED ON) -set(Boost_DETAILED_FAILURE_MSG ON) -set(Boost_ADDITIONAL_VERSIONS 1.65.1 1.65) -set(Boost_USE_STATIC_LIBS OFF) - find_package(GTest REQUIRED) -find_package(Boost COMPONENTS program_options) - -if(NOT Boost_FOUND) - message(STATUS "Dynamic boost libraries not found. Attempting to find static libraries...") - set(Boost_USE_STATIC_LIBS ON) - find_package(Boost REQUIRED COMPONENTS program_options) -endif() # Download some test matrices set(TEST_MATRICES @@ -346,7 +334,7 @@ target_compile_options(rocsparse-test PRIVATE -ffp-contract=on -mfma -Wno-unused target_include_directories(rocsparse-test PRIVATE $) # Target link libraries -target_link_libraries(rocsparse-test PRIVATE GTest::GTest Boost::program_options roc::rocsparse hip::host) +target_link_libraries(rocsparse-test PRIVATE GTest::GTest roc::rocsparse hip::host) # Add OpenMP if available if(OPENMP_FOUND) diff --git a/docs/source/usermanual.rst b/docs/source/usermanual.rst index 8d6efa27..ca767cae 100644 --- a/docs/source/usermanual.rst +++ b/docs/source/usermanual.rst @@ -58,7 +58,6 @@ Furthermore, the following compile-time dependencies must be met - `AMD ROCm `_ - `rocPRIM `_ - `googletest `_ (optional, for clients) -- `libboost-program-options `_ (optional, for clients) Download rocSPARSE `````````````````` @@ -127,15 +126,12 @@ rocSPARSE can be built using the following commands: # Install rocSPARSE to /opt/rocm $ make install -Boost and GoogleTest is required in order to build rocSPARSE clients. +GoogleTest is required in order to build rocSPARSE clients. rocSPARSE with dependencies and clients can be built using the following commands: :: - # Install boost on e.g. Ubuntu - $ apt install libboost-program-options-dev - # Install googletest $ mkdir -p build/release/deps ; cd build/release/deps $ cmake ../../../deps