Peano
Loading...
Searching...
No Matches
Statistics.cpp
Go to the documentation of this file.
1#include "Statistics.h"
2#include "tarch/Assertions.h"
4#include "tarch/mpi/Rank.h"
5
7
8#include <fstream>
9
10
12tarch::logging::Log tarch::logging::Statistics::_log( "tarch::logging::Statistics" );
14
15
20
21
22
24 _maxCountInBetweenTwoMeasurements(1000),
25 _maxTimeInBetweenTwoMeasurements(1.0),
26 _globalWatch( "tarch::logging::Statistics", "Statistics", false) {
27}
28
29
30
32 _watch("tarch::logging::Statistics", "Statistics", false),
33 _counter(0) {
34}
35
36
38 _watch("tarch::logging::Statistics", "Statistics", false),
39 _counter(0) {
40 _data.push_back( std::make_tuple(time,0.0,0.0,0.0,0) );
41}
42
43
45 std::ostringstream msg;
46 msg << "(#" << _data.size() << ", ("
47 << std::get<0>( _data.back() ) << ", "
48 << std::get<1>( _data.back() ) << ", "
49 << std::get<2>( _data.back() ) << ", "
50 << std::get<3>( _data.back() ) << ", "
51 << std::get<4>( _data.back() ) << "))";
52 return msg.str();
53}
54
55
56void tarch::logging::Statistics::DataSet::createNewSnapshot(double time, bool clearAfterDatabaseDump) {
57 double lastValueFromPreviousSnapshot = clearAfterDatabaseDump ? 0.0 : std::get<1>( _data.back() );
58 _data.push_back( std::make_tuple(
59 time,
60 lastValueFromPreviousSnapshot,
61 lastValueFromPreviousSnapshot,
62 lastValueFromPreviousSnapshot,
63 0
64 ));
65}
66
67
71
72
73bool tarch::logging::Statistics::acceptNewData(const std::string& identifier, bool disableSampling) {
74 _dataSetMap[identifier]._counter++;
75 _dataSetMap[identifier]._watch.stop();
76
77 bool result = false;
78
79 if (
80 disableSampling
81 ) {
82 result = true;
83 }
84 else if (
85 _dataSetMap[identifier]._data.size()>1
86 and
87 std::get<1>( _dataSetMap[identifier]._data[_dataSetMap[identifier]._data.size()-1] ) == std::get<1>( _dataSetMap[identifier]._data[_dataSetMap[identifier]._data.size()-2] )
88 ) {
89 result = false;
90 }
91 else if (
93 or
94 _dataSetMap[identifier]._watch.getCalendarTime() > _maxTimeInBetweenTwoMeasurements
95 ) {
96 result = true;
97 }
98
99 if (result) {
100 _dataSetMap[identifier]._counter = 0;
101 _dataSetMap[identifier]._watch.start();
102 return true;
103 }
104 else return false;
105}
106
107
108void tarch::logging::Statistics::initData(const std::string& identifier) {
109 if ( _dataSetMap.count( identifier )==0 ) {
111 double t = _globalWatch.getCalendarTime();
112
113 _dataSetMap.insert( std::pair<std::string,DataSet>( identifier, DataSet(t) ));
114 }
115}
116
117
118void tarch::logging::Statistics::updateDataSnapshot(const std::string& identifier, double value) {
119 assertion( _dataSetMap.count( identifier )==1 );
120 std::get<1>( _dataSetMap[identifier]._data.back() ) = value;
121 std::get<2>( _dataSetMap[identifier]._data.back() ) = std::min(std::get<2>( _dataSetMap[identifier]._data.back() ), value);
122 std::get<3>( _dataSetMap[identifier]._data.back() ) = std::max(std::get<3>( _dataSetMap[identifier]._data.back() ), value);
123 std::get<4>( _dataSetMap[identifier]._data.back() ) = 1 + std::get<4>( _dataSetMap[identifier]._data.back() );
124}
125
126
127#ifdef TrackStatistics
128void tarch::logging::Statistics::log( const std::string& identifier, const std::string& value ) {
130 if ( _logMessageMap.count( identifier )==0 ) {
131 _logMessageMap.insert( std::pair< std::string, LogMessage >( identifier, LogMessage() ) );
132 }
133
135 double t = _globalWatch.getCalendarTime();
136
137 _logMessageMap[identifier]._data.push_back( std::tuple<double,std::string>(t,value) );
138}
139
140
141void tarch::logging::Statistics::log( const std::string& identifier, double value, bool disableSampling ) {
143 initData(identifier);
144 updateDataSnapshot(identifier,value);
145 if ( acceptNewData(identifier, disableSampling) ) {
147 double t = _globalWatch.getCalendarTime();
148 logDebug( "log(string,double)", identifier << "=" << value );
149 _dataSetMap[identifier].createNewSnapshot(t, false);
150 }
151}
152
153
154void tarch::logging::Statistics::inc( const std::string& identifier, double value, bool disableSampling, bool clearAfterDatabaseDump ) {
156 initData( identifier );
157
158 double newValue = std::get<1>( _dataSetMap[identifier]._data.back() ) + value;
159 updateDataSnapshot(identifier,newValue);
160
161 if ( acceptNewData(identifier, disableSampling) ) {
163 double t = _globalWatch.getCalendarTime();
164 _dataSetMap[identifier].createNewSnapshot(t, clearAfterDatabaseDump);
165 }
166}
167#endif
168
169
170void tarch::logging::Statistics::writeToCSV( [[maybe_unused]] std::string filename ) {
171#ifdef TrackStatistics
172 logDebug( "writeToCSV(string)", "start to dump statistics into file " << filename );
173
174 if (tarch::mpi::Rank::getInstance().getNumberOfRanks()>0 ) {
175 filename += "-rank-" + std::to_string( tarch::mpi::Rank::getInstance().getRank() );
176 }
177
178 filename += ".csv";
179
180 // only for stats
181 int totalNumberOfEntries = 0;
182 for (auto& p: _dataSetMap) {
183 totalNumberOfEntries += p.second._data.size();
184 }
185 for (auto& p: _logMessageMap) {
186 totalNumberOfEntries += p.second._data.size();
187 }
188 logInfo( "writeToCSV(string)", "write statistics to file " << filename << " (total no of entries=" << totalNumberOfEntries << ")" );
189
190 std::ofstream file( filename );
191 file << "t";
192 for (auto& p: _dataSetMap) {
193 file << ", " << p.first;
194 }
195 for (auto& p: _logMessageMap) {
196 file << ", " << p.first;
197 }
198 file << std::endl;
199
200 double t = 0.0;
201 while (t<std::numeric_limits<double>::max()) {
202 // find minimum time stamp over both types of logs
203 t = std::numeric_limits<double>::max();
204
205 auto computeT = [&](double currentT) {
206 t = std::min( t, currentT );
207 };
208
209 for (auto& p: _dataSetMap) {
210 if (not p.second._data.empty()) {
211 computeT( std::get<0>(p.second._data.front()) );
212 }
213 }
214 for (auto& p: _logMessageMap) {
215 if (not p.second._data.empty()) {
216 computeT( std::get<0>(p.second._data.front()) );
217 }
218 }
219
220 // plot data. If an entry is a fit, remove it from sequence
221 if (t<std::numeric_limits<double>::max()) {
222 file << t;
223 for (auto& p: _dataSetMap) {
224 if (
225 not p.second._data.empty()
226 and
227 tarch::la::smallerEquals( std::get<0>(p.second._data.front()), t )
228 ) {
229 file << ", (" << std::get<1>(p.second._data.front())
230 << "/" << std::get<2>(p.second._data.front())
231 << "/" << std::get<3>(p.second._data.front())
232 << "/#" << std::get<4>(p.second._data.front())
233 << ")";
234 p.second._data.erase(p.second._data.begin());
235 }
236 else {
237 file << ", ";
238 }
239 }
240 for (auto& pp: _logMessageMap) {
241 if (
242 not pp.second._data.empty()
243 and
244 tarch::la::smallerEquals( std::get<0>(pp.second._data.front()), t )
245 ) {
246 file << ", \"" << std::get<1>(pp.second._data.front()) << "\" ";
247 pp.second._data.erase(pp.second._data.begin());
248 file << ", ";
249 }
250 else {
251 file << ", ";
252 }
253 }
254 }
255 file << std::endl;
256 }
257
258 // clear maps. Within this clear, I get seg faults on some computers when the program terminates
259 _dataSetMap.clear();
260 _logMessageMap.clear();
261
262 // close output file
263 file.close();
264 #else
265 logWarning( "writeToCSV(string)", "no statistics available. Recompile with -DTrackStatistics for runtime sampling" );
266 #endif
267}
#define assertion(expr)
#define logDebug(methodName, logMacroMessageStream)
Definition Log.h:50
#define logWarning(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:440
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:411
Log Device.
Definition Log.h:516
Global statistics interface.
Definition Statistics.h:72
tarch::timing::Watch _globalWatch
Definition Statistics.h:156
void log(const std::string &identifier, double value, bool disableSampling=false)
Definition Statistics.h:105
std::map< std::string, LogMessage > _logMessageMap
Definition Statistics.h:195
void updateDataSnapshot(const std::string &identifier, double value)
Updates snapshot.
void initData(const std::string &identifier)
Ensures that dataset is there.
void writeToCSV(std::string filename="statistics")
Write data to csv file.
void inc(const std::string &identifier, double value=1.0, bool disableSampling=false, bool clearAfterDatabaseDump=false)
Definition Statistics.h:107
std::map< std::string, DataSet > _dataSetMap
Mapping from identifier who wrote stats (key) onto DataSet.
Definition Statistics.h:194
static tarch::multicore::BooleanSemaphore _semaphore
Definition Statistics.h:151
static Statistics _singleton
Definition Statistics.h:147
bool acceptNewData(const std::string &identifier, bool disableSampling)
Not const, as it also updates the internal counters.
static Statistics & getInstance()
This is not the canonical realisation of singletons as I use it usually for stats in Peano.
static Rank & getInstance()
This operation returns the singleton instance.
Definition Rank.cpp:543
Create a lock around a boolean semaphore region.
Definition Lock.h:19
double getCalendarTime()
This method returns the elapsed calendar time between the start and stop command of the timer,...
Definition Watch.cpp:74
void stop()
Stop timer.
Definition Watch.cpp:55
bool smallerEquals(double lhs, double rhs, double tolerance=NUMERICAL_ZERO_DIFFERENCE)
One data set for one type (identifier) of statistics.
Definition Statistics.h:168
DataSet()
As we hold data sets within a map, we need a default constructor.
void createNewSnapshot(double t, bool clearAfterDatabaseDump)
std::vector< std::tuple< double, double, double, double, int > > _data
Definition Statistics.h:174