/builds/MusicScience37Projects/utility-libraries/cpp-stat-bench/include/stat_bench/stat/custom_stat_output.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2021 MusicScience37 (Kenta Kabashima) |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | /*! |
17 | | * \file |
18 | | * \brief Definition of CustomStatOutput class. |
19 | | */ |
20 | | #pragma once |
21 | | |
22 | | #include <cstddef> |
23 | | #include <cstdint> |
24 | | #include <utility> |
25 | | #include <vector> |
26 | | |
27 | | #include "stat_bench/clock/duration.h" |
28 | | #include "stat_bench/custom_output_name.h" |
29 | | #include "stat_bench/stat/calc_stat.h" |
30 | | #include "stat_bench/stat/statistics.h" |
31 | | #include "stat_bench/stat_bench_exception.h" |
32 | | |
33 | | namespace stat_bench { |
34 | | namespace stat { |
35 | | |
36 | | /*! |
37 | | * \brief Enumeration of types of analysis applied to custom outputs. |
38 | | */ |
39 | | enum class CustomOutputAnalysisType : std::uint8_t { |
40 | | mean, //!< Mean per sample. |
41 | | rate_per_sec //!< Rate per sec. |
42 | | }; |
43 | | |
44 | | /*! |
45 | | * \brief Class of custom outputs with statistics. |
46 | | */ |
47 | | class CustomStatOutput { |
48 | | public: |
49 | | /*! |
50 | | * \brief Constructor. |
51 | | * |
52 | | * \param[in] name Name. |
53 | | * \param[in] threads Number of threads. |
54 | | * \param[in] samples Number of samples (including warming_up_samples). |
55 | | * \param[in] warming_up_samples Number of samples for warming up. (They're |
56 | | * ignored.) |
57 | | * \param[in] iterations Number of iterations. \param[in] |
58 | | * analysis_type Type of analysis. |
59 | | */ |
60 | | CustomStatOutput(CustomOutputName name, std::size_t threads, |
61 | | std::size_t samples, std::size_t warming_up_samples, |
62 | | std::size_t iterations, CustomOutputAnalysisType analysis_type) |
63 | 528 | : name_(std::move(name)), |
64 | 528 | threads_(threads), |
65 | 528 | samples_(samples), |
66 | 528 | warming_up_samples_(warming_up_samples), |
67 | 528 | iterations_(iterations), |
68 | 528 | analysis_type_(analysis_type) { |
69 | 528 | if (samples <= warming_up_samples) { |
70 | 0 | throw StatBenchException("Invalid number of samples."); |
71 | 0 | } |
72 | 528 | data_.reserve(threads_); |
73 | 528 | const std::size_t used_samples = samples - warming_up_samples; |
74 | 1.06k | for (std::size_t i = 0; i < threads_; ++i) { |
75 | 532 | data_.emplace_back(used_samples, 0.0); |
76 | 532 | } |
77 | 528 | } |
78 | | |
79 | | /*! |
80 | | * \brief Add a value. |
81 | | * |
82 | | * \param[in] thread_index Index of the thread. |
83 | | * \param[in] sample_index Index of the sample. |
84 | | * \param[in] val Value of the current iteration. |
85 | | */ |
86 | 781k | void add(std::size_t thread_index, std::size_t sample_index, double val) { |
87 | 781k | if (sample_index < warming_up_samples_) { |
88 | 61.1k | return; |
89 | 61.1k | } |
90 | 720k | data_.at(thread_index).at(sample_index - warming_up_samples_) += val; |
91 | 720k | } |
92 | | |
93 | | /*! |
94 | | * \brief Preprocess data. |
95 | | * |
96 | | * \param[in] durations Durations. |
97 | | */ |
98 | | void preprocess( |
99 | 526 | const std::vector<std::vector<clock::Duration>>& durations) { |
100 | 526 | const std::size_t used_samples = samples_ - warming_up_samples_; |
101 | 1.05k | for (std::size_t i = 0; i < threads_; ++i) { |
102 | 121k | for (std::size_t j = 0; j < used_samples; ++j) { |
103 | 121k | double& val = data_.at(i).at(j); |
104 | | |
105 | 121k | switch (analysis_type_) { |
106 | 150 | case CustomOutputAnalysisType::mean: |
107 | 150 | val /= static_cast<double>(iterations_); |
108 | 150 | break; |
109 | 120k | case CustomOutputAnalysisType::rate_per_sec: |
110 | 120k | val /= durations.at(i).at(j).seconds(); |
111 | 120k | break; |
112 | 121k | } |
113 | 121k | } |
114 | 528 | } |
115 | 526 | } |
116 | | |
117 | | /*! |
118 | | * \brief Calculate statistics. |
119 | | * |
120 | | * \return Statistics. |
121 | | */ |
122 | 526 | [[nodiscard]] auto stat() const -> Statistics { return calc_stat(data_); } |
123 | | |
124 | | /*! |
125 | | * \brief Get the name. |
126 | | * |
127 | | * \return Name. |
128 | | */ |
129 | 182 | [[nodiscard]] auto name() const noexcept -> const CustomOutputName& { |
130 | 182 | return name_; |
131 | 182 | } |
132 | | |
133 | | /*! |
134 | | * \brief Get data. |
135 | | * |
136 | | * \return Data. |
137 | | */ |
138 | | [[nodiscard]] auto data() const noexcept |
139 | 72 | -> const std::vector<std::vector<double>>& { |
140 | 72 | return data_; |
141 | 72 | } |
142 | | |
143 | | private: |
144 | | //! Name. |
145 | | CustomOutputName name_; |
146 | | |
147 | | //! Data. |
148 | | std::vector<std::vector<double>> data_{}; |
149 | | |
150 | | //! Number of threads. |
151 | | std::size_t threads_; |
152 | | |
153 | | //! Number of total samples. |
154 | | std::size_t samples_; |
155 | | |
156 | | //! Number of samples for warming up. |
157 | | std::size_t warming_up_samples_; |
158 | | |
159 | | //! Number of iterations. |
160 | | std::size_t iterations_; |
161 | | |
162 | | //! Type of analysis. |
163 | | CustomOutputAnalysisType analysis_type_; |
164 | | }; |
165 | | |
166 | | } // namespace stat |
167 | | } // namespace stat_bench |