//================================================================================================= /*! // \file src/main/DVecSVecOuter.cpp // \brief Source file for the dense vector/sparse vector outer product benchmark // // Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved // // This file is part of the Blaze library. You can redistribute it and/or modify it under // the terms of the New (Revised) BSD License. Redistribution and use in source and binary // forms, with or without modification, are permitted provided that the following conditions // are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // 3. Neither the names of the Blaze development group nor the names of its contributors // may be used to endorse or promote products derived from this software without specific // prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT // SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH // DAMAGE. */ //================================================================================================= //************************************************************************************************* // Includes //************************************************************************************************* #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef BLAZE_USE_HPX_THREADS # include #endif //************************************************************************************************* // Using declarations //************************************************************************************************* using blazemark::Benchmarks; using blazemark::DynamicSparseRun; using blazemark::Parser; //================================================================================================= // // TYPE DEFINITIONS // //================================================================================================= //************************************************************************************************* /*!\brief Type of a benchmark run. // // This type definition specifies the type of a single benchmark run for the dense vector/sparse // vector outer product benchmark. */ using Run = DynamicSparseRun; //************************************************************************************************* //================================================================================================= // // UTILITY FUNCTIONS // //================================================================================================= //************************************************************************************************* /*!\brief Estimating the necessary number of steps for each benchmark. // // \param run The parameters for the benchmark run. // \return void // // This function estimates the necessary number of steps for the given benchmark based on the // performance of the Blaze library. */ void estimateSteps( Run& run ) { using blazemark::element_t; using blaze::rowVector; using blaze::columnVector; using blaze::rowMajor; ::blaze::setSeed( ::blazemark::seed ); const size_t N( run.getSize() ); const size_t F( run.getNonZeros() ); blaze::DynamicVector a( N ); blaze::CompressedVector b( N, F ); blaze::CompressedMatrix A( N, N ); blaze::timing::WcTimer timer; double wct( 0.0 ); size_t steps( 1UL ); blazemark::blaze::init( a ); blazemark::blaze::init( b, F ); while( true ) { timer.start(); for( size_t i=0UL; i= 0.2 ) break; steps *= 2UL; } if( A.rows() != N ) std::cerr << " Line " << __LINE__ << ": ERROR detected!!!\n"; const size_t estimatedSteps( ( blazemark::runtime * steps ) / timer.last() ); run.setSteps( blaze::max( 1UL, estimatedSteps ) ); } //************************************************************************************************* //************************************************************************************************* /*!\brief Estimating the necessary number of floating point operations. // // \param run The parameters for the benchmark run. // \return void // // This function estimates the number of floating point operations required for a single // computation of the (composite) arithmetic operation. */ void estimateFlops( Run& run ) { const size_t N( run.getSize() ); const size_t F( run.getNonZeros() ); run.setFlops( N*F ); } //************************************************************************************************* //================================================================================================= // // BENCHMARK FUNCTIONS // //================================================================================================= //************************************************************************************************* /*!\brief Dense vector/sparse vector outer product benchmark function. // // \param runs The specified benchmark runs. // \param benchmarks The selection of benchmarks. // \return void */ void dvecsvecouter( std::vector& runs, Benchmarks benchmarks ) { std::cout << std::left; std::sort( runs.begin(), runs.end() ); size_t slowSize( blaze::inf ); for( std::vector::iterator run=runs.begin(); run!=runs.end(); ++run ) { estimateFlops( *run ); if( run->getSteps() == 0UL ) { if( run->getSize() < slowSize ) { estimateSteps( *run ); if( run->getSteps() == 1UL ) slowSize = run->getSize(); } else run->setSteps( 1UL ); } } if( benchmarks.runBlaze ) { std::vector::iterator run=runs.begin(); while( run != runs.end() ) { const float fill( run->getFillingDegree() ); std::cout << " Blaze (" << fill << "% filled) [MFlop/s]:\n"; for( ; run!=runs.end(); ++run ) { if( run->getFillingDegree() != fill ) break; const size_t N ( run->getSize() ); const size_t F ( run->getNonZeros() ); const size_t steps( run->getSteps() ); run->setBlazeResult( blazemark::blaze::dvecsvecouter( N, F, steps ) ); const double mflops( run->getFlops() * steps / run->getBlazeResult() / 1E6 ); std::cout << " " << std::setw(12) << N << mflops << std::endl; } } } #if BLAZEMARK_BOOST_MODE if( benchmarks.runBoost ) { std::vector::iterator run=runs.begin(); while( run != runs.end() ) { const float fill( run->getFillingDegree() ); std::cout << " Boost uBLAS (" << fill << "% filled) [MFlop/s]:\n"; for( ; run!=runs.end(); ++run ) { if( run->getFillingDegree() != fill ) break; const size_t N ( run->getSize() ); const size_t F ( run->getNonZeros() ); const size_t steps( run->getSteps() ); run->setBoostResult( blazemark::boost::dvecsvecouter( N, F, steps ) ); const double mflops( run->getFlops() * steps / run->getBoostResult() / 1E6 ); std::cout << " " << std::setw(12) << N << mflops << std::endl; } } } #endif for( std::vector::iterator run=runs.begin(); run!=runs.end(); ++run ) { std::cout << *run; } } //************************************************************************************************* //================================================================================================= // // MAIN FUNCTION // //================================================================================================= //************************************************************************************************* /*!\brief The main function for the dense vector/sparse vector outer product benchmark. // // \param argc The total number of command line arguments. // \param argv The array of command line arguments. // \return void */ int main( int argc, char** argv ) { std::cout << "\n Dense Vector/Sparse Vector Outer Product:\n"; Benchmarks benchmarks; try { parseCommandLineArguments( argc, argv, benchmarks ); } catch( std::exception& ex ) { std::cerr << " " << ex.what() << "\n"; return EXIT_FAILURE; } const std::string installPath( INSTALL_PATH ); const std::string parameterFile( installPath + "/params/dvecsvecouter.prm" ); Parser parser; std::vector runs; try { parser.parse( parameterFile.c_str(), runs ); } catch( std::exception& ex ) { std::cerr << " Error during parameter extraction: " << ex.what() << "\n"; return EXIT_FAILURE; } try { dvecsvecouter( runs, benchmarks ); } catch( std::exception& ex ) { std::cerr << " Error during benchmark execution: " << ex.what() << "\n"; return EXIT_FAILURE; } return EXIT_SUCCESS; } //*************************************************************************************************