1 //=================================================================================================
2 /*!
3 // \file src/main/DVecSVecMult.cpp
4 // \brief Source file for the dense vector/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/DynamicVector.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/DVecSVecMult.h>
53 #include <blazemark/blaze/init/CompressedVector.h>
54 #include <blazemark/blaze/init/DynamicVector.h>
55 #include <blazemark/boost/DVecSVecMult.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 dense vector/sparse
89 // vector 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::columnVector;
116
117 ::blaze::setSeed( ::blazemark::seed );
118
119 const size_t N( run.getSize() );
120 const size_t F( run.getNonZeros() );
121
122 blaze::DynamicVector<element_t,columnVector> a( N );
123 blaze::CompressedVector<element_t,columnVector> b( N, F ), c( N );
124 blaze::timing::WcTimer timer;
125 double wct( 0.0 );
126 size_t steps( 1UL );
127
128 blazemark::blaze::init( a );
129 blazemark::blaze::init( b, F );
130
131 while( true ) {
132 timer.start();
133 for( size_t i=0UL; i<steps; ++i ) {
134 c = a * b;
135 }
136 timer.end();
137 wct = timer.last();
138 if( wct >= 0.2 ) break;
139 steps *= 2UL;
140 }
141
142 if( c.size() != N )
143 std::cerr << " Line " << __LINE__ << ": ERROR detected!!!\n";
144
145 const size_t estimatedSteps( ( blazemark::runtime * steps ) / timer.last() );
146 run.setSteps( blaze::max( 1UL, estimatedSteps ) );
147 }
148 //*************************************************************************************************
149
150
151 //*************************************************************************************************
152 /*!\brief Estimating the necessary number of floating point operations.
153 //
154 // \param run The parameters for the benchmark run.
155 // \return void
156 //
157 // This function estimates the number of floating point operations required for a single
158 // computation of the (composite) arithmetic operation.
159 */
estimateFlops(Run & run)160 void estimateFlops( Run& run )
161 {
162 const size_t F( run.getNonZeros() );
163
164 run.setFlops( F );
165 }
166 //*************************************************************************************************
167
168
169
170
171 //=================================================================================================
172 //
173 // BENCHMARK FUNCTIONS
174 //
175 //=================================================================================================
176
177 //*************************************************************************************************
178 /*!\brief Dense vector/sparse vector multiplication benchmark function.
179 //
180 // \param runs The specified benchmark runs.
181 // \param benchmarks The selection of benchmarks.
182 // \return void
183 */
dvecsvecmult(std::vector<Run> & runs,Benchmarks benchmarks)184 void dvecsvecmult( std::vector<Run>& runs, Benchmarks benchmarks )
185 {
186 std::cout << std::left;
187
188 std::sort( runs.begin(), runs.end() );
189
190 size_t slowSize( blaze::inf );
191 for( std::vector<Run>::iterator run=runs.begin(); run!=runs.end(); ++run )
192 {
193 estimateFlops( *run );
194
195 if( run->getSteps() == 0UL ) {
196 if( run->getSize() < slowSize ) {
197 estimateSteps( *run );
198 if( run->getSteps() == 1UL )
199 slowSize = run->getSize();
200 }
201 else run->setSteps( 1UL );
202 }
203 }
204
205 if( benchmarks.runBlaze ) {
206 std::vector<Run>::iterator run=runs.begin();
207 while( run != runs.end() ) {
208 const float fill( run->getFillingDegree() );
209 std::cout << " Blaze (" << fill << "% filled) [MFlop/s]:\n";
210 for( ; run!=runs.end(); ++run ) {
211 if( run->getFillingDegree() != fill ) break;
212 const size_t N ( run->getSize() );
213 const size_t F ( run->getNonZeros() );
214 const size_t steps( run->getSteps() );
215 run->setBlazeResult( blazemark::blaze::dvecsvecmult( N, F, steps ) );
216 const double mflops( run->getFlops() * steps / run->getBlazeResult() / 1E6 );
217 std::cout << " " << std::setw(12) << N << mflops << std::endl;
218 }
219 }
220 }
221
222 #if BLAZEMARK_BOOST_MODE
223 if( benchmarks.runBoost ) {
224 std::vector<Run>::iterator run=runs.begin();
225 while( run != runs.end() ) {
226 const float fill( run->getFillingDegree() );
227 std::cout << " Boost uBLAS (" << fill << "% filled) [MFlop/s]:\n";
228 for( ; run!=runs.end(); ++run ) {
229 if( run->getFillingDegree() != fill ) break;
230 const size_t N ( run->getSize() );
231 const size_t F ( run->getNonZeros() );
232 const size_t steps( run->getSteps() );
233 run->setBoostResult( blazemark::boost::dvecsvecmult( N, F, steps ) );
234 const double mflops( run->getFlops() * steps / run->getBoostResult() / 1E6 );
235 std::cout << " " << std::setw(12) << N << mflops << std::endl;
236 }
237 }
238 }
239 #endif
240
241 for( std::vector<Run>::iterator run=runs.begin(); run!=runs.end(); ++run ) {
242 std::cout << *run;
243 }
244 }
245 //*************************************************************************************************
246
247
248
249
250 //=================================================================================================
251 //
252 // MAIN FUNCTION
253 //
254 //=================================================================================================
255
256 //*************************************************************************************************
257 /*!\brief The main function for the dense vector/sparse vector multiplication benchmark.
258 //
259 // \param argc The total number of command line arguments.
260 // \param argv The array of command line arguments.
261 // \return void
262 */
main(int argc,char ** argv)263 int main( int argc, char** argv )
264 {
265 std::cout << "\n Dense Vector/Sparse Vector Multiplication:\n";
266
267 Benchmarks benchmarks;
268
269 try {
270 parseCommandLineArguments( argc, argv, benchmarks );
271 }
272 catch( std::exception& ex ) {
273 std::cerr << " " << ex.what() << "\n";
274 return EXIT_FAILURE;
275 }
276
277 const std::string installPath( INSTALL_PATH );
278 const std::string parameterFile( installPath + "/params/dvecsvecmult.prm" );
279 Parser<Run> parser;
280 std::vector<Run> runs;
281
282 try {
283 parser.parse( parameterFile.c_str(), runs );
284 }
285 catch( std::exception& ex ) {
286 std::cerr << " Error during parameter extraction: " << ex.what() << "\n";
287 return EXIT_FAILURE;
288 }
289
290 try {
291 dvecsvecmult( runs, benchmarks );
292 }
293 catch( std::exception& ex ) {
294 std::cerr << " Error during benchmark execution: " << ex.what() << "\n";
295 return EXIT_FAILURE;
296 }
297
298 return EXIT_SUCCESS;
299 }
300 //*************************************************************************************************
301