1 //=================================================================================================
2 /*!
3 // \file src/main/TDMatSVecMult.cpp
4 // \brief Source file for the transpose dense matrix/sparse vector 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/CompressedVector.h>
47 #include <blaze/math/DynamicMatrix.h>
48 #include <blaze/math/DynamicVector.h>
49 #include <blaze/math/Infinity.h>
50 #include <blaze/util/algorithms/Max.h>
51 #include <blaze/util/Random.h>
52 #include <blaze/util/Timing.h>
53 #include <blazemark/blaze/init/CompressedVector.h>
54 #include <blazemark/blaze/init/DynamicMatrix.h>
55 #include <blazemark/blaze/TDMatSVecMult.h>
56 #include <blazemark/boost/TDMatSVecMult.h>
57 #include <blazemark/gmm/TDMatSVecMult.h>
58 #include <blazemark/system/Boost.h>
59 #include <blazemark/system/Config.h>
60 #include <blazemark/system/GMM.h>
61 #include <blazemark/system/Types.h>
62 #include <blazemark/util/Benchmarks.h>
63 #include <blazemark/util/DynamicSparseRun.h>
64 #include <blazemark/util/Parser.h>
65
66 #ifdef BLAZE_USE_HPX_THREADS
67 # include <hpx/hpx_main.hpp>
68 #endif
69
70
71 //*************************************************************************************************
72 // Using declarations
73 //*************************************************************************************************
74
75 using blazemark::Benchmarks;
76 using blazemark::DynamicSparseRun;
77 using blazemark::Parser;
78
79
80
81
82 //=================================================================================================
83 //
84 // TYPE DEFINITIONS
85 //
86 //=================================================================================================
87
88 //*************************************************************************************************
89 /*!\brief Type of a benchmark run.
90 //
91 // This type definition specifies the type of a single benchmark run for the transpose dense
92 // matrix/sparse vector multiplication benchmark.
93 */
94 using Run = DynamicSparseRun;
95 //*************************************************************************************************
96
97
98
99
100 //=================================================================================================
101 //
102 // UTILITY FUNCTIONS
103 //
104 //=================================================================================================
105
106 //*************************************************************************************************
107 /*!\brief Estimating the necessary number of steps for each benchmark.
108 //
109 // \param run The parameters for the benchmark run.
110 // \return void
111 //
112 // This function estimates the necessary number of steps for the given benchmark based on the
113 // performance of the Blaze library.
114 */
estimateSteps(Run & run)115 void estimateSteps( Run& run )
116 {
117 using blazemark::element_t;
118 using blaze::columnVector;
119 using blaze::columnMajor;
120
121 ::blaze::setSeed( ::blazemark::seed );
122
123 const size_t N( run.getSize() );
124 const size_t F( run.getNonZeros() );
125
126 blaze::DynamicMatrix<element_t,columnMajor> A( N, N );
127 blaze::CompressedVector<element_t,columnVector> a( N, F );
128 blaze::DynamicVector<element_t,columnVector> b( N );
129 blaze::timing::WcTimer timer;
130 double wct( 0.0 );
131 size_t steps( 1UL );
132
133 blazemark::blaze::init( A );
134 blazemark::blaze::init( a, F );
135
136 while( true ) {
137 timer.start();
138 for( size_t i=0UL; i<steps; ++i ) {
139 b = A * a;
140 }
141 timer.end();
142 wct = timer.last();
143 if( wct >= 0.2 ) break;
144 steps *= 2UL;
145 }
146
147 if( b.size() != N )
148 std::cerr << " Line " << __LINE__ << ": ERROR detected!!!\n";
149
150 const size_t estimatedSteps( ( blazemark::runtime * steps ) / timer.last() );
151 run.setSteps( blaze::max( 1UL, estimatedSteps ) );
152 }
153 //*************************************************************************************************
154
155
156 //*************************************************************************************************
157 /*!\brief Estimating the necessary number of floating point operations.
158 //
159 // \param run The parameters for the benchmark run.
160 // \return void
161 //
162 // This function estimates the number of floating point operations required for a single
163 // computation of the (composite) arithmetic operation.
164 */
estimateFlops(Run & run)165 void estimateFlops( Run& run )
166 {
167 const size_t N( run.getSize() );
168 const size_t F( run.getNonZeros() );
169
170 run.setFlops( 2U*N*F - N );
171 }
172 //*************************************************************************************************
173
174
175
176
177 //=================================================================================================
178 //
179 // BENCHMARK FUNCTIONS
180 //
181 //=================================================================================================
182
183 //*************************************************************************************************
184 /*!\brief Transpose dense matrix/sparse vector multiplication benchmark function.
185 //
186 // \param runs The specified benchmark runs.
187 // \param benchmarks The selection of benchmarks.
188 // \return void
189 */
tdmatsvecmult(std::vector<Run> & runs,Benchmarks benchmarks)190 void tdmatsvecmult( std::vector<Run>& runs, Benchmarks benchmarks )
191 {
192 std::cout << std::left;
193
194 std::sort( runs.begin(), runs.end() );
195
196 size_t slowSize( blaze::inf );
197 for( std::vector<Run>::iterator run=runs.begin(); run!=runs.end(); ++run )
198 {
199 estimateFlops( *run );
200
201 if( run->getSteps() == 0UL ) {
202 if( run->getSize() < slowSize ) {
203 estimateSteps( *run );
204 if( run->getSteps() == 1UL )
205 slowSize = run->getSize();
206 }
207 else run->setSteps( 1UL );
208 }
209 }
210
211 if( benchmarks.runBlaze ) {
212 std::vector<Run>::iterator run=runs.begin();
213 while( run != runs.end() ) {
214 const float fill( run->getFillingDegree() );
215 std::cout << " Blaze (" << fill << "% filled) [MFlop/s]:\n";
216 for( ; run!=runs.end(); ++run ) {
217 if( run->getFillingDegree() != fill ) break;
218 const size_t N ( run->getSize() );
219 const size_t F ( run->getNonZeros() );
220 const size_t steps( run->getSteps() );
221 run->setBlazeResult( blazemark::blaze::tdmatsvecmult( N, F, steps ) );
222 const double mflops( run->getFlops() * steps / run->getBlazeResult() / 1E6 );
223 std::cout << " " << std::setw(12) << N << mflops << std::endl;
224 }
225 }
226 }
227
228 #if BLAZEMARK_BOOST_MODE
229 if( benchmarks.runBoost ) {
230 std::vector<Run>::iterator run=runs.begin();
231 while( run != runs.end() ) {
232 const float fill( run->getFillingDegree() );
233 std::cout << " Boost uBLAS (" << fill << "% filled) [MFlop/s]:\n";
234 for( ; run!=runs.end(); ++run ) {
235 if( run->getFillingDegree() != fill ) break;
236 const size_t N ( run->getSize() );
237 const size_t F ( run->getNonZeros() );
238 const size_t steps( run->getSteps() );
239 run->setBoostResult( blazemark::boost::tdmatsvecmult( N, F, steps ) );
240 const double mflops( run->getFlops() * steps / run->getBoostResult() / 1E6 );
241 std::cout << " " << std::setw(12) << N << mflops << std::endl;
242 }
243 }
244 }
245 #endif
246
247 #if BLAZEMARK_GMM_MODE
248 if( benchmarks.runGMM ) {
249 std::vector<Run>::iterator run=runs.begin();
250 while( run != runs.end() ) {
251 const float fill( run->getFillingDegree() );
252 std::cout << " GMM++ (" << fill << "% filled) [MFlop/s]:\n";
253 for( ; run!=runs.end(); ++run ) {
254 if( run->getFillingDegree() != fill ) break;
255 const size_t N ( run->getSize() );
256 const size_t F ( run->getNonZeros() );
257 const size_t steps( run->getSteps() );
258 run->setGMMResult( blazemark::gmm::tdmatsvecmult( N, F, steps ) );
259 const double mflops( run->getFlops() * steps / run->getGMMResult() / 1E6 );
260 std::cout << " " << std::setw(12) << N << mflops << std::endl;
261 }
262 }
263 }
264 #endif
265
266 for( std::vector<Run>::iterator run=runs.begin(); run!=runs.end(); ++run ) {
267 std::cout << *run;
268 }
269 }
270 //*************************************************************************************************
271
272
273
274
275 //=================================================================================================
276 //
277 // MAIN FUNCTION
278 //
279 //=================================================================================================
280
281 //*************************************************************************************************
282 /*!\brief The main function for the transpose dense matrix/sparse vector multiplication benchmark.
283 //
284 // \param argc The total number of command line arguments.
285 // \param argv The array of command line arguments.
286 // \return void
287 */
main(int argc,char ** argv)288 int main( int argc, char** argv )
289 {
290 std::cout << "\n Transpose Dense Matrix/Sparse Vector Multiplication:\n";
291
292 Benchmarks benchmarks;
293
294 try {
295 parseCommandLineArguments( argc, argv, benchmarks );
296 }
297 catch( std::exception& ex ) {
298 std::cerr << " " << ex.what() << "\n";
299 return EXIT_FAILURE;
300 }
301
302 const std::string installPath( INSTALL_PATH );
303 const std::string parameterFile( installPath + "/params/tdmatsvecmult.prm" );
304 Parser<Run> parser;
305 std::vector<Run> runs;
306
307 try {
308 parser.parse( parameterFile.c_str(), runs );
309 }
310 catch( std::exception& ex ) {
311 std::cerr << " Error during parameter extraction: " << ex.what() << "\n";
312 return EXIT_FAILURE;
313 }
314
315 try {
316 tdmatsvecmult( runs, benchmarks );
317 }
318 catch( std::exception& ex ) {
319 std::cerr << " Error during benchmark execution: " << ex.what() << "\n";
320 return EXIT_FAILURE;
321 }
322
323 return EXIT_SUCCESS;
324 }
325 //*************************************************************************************************
326