43
43
#include < graphblas/algorithms/multigrid/multigrid_v_cycle.hpp>
44
44
#include < graphblas/algorithms/multigrid/red_black_gauss_seidel.hpp>
45
45
#include < graphblas/algorithms/multigrid/single_matrix_coarsener.hpp>
46
- #include < graphblas/utils/Timer.hpp>
47
46
#include < graphblas/utils/telemetry/Telemetry.hpp>
48
47
49
48
#include < utils/argument_parser.hpp>
@@ -135,10 +134,14 @@ using hpcg_runner_t = MultiGridCGRunner< HPCGTypes, mg_runner_t, hpcg_controller
135
134
hpcg_desc, DBGStream >;
136
135
using hpcg_data_t = typename hpcg_runner_t ::HPCGInputType;
137
136
137
+ // Stopwatch type, to measure various setup phases
138
+ using Stw = utils::telemetry::ActiveStopwatch;
139
+
140
+
138
141
// 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 {
140
143
const grb::Vector< IOType > & v;
141
- dotter ( const grb::Vector< IOType > & _v ) : v( _v ) {}
144
+
142
145
ResidualType operator ()() const {
143
146
Ring ring;
144
147
ResidualType r = 0 ;
@@ -149,7 +152,7 @@ struct dotter : grb::utils::telemetry::OutputStreamLazy {
149
152
150
153
static inline DBGStream & operator <<( DBGStream & stream, const grb::Vector< IOType > & v ) {
151
154
stream << std::setprecision ( 7 );
152
- return stream << dotter ( v );
155
+ return stream << DBGStream::makeLazy ( dotter{ v } );
153
156
}
154
157
155
158
// various algebraic zeros
@@ -226,19 +229,17 @@ static void allocate_system_structures(
226
229
const mg_controller_t & mg_controller,
227
230
DistStream & logger
228
231
) {
229
- grb::utils::Timer timer;
232
+ Stw timer;
230
233
231
234
hpcg_data_t * data = new hpcg_data_t ( mg_sizes[ 0 ] );
232
235
cg_system_data = std::unique_ptr< hpcg_data_t >( data );
233
236
logger << " allocating data for the MultiGrid simulation..." ;
234
- timer.reset ();
237
+ timer.start ();
235
238
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;
238
240
239
241
// zero all vectors
240
242
logger << " zeroing all vectors..." ;
241
- timer.reset ();
242
243
grb::RC rc = data->init_vectors ( io_zero );
243
244
ASSERT_RC_SUCCESS ( rc );
244
245
std::for_each ( system_levels.begin (), system_levels.end (),
@@ -253,8 +254,7 @@ static void allocate_system_structures(
253
254
[]( std::unique_ptr< smoothing_data_t > & s ) {
254
255
ASSERT_RC_SUCCESS ( s->init_vectors ( io_zero ) );
255
256
} );
256
- time = timer.time ();
257
- logger << " time (ms) " << time << std::endl;
257
+ logger << " time (ms) " << Stw::nano2Milli ( timer.stop () ) << std::endl;
258
258
}
259
259
260
260
/* *
@@ -272,18 +272,17 @@ static void build_3d_system(
272
272
) {
273
273
constexpr size_t DIMS = 3 ;
274
274
using builder_t = grb::algorithms::HPCGSystemBuilder< DIMS, coord_t , NonzeroType >;
275
- grb::utils::Timer timer;
275
+ Stw timer;
276
276
277
277
HPCGSystemParams< DIMS, NonzeroType > params = { { in.nx , in.ny , in.nz }, HALO_RADIUS,
278
278
SYSTEM_DIAG_VALUE, SYSTEM_NON_DIAG_VALUE, PHYS_SYSTEM_SIZE_MIN, in.max_coarsening_levels , 2 };
279
279
280
280
std::vector< builder_t > mg_generators;
281
281
logger << " building HPCG generators for " << ( in.max_coarsening_levels + 1 ) << " levels..." ;
282
- timer.reset ();
282
+ timer.start ();
283
283
// construct the builder_t generator for each grid level, which depends on the system physics
284
284
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;
287
286
logger << " built HPCG generators for " << mg_generators.size () << " levels" << std::endl;
288
287
289
288
// extract the size for each level
@@ -310,34 +309,30 @@ static void build_3d_system(
310
309
}
311
310
logger << sizes[ DIMS - 1 ] << std::endl;
312
311
logger << " populating system matrix: " ;
313
- timer.reset ();
312
+ timer.start ();
314
313
grb::RC rc = hpcg_populate_system_matrix ( mg_generators[ i ],
315
314
system_levels.at ( i )->A , logger );
316
- time = timer.time ();
317
315
ASSERT_RC_SUCCESS ( rc );
318
- logger << " time (ms) " << time << std::endl;
316
+ logger << " time (ms) " << Stw::nano2Milli ( timer. restart () ) << std::endl;
319
317
320
318
logger << " populating smoothing data: " ;
321
- timer.reset ();
322
319
rc = hpcg_populate_smoothing_data ( mg_generators[ i ], *smoother_levels[ i ],
323
320
logger );
324
- time = timer.time () ;
321
+ logger << " time (ms) " << Stw::nano2Milli ( timer.stop () ) << std::endl ;
325
322
ASSERT_RC_SUCCESS ( rc );
326
- logger << " time (ms) " << time << std::endl;
327
323
328
324
if ( i > 0 ) {
329
325
logger << " populating coarsening data: " ;
330
- timer.reset ();
326
+ timer.start ();
331
327
if ( ! in.use_average_coarsener ) {
332
328
rc = hpcg_populate_coarsener ( mg_generators[ i - 1 ], mg_generators[ i ],
333
329
*coarsener_levels[ i - 1 ] );
334
330
} else {
335
331
rc = hpcg_populate_coarsener_avg ( mg_generators[ i - 1 ], mg_generators[ i ],
336
332
*coarsener_levels[ i - 1 ] );
337
333
}
338
- time = timer.time () ;
334
+ logger << " time (ms) " << Stw::nano2Milli ( timer.stop () ) << std::endl ;
339
335
ASSERT_RC_SUCCESS ( rc );
340
- logger << " time (ms) " << time << std::endl;
341
336
}
342
337
}
343
338
}
@@ -349,7 +344,7 @@ static void build_3d_system(
349
344
void grbProgram ( const simulation_input & in, struct output & out ) {
350
345
// get user process ID
351
346
const size_t pid = spmd<>::pid ();
352
- grb::utils::Timer timer;
347
+ Stw timer;
353
348
354
349
// standard logger: active only on master node
355
350
dist_controller_t dist ( pid == 0 );
@@ -389,12 +384,11 @@ void grbProgram( const simulation_input & in, struct output & out ) {
389
384
hpcg_runner.tolerance = residual_zero;
390
385
hpcg_runner.with_preconditioning = ! in.no_preconditioning ;
391
386
392
- timer.reset ();
387
+ timer.start ();
393
388
// build the entire multi-grid system
394
389
build_3d_system ( mg_runner.system_levels , coarsener.coarsener_levels , smoother.levels ,
395
390
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;
398
392
399
393
#ifdef HPCG_PRINT_SYSTEM
400
394
if ( pid == 0 ) {
@@ -423,18 +417,16 @@ void grbProgram( const simulation_input & in, struct output & out ) {
423
417
}
424
418
#endif
425
419
426
- out.times .preamble = timer.time ( );
420
+ out.times .preamble = Stw::nano2Milli ( timer.restart () );
427
421
428
422
mg_data_t & grid_base = *mg_runner.system_levels [ 0 ];
429
423
430
424
// do a cold run to warm the system up
431
425
logger << TEXT_HIGHLIGHT << " beginning cold run..." << std::endl;
432
426
hpcg_runner.max_iterations = 1 ;
433
- timer.reset ();
434
427
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 ;
436
429
ASSERT_RC_SUCCESS ( rc );
437
- logger << " time (ms): " << iter_duration << std::endl;
438
430
439
431
// restore CG options to user-given values
440
432
hpcg_runner.max_iterations = in.max_iterations ;
@@ -445,16 +437,14 @@ void grbProgram( const simulation_input & in, struct output & out ) {
445
437
// initialize CSV writers (if activated)
446
438
hpcg_csv_t hpcg_csv ( hpcg_controller, { " repetition" , " time" } );
447
439
mg_csv_t mg_csv ( mg_controller, { " repetition" , " level" , " mg time" , " smoother time" } );
440
+ timer.reset ();
448
441
449
442
// do benchmark
450
443
for ( size_t i = 0 ; i < in.inner_test_repetitions ; ++i ) {
451
444
rc = set ( x, io_zero );
452
445
ASSERT_RC_SUCCESS ( rc );
453
446
logger << TEXT_HIGHLIGHT << " beginning iteration: " << i << std::endl;
454
- timer.reset ();
455
447
rc = hpcg_runner ( grid_base, *hpcg_state, out.cg_out );
456
- iter_duration = timer.time ();
457
- out.times .useful += iter_duration;
458
448
ASSERT_RC_SUCCESS ( rc );
459
449
hpcg_csv.add_line ( i, hpcg_runner.getElapsedNano () );
460
450
logger << " repetition,duration (ns): " << hpcg_csv.last_line () << std::endl;
@@ -468,6 +458,8 @@ void grbProgram( const simulation_input & in, struct output & out ) {
468
458
469
459
out.inner_test_repetitions ++;
470
460
}
461
+ timer.stop ();
462
+ out.times .useful += Stw::nano2Milli ( timer.getElapsedNano () );
471
463
if ( in.evaluation_run ) {
472
464
// get maximum execution time among processes
473
465
rc = collectives<>::reduce ( out.times .useful , 0 , operators::max< double >() );
@@ -481,7 +473,7 @@ void grbProgram( const simulation_input & in, struct output & out ) {
481
473
std::cout.imbue ( old_locale );
482
474
483
475
// start postamble
484
- timer.reset ();
476
+ timer.restart ();
485
477
// set error code to caller
486
478
out.error_code = rc;
487
479
@@ -493,7 +485,6 @@ void grbProgram( const simulation_input & in, struct output & out ) {
493
485
// output
494
486
out.pinnedVector .reset ( new PinnedVector< NonzeroType >( x, SEQUENTIAL ) );
495
487
// finish timing
496
- out.times .postamble = timer.time ();
497
488
498
489
// write measurements into CSV files
499
490
if ( in.hpcg_log ) {
@@ -502,6 +493,7 @@ void grbProgram( const simulation_input & in, struct output & out ) {
502
493
if ( in.mg_log ) {
503
494
mg_csv.write_to_file ( in.mg_csv .data () );
504
495
}
496
+ out.times .postamble = Stw::nano2Milli ( timer.stop () );
505
497
}
506
498
507
499
#define thcout ( std::cout << TEXT_HIGHLIGHT )
0 commit comments