4343#include < graphblas/algorithms/multigrid/multigrid_v_cycle.hpp>
4444#include < graphblas/algorithms/multigrid/red_black_gauss_seidel.hpp>
4545#include < graphblas/algorithms/multigrid/single_matrix_coarsener.hpp>
46- #include < graphblas/utils/Timer.hpp>
4746#include < graphblas/utils/telemetry/Telemetry.hpp>
4847
4948#include < utils/argument_parser.hpp>
@@ -135,10 +134,14 @@ using hpcg_runner_t = MultiGridCGRunner< HPCGTypes, mg_runner_t, hpcg_controller
135134 hpcg_desc, DBGStream >;
136135using hpcg_data_t = typename hpcg_runner_t ::HPCGInputType;
137136
137+ // Stopwatch type, to measure various setup phases
138+ using Stw = utils::telemetry::ActiveStopwatch;
139+
140+
138141// allow DBGStream to print grb::Vector's in a lazy way (i.e., no code generated if deactivated)
139- struct dotter : grb::utils::telemetry::OutputStreamLazy {
142+ struct dotter {
140143 const grb::Vector< IOType > & v;
141- dotter ( const grb::Vector< IOType > & _v ) : v( _v ) {}
144+
142145 ResidualType operator ()() const {
143146 Ring ring;
144147 ResidualType r = 0 ;
@@ -149,7 +152,7 @@ struct dotter : grb::utils::telemetry::OutputStreamLazy {
149152
150153static inline DBGStream & operator <<( DBGStream & stream, const grb::Vector< IOType > & v ) {
151154 stream << std::setprecision ( 7 );
152- return stream << dotter ( v );
155+ return stream << DBGStream::makeLazy ( dotter{ v } );
153156}
154157
155158// various algebraic zeros
@@ -226,19 +229,17 @@ static void allocate_system_structures(
226229 const mg_controller_t & mg_controller,
227230 DistStream & logger
228231) {
229- grb::utils::Timer timer;
232+ Stw timer;
230233
231234 hpcg_data_t * data = new hpcg_data_t ( mg_sizes[ 0 ] );
232235 cg_system_data = std::unique_ptr< hpcg_data_t >( data );
233236 logger << " allocating data for the MultiGrid simulation..." ;
234- timer.reset ();
237+ timer.start ();
235238 multigrid_allocate_data ( system_levels, coarsener_levels, smoother_levels, mg_sizes, mg_controller );
236- double time = timer.time ();
237- logger << " time (ms) " << time << std::endl;
239+ logger << " time (ms) " << Stw::nano2Milli ( timer.restart () ) << std::endl;
238240
239241 // zero all vectors
240242 logger << " zeroing all vectors..." ;
241- timer.reset ();
242243 grb::RC rc = data->init_vectors ( io_zero );
243244 ASSERT_RC_SUCCESS ( rc );
244245 std::for_each ( system_levels.begin (), system_levels.end (),
@@ -253,8 +254,7 @@ static void allocate_system_structures(
253254 []( std::unique_ptr< smoothing_data_t > & s ) {
254255 ASSERT_RC_SUCCESS ( s->init_vectors ( io_zero ) );
255256 } );
256- time = timer.time ();
257- logger << " time (ms) " << time << std::endl;
257+ logger << " time (ms) " << Stw::nano2Milli ( timer.stop () ) << std::endl;
258258}
259259
260260/* *
@@ -272,18 +272,17 @@ static void build_3d_system(
272272) {
273273 constexpr size_t DIMS = 3 ;
274274 using builder_t = grb::algorithms::HPCGSystemBuilder< DIMS, coord_t , NonzeroType >;
275- grb::utils::Timer timer;
275+ Stw timer;
276276
277277 HPCGSystemParams< DIMS, NonzeroType > params = { { in.nx , in.ny , in.nz }, HALO_RADIUS,
278278 SYSTEM_DIAG_VALUE, SYSTEM_NON_DIAG_VALUE, PHYS_SYSTEM_SIZE_MIN, in.max_coarsening_levels , 2 };
279279
280280 std::vector< builder_t > mg_generators;
281281 logger << " building HPCG generators for " << ( in.max_coarsening_levels + 1 ) << " levels..." ;
282- timer.reset ();
282+ timer.start ();
283283 // construct the builder_t generator for each grid level, which depends on the system physics
284284 hpcg_build_multigrid_generators ( params, mg_generators );
285- double time = timer.time ();
286- logger << " time (ms) " << time << std::endl;
285+ logger << " time (ms) " << Stw::nano2Milli ( timer.stop () ) << std::endl;
287286 logger << " built HPCG generators for " << mg_generators.size () << " levels" << std::endl;
288287
289288 // extract the size for each level
@@ -310,34 +309,30 @@ static void build_3d_system(
310309 }
311310 logger << sizes[ DIMS - 1 ] << std::endl;
312311 logger << " populating system matrix: " ;
313- timer.reset ();
312+ timer.start ();
314313 grb::RC rc = hpcg_populate_system_matrix ( mg_generators[ i ],
315314 system_levels.at ( i )->A , logger );
316- time = timer.time ();
317315 ASSERT_RC_SUCCESS ( rc );
318- logger << " time (ms) " << time << std::endl;
316+ logger << " time (ms) " << Stw::nano2Milli ( timer. restart () ) << std::endl;
319317
320318 logger << " populating smoothing data: " ;
321- timer.reset ();
322319 rc = hpcg_populate_smoothing_data ( mg_generators[ i ], *smoother_levels[ i ],
323320 logger );
324- time = timer.time () ;
321+ logger << " time (ms) " << Stw::nano2Milli ( timer.stop () ) << std::endl ;
325322 ASSERT_RC_SUCCESS ( rc );
326- logger << " time (ms) " << time << std::endl;
327323
328324 if ( i > 0 ) {
329325 logger << " populating coarsening data: " ;
330- timer.reset ();
326+ timer.start ();
331327 if ( ! in.use_average_coarsener ) {
332328 rc = hpcg_populate_coarsener ( mg_generators[ i - 1 ], mg_generators[ i ],
333329 *coarsener_levels[ i - 1 ] );
334330 } else {
335331 rc = hpcg_populate_coarsener_avg ( mg_generators[ i - 1 ], mg_generators[ i ],
336332 *coarsener_levels[ i - 1 ] );
337333 }
338- time = timer.time () ;
334+ logger << " time (ms) " << Stw::nano2Milli ( timer.stop () ) << std::endl ;
339335 ASSERT_RC_SUCCESS ( rc );
340- logger << " time (ms) " << time << std::endl;
341336 }
342337 }
343338}
@@ -349,7 +344,7 @@ static void build_3d_system(
349344void grbProgram ( const simulation_input & in, struct output & out ) {
350345 // get user process ID
351346 const size_t pid = spmd<>::pid ();
352- grb::utils::Timer timer;
347+ Stw timer;
353348
354349 // standard logger: active only on master node
355350 dist_controller_t dist ( pid == 0 );
@@ -389,12 +384,11 @@ void grbProgram( const simulation_input & in, struct output & out ) {
389384 hpcg_runner.tolerance = residual_zero;
390385 hpcg_runner.with_preconditioning = ! in.no_preconditioning ;
391386
392- timer.reset ();
387+ timer.start ();
393388 // build the entire multi-grid system
394389 build_3d_system ( mg_runner.system_levels , coarsener.coarsener_levels , smoother.levels ,
395390 hpcg_state, in, mg_controller, logger );
396- double input_duration = timer.time ();
397- logger << " input generation time (ms): " << input_duration << std::endl;
391+ logger << " input generation time (ms): " << Stw::nano2Milli ( timer.restart () ) << std::endl;
398392
399393#ifdef HPCG_PRINT_SYSTEM
400394 if ( pid == 0 ) {
@@ -423,18 +417,16 @@ void grbProgram( const simulation_input & in, struct output & out ) {
423417 }
424418#endif
425419
426- out.times .preamble = timer.time ( );
420+ out.times .preamble = Stw::nano2Milli ( timer.restart () );
427421
428422 mg_data_t & grid_base = *mg_runner.system_levels [ 0 ];
429423
430424 // do a cold run to warm the system up
431425 logger << TEXT_HIGHLIGHT << " beginning cold run..." << std::endl;
432426 hpcg_runner.max_iterations = 1 ;
433- timer.reset ();
434427 rc = hpcg_runner ( grid_base, *hpcg_state, out.cg_out );
435- double iter_duration = timer.time () ;
428+ logger << " time (ms): " << Stw::nano2Milli ( timer.restart () ) << std::endl ;
436429 ASSERT_RC_SUCCESS ( rc );
437- logger << " time (ms): " << iter_duration << std::endl;
438430
439431 // restore CG options to user-given values
440432 hpcg_runner.max_iterations = in.max_iterations ;
@@ -445,16 +437,14 @@ void grbProgram( const simulation_input & in, struct output & out ) {
445437 // initialize CSV writers (if activated)
446438 hpcg_csv_t hpcg_csv ( hpcg_controller, { " repetition" , " time" } );
447439 mg_csv_t mg_csv ( mg_controller, { " repetition" , " level" , " mg time" , " smoother time" } );
440+ timer.reset ();
448441
449442 // do benchmark
450443 for ( size_t i = 0 ; i < in.inner_test_repetitions ; ++i ) {
451444 rc = set ( x, io_zero );
452445 ASSERT_RC_SUCCESS ( rc );
453446 logger << TEXT_HIGHLIGHT << " beginning iteration: " << i << std::endl;
454- timer.reset ();
455447 rc = hpcg_runner ( grid_base, *hpcg_state, out.cg_out );
456- iter_duration = timer.time ();
457- out.times .useful += iter_duration;
458448 ASSERT_RC_SUCCESS ( rc );
459449 hpcg_csv.add_line ( i, hpcg_runner.getElapsedNano () );
460450 logger << " repetition,duration (ns): " << hpcg_csv.last_line () << std::endl;
@@ -468,6 +458,8 @@ void grbProgram( const simulation_input & in, struct output & out ) {
468458
469459 out.inner_test_repetitions ++;
470460 }
461+ timer.stop ();
462+ out.times .useful += Stw::nano2Milli ( timer.getElapsedNano () );
471463 if ( in.evaluation_run ) {
472464 // get maximum execution time among processes
473465 rc = collectives<>::reduce ( out.times .useful , 0 , operators::max< double >() );
@@ -481,7 +473,7 @@ void grbProgram( const simulation_input & in, struct output & out ) {
481473 std::cout.imbue ( old_locale );
482474
483475 // start postamble
484- timer.reset ();
476+ timer.restart ();
485477 // set error code to caller
486478 out.error_code = rc;
487479
@@ -493,7 +485,6 @@ void grbProgram( const simulation_input & in, struct output & out ) {
493485 // output
494486 out.pinnedVector .reset ( new PinnedVector< NonzeroType >( x, SEQUENTIAL ) );
495487 // finish timing
496- out.times .postamble = timer.time ();
497488
498489 // write measurements into CSV files
499490 if ( in.hpcg_log ) {
@@ -502,6 +493,7 @@ void grbProgram( const simulation_input & in, struct output & out ) {
502493 if ( in.mg_log ) {
503494 mg_csv.write_to_file ( in.mg_csv .data () );
504495 }
496+ out.times .postamble = Stw::nano2Milli ( timer.stop () );
505497}
506498
507499#define thcout ( std::cout << TEXT_HIGHLIGHT )
0 commit comments