VIPRA Documentation
Loading...
Searching...
No Matches
timing.hpp
1#pragma once
2
3#ifdef VIPRA_TIME_SIM
4
5#include <algorithm>
6#include <ios>
7
8#ifdef VIPRA_USE_MPI
9#include <mpi.h>
10#endif
11
12#include <cstdint>
13#include <filesystem>
14#include <fstream>
15#include <stdexcept>
16#include <vector>
17
18#include "vipra/util/clock.hpp"
19#include "vipra/util/mpi_util.hpp"
20
21namespace VIPRA::Util {
22class Timings {
23 public:
24 using time_t = Util::nano;
25
26 void start_new() { _clock.start(); }
27 void pause() { _clock.pause(); }
28 void resume() { _clock.resume(); }
29 void stop() { _times.emplace_back(_clock.stop()); }
30
31 static void set_output_file(std::filesystem::path const& filepath)
32 {
33 timingPath = filepath;
34 }
35
36#ifdef VIPRA_USE_MPI
37 void output_timings()
38 {
39 stop();
40
41 std::vector<int64_t> timings(_times.size());
42 std::transform(
43 _times.begin(), _times.end(), timings.begin(),
44 [](Util::nano const& time) { return static_cast<int64_t>(time.count()); });
45
46 auto [allTimings, counts] = Util::mpi_gather_all_vectors<int64_t>(timings);
47
48 Util::master_do([&]() { output_timings_file(allTimings, counts, timingPath); });
49
50 MPI_Barrier(MPI_COMM_WORLD);
51 }
52
53 void output_timings_file(std::vector<int64_t> const& timings,
54 std::vector<int> const& counts,
55 std::filesystem::path const& filepath)
56 {
57 std::ofstream file(filepath, std::ios_base::app);
58
59 if ( ! file.is_open() )
60 throw std::runtime_error("Unable to open timings output file: " +
61 filepath.string());
62
63 size_t start{0};
64
65 for ( int i = 0; i < counts.size(); ++i ) {
66 file << _name << i << ',';
67
68 for ( int j = 0; j < counts[i]; ++j ) {
69 file << time_string(static_cast<time_t>(timings[start + j]));
70 if ( j != counts[i] - 1 ) file << ',';
71 }
72
73 start += counts[i];
74 file << '\n';
75 }
76
77 file.close();
78 }
79#else
80 void output_timings()
81 {
82 std::ofstream file(timingPath, std::ios_base::app);
83
84 if ( ! file.is_open() )
85 throw std::runtime_error("Unable to open timings output file: " +
86 timingPath.string());
87
88 file << _name << ',';
89
90 for ( size_t timeIdx = 0; timeIdx < _times.size(); ++timeIdx ) {
91 file << time_string(static_cast<time_t>(_times[timeIdx]));
92 if ( timeIdx != _times.size() - 1 ) file << ',';
93 }
94
95 file << '\n';
96
97 file.close();
98 }
99#endif
100 Timings() = default;
101 ~Timings() = default;
102 Timings(Timings&&) = default;
103 auto operator=(const Timings&) -> Timings& = default;
104 auto operator=(Timings&&) -> Timings& = default;
105 Timings(Timings const&) = default;
106 explicit Timings(char const* name) : _name(name) {}
107
108 private:
109 std::string _name;
110 Util::Clock<time_t> _clock;
111 std::vector<time_t> _times;
112
113 static std::filesystem::path timingPath;
114};
115} // namespace VIPRA::Util
116
117#else
118
119#include <filesystem>
120
121namespace VIPRA::Util {
122class Timings {
123 public:
124 explicit Timings(char const* /*unused*/) noexcept {}
125 void start_new() const noexcept {}
126 void pause() const noexcept {}
127 void resume() const noexcept {}
128 void stop() const noexcept {}
129 void output_timings() const noexcept {}
130 void output_timings(std::filesystem::path const& /*output file*/) const noexcept {}
131 static void set_output_file(std::filesystem::path const& /*filepath*/) noexcept {}
132};
133} // namespace VIPRA::Util
134#endif
Definition timing.hpp:122