1 //=================================================================================================
2 /*!
3 //  \file src/main/TSVecSMatMult.cpp
4 //  \brief Source file for the transpose sparse vector/sparse matrix multiplication benchmark
5 //
6 //  Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved
7 //
8 //  This file is part of the Blaze library. You can redistribute it and/or modify it under
9 //  the terms of the New (Revised) BSD License. Redistribution and use in source and binary
10 //  forms, with or without modification, are permitted provided that the following conditions
11 //  are met:
12 //
13 //  1. Redistributions of source code must retain the above copyright notice, this list of
14 //     conditions and the following disclaimer.
15 //  2. Redistributions in binary form must reproduce the above copyright notice, this list
16 //     of conditions and the following disclaimer in the documentation and/or other materials
17 //     provided with the distribution.
18 //  3. Neither the names of the Blaze development group nor the names of its contributors
19 //     may be used to endorse or promote products derived from this software without specific
20 //     prior written permission.
21 //
22 //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 //  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 //  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 //  SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 //  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 //  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 //  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 //  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 //  DAMAGE.
32 */
33 //=================================================================================================
34 
35 
36 //*************************************************************************************************
37 // Includes
38 //*************************************************************************************************
39 
40 #include <algorithm>
41 #include <cstdlib>
42 #include <iostream>
43 #include <stdexcept>
44 #include <string>
45 #include <vector>
46 #include <blaze/math/CompressedMatrix.h>
47 #include <blaze/math/CompressedVector.h>
48 #include <blaze/math/Infinity.h>
49 #include <blaze/util/algorithms/Max.h>
50 #include <blaze/util/Random.h>
51 #include <blaze/util/Timing.h>
52 #include <blazemark/blaze/init/CompressedMatrix.h>
53 #include <blazemark/blaze/init/CompressedVector.h>
54 #include <blazemark/blaze/TSVecSMatMult.h>
55 #include <blazemark/boost/TSVecSMatMult.h>
56 #include <blazemark/system/Boost.h>
57 #include <blazemark/system/Config.h>
58 #include <blazemark/system/Types.h>
59 #include <blazemark/util/Benchmarks.h>
60 #include <blazemark/util/DynamicSparseRun.h>
61 #include <blazemark/util/Parser.h>
62 
63 #ifdef BLAZE_USE_HPX_THREADS
64 #  include <hpx/hpx_main.hpp>
65 #endif
66 
67 
68 //*************************************************************************************************
69 // Using declarations
70 //*************************************************************************************************
71 
72 using blazemark::Benchmarks;
73 using blazemark::DynamicSparseRun;
74 using blazemark::Parser;
75 
76 
77 
78 
79 //=================================================================================================
80 //
81 //  TYPE DEFINITIONS
82 //
83 //=================================================================================================
84 
85 //*************************************************************************************************
86 /*!\brief Type of a benchmark run.
87 //
88 // This type definition specifies the type of a single benchmark run for the transpose sparse
89 // vector/sparse matrix multiplication benchmark.
90 */
91 using Run = DynamicSparseRun;
92 //*************************************************************************************************
93 
94 
95 
96 
97 //=================================================================================================
98 //
99 //  UTILITY FUNCTIONS
100 //
101 //=================================================================================================
102 
103 //*************************************************************************************************
104 /*!\brief Estimating the necessary number of steps for each benchmark.
105 //
106 // \param run The parameters for the benchmark run.
107 // \return void
108 //
109 // This function estimates the necessary number of steps for the given benchmark based on the
110 // performance of the Blaze library.
111 */
estimateSteps(Run & run)112 void estimateSteps( Run& run )
113 {
114    using blazemark::element_t;
115    using blaze::rowVector;
116    using blaze::rowMajor;
117 
118    ::blaze::setSeed( ::blazemark::seed );
119 
120    const size_t N( run.getSize() );
121    const size_t F( run.getNonZeros() );
122 
123    blaze::CompressedVector<element_t,rowVector> a( N, F ), b( N );
124    blaze::CompressedMatrix<element_t,rowMajor> A( N, N, N*F );
125    blaze::timing::WcTimer timer;
126    double wct( 0.0 );
127    size_t steps( 1UL );
128 
129    blazemark::blaze::init( a, F );
130    blazemark::blaze::init( A, F );
131 
132    while( true ) {
133       timer.start();
134       for( size_t i=0UL; i<steps; ++i ) {
135          b = a * A;
136       }
137       timer.end();
138       wct = timer.last();
139       if( wct >= 0.2 ) break;
140       steps *= 2UL;
141    }
142 
143    if( b.size() != N )
144       std::cerr << " Line " << __LINE__ << ": ERROR detected!!!\n";
145 
146    const size_t estimatedSteps( ( blazemark::runtime * steps ) / timer.last() );
147    run.setSteps( blaze::max( 1UL, estimatedSteps ) );
148 }
149 //*************************************************************************************************
150 
151 
152 //*************************************************************************************************
153 /*!\brief Estimating the necessary number of floating point operations.
154 //
155 // \param run The parameters for the benchmark run.
156 // \return void
157 //
158 // This function estimates the number of floating point operations required for a single
159 // computation of the (composite) arithmetic operation.
160 */
estimateFlops(Run & run)161 void estimateFlops( Run& run )
162 {
163    const size_t N( run.getSize()     );
164    const size_t F( run.getNonZeros() );
165 
166    run.setFlops( 2UL*N*F - N );
167 }
168 //*************************************************************************************************
169 
170 
171 
172 
173 //=================================================================================================
174 //
175 //  BENCHMARK FUNCTIONS
176 //
177 //=================================================================================================
178 
179 //*************************************************************************************************
180 /*!\brief Transpose sparse vector/sparse matrix multiplication benchmark function.
181 //
182 // \param runs The specified benchmark runs.
183 // \param benchmarks The selection of benchmarks.
184 // \return void
185 */
tsvecsmatmult(std::vector<Run> & runs,Benchmarks benchmarks)186 void tsvecsmatmult( std::vector<Run>& runs, Benchmarks benchmarks )
187 {
188    std::cout << std::left;
189 
190    std::sort( runs.begin(), runs.end() );
191 
192    size_t slowSize( blaze::inf );
193    for( std::vector<Run>::iterator run=runs.begin(); run!=runs.end(); ++run )
194    {
195       estimateFlops( *run );
196 
197       if( run->getSteps() == 0UL ) {
198          if( run->getSize() < slowSize ) {
199             estimateSteps( *run );
200             if( run->getSteps() == 1UL )
201                slowSize = run->getSize();
202          }
203          else run->setSteps( 1UL );
204       }
205    }
206 
207    if( benchmarks.runBlaze ) {
208       std::vector<Run>::iterator run=runs.begin();
209       while( run != runs.end() ) {
210          const float fill( run->getFillingDegree() );
211          std::cout << "   Blaze (" << fill << "% filled) [MFlop/s]:\n";
212          for( ; run!=runs.end(); ++run ) {
213             if( run->getFillingDegree() != fill ) break;
214             const size_t N    ( run->getSize()     );
215             const size_t F    ( run->getNonZeros() );
216             const size_t steps( run->getSteps()    );
217             run->setBlazeResult( blazemark::blaze::tsvecsmatmult( N, F, steps ) );
218             const double mflops( run->getFlops() * steps / run->getBlazeResult() / 1E6 );
219             std::cout << "     " << std::setw(12) << N << mflops << std::endl;
220          }
221       }
222    }
223 
224 #if BLAZEMARK_BOOST_MODE
225    if( benchmarks.runBoost ) {
226       std::vector<Run>::iterator run=runs.begin();
227       while( run != runs.end() ) {
228          const float fill( run->getFillingDegree() );
229          std::cout << "   Boost uBLAS (" << fill << "% filled) [MFlop/s]:\n";
230          for( ; run!=runs.end(); ++run ) {
231             if( run->getFillingDegree() != fill ) break;
232             const size_t N    ( run->getSize()     );
233             const size_t F    ( run->getNonZeros() );
234             const size_t steps( run->getSteps()    );
235             run->setBoostResult( blazemark::boost::tsvecsmatmult( N, F, steps ) );
236             const double mflops( run->getFlops() * steps / run->getBoostResult() / 1E6 );
237             std::cout << "     " << std::setw(12) << N << mflops << std::endl;
238          }
239       }
240    }
241 #endif
242 
243    for( std::vector<Run>::iterator run=runs.begin(); run!=runs.end(); ++run ) {
244       std::cout << *run;
245    }
246 }
247 //*************************************************************************************************
248 
249 
250 
251 
252 //=================================================================================================
253 //
254 //  MAIN FUNCTION
255 //
256 //=================================================================================================
257 
258 //*************************************************************************************************
259 /*!\brief The main function for the transpose sparse vector/sparse matrix multiplication benchmark.
260 //
261 // \param argc The total number of command line arguments.
262 // \param argv The array of command line arguments.
263 // \return void
264 */
main(int argc,char ** argv)265 int main( int argc, char** argv )
266 {
267    std::cout << "\n Transpose Sparse Vector/Sparse Matrix Multiplication:\n";
268 
269    Benchmarks benchmarks;
270 
271    try {
272       parseCommandLineArguments( argc, argv, benchmarks );
273    }
274    catch( std::exception& ex ) {
275       std::cerr << "   " << ex.what() << "\n";
276       return EXIT_FAILURE;
277    }
278 
279    const std::string installPath( INSTALL_PATH );
280    const std::string parameterFile( installPath + "/params/tsvecsmatmult.prm" );
281    Parser<Run> parser;
282    std::vector<Run> runs;
283 
284    try {
285       parser.parse( parameterFile.c_str(), runs );
286    }
287    catch( std::exception& ex ) {
288       std::cerr << "   Error during parameter extraction: " << ex.what() << "\n";
289       return EXIT_FAILURE;
290    }
291 
292    try {
293       tsvecsmatmult( runs, benchmarks );
294    }
295    catch( std::exception& ex ) {
296       std::cerr << "   Error during benchmark execution: " << ex.what() << "\n";
297       return EXIT_FAILURE;
298    }
299 
300    return EXIT_SUCCESS;
301 }
302 //*************************************************************************************************
303