CppADCodeGen 2.4.3
A C++ Algorithmic Differentiation Package with Source Code Generation
Loading...
Searching...
No Matches
job_timer.hpp
1#ifndef CPPAD_CG_JOB_TIMER_INCLUDED
2#define CPPAD_CG_JOB_TIMER_INCLUDED
3/* --------------------------------------------------------------------------
4 * CppADCodeGen: C++ Algorithmic Differentiation with Source Code Generation:
5 * Copyright (C) 2013 Ciengis
6 *
7 * CppADCodeGen is distributed under multiple licenses:
8 *
9 * - Eclipse Public License Version 1.0 (EPL1), and
10 * - GNU General Public License Version 3 (GPL3).
11 *
12 * EPL1 terms and conditions can be found in the file "epl-v10.txt", while
13 * terms and conditions for the GPL3 can be found in the file "gpl3.txt".
14 * ----------------------------------------------------------------------------
15 * Author: Joao Leal
16 */
17
18namespace CppAD {
19namespace cg {
20
24class JobType {
25private:
29 std::string _action;
33 std::string _actionEnd;
34public:
35
36 inline JobType(const std::string& action,
37 const std::string& actionEnd) :
38 _action(action),
39 _actionEnd(actionEnd) {
40 }
41
42 inline const std::string& getActionName() const {
43 return _action;
44 }
45
46 inline void setActionName(const std::string& action) {
47 _action = action;
48 }
49
50 inline const std::string& getActionEndName()const {
51 return _actionEnd;
52 }
53
54 inline void setActionEndName(const std::string& actionEnd) {
55 _actionEnd = actionEnd;
56 }
57
58 inline virtual ~JobType() {
59 }
60};
61
65template<int T = 0 >
67public:
68 static const JobType DEFAULT;
69 static const JobType LOOP_DETECTION;
70 static const JobType GRAPH;
71 static const JobType SOURCE_FOR_MODEL;
72 static const JobType SOURCE_GENERATION;
73 static const JobType COMPILING_FOR_MODEL;
74 static const JobType COMPILING;
75 static const JobType COMPILING_DYNAMIC_LIBRARY;
76 static const JobType DYNAMIC_MODEL_LIBRARY;
77 static const JobType STATIC_MODEL_LIBRARY;
78 static const JobType ASSEMBLE_STATIC_LIBRARY;
79 static const JobType JIT_MODEL_LIBRARY;
80};
81
82template<int T>
83const JobType JobTypeHolder<T>::DEFAULT("generating", "generated");
84
85template<int T>
86const JobType JobTypeHolder<T>::LOOP_DETECTION("starting loop detection", "ended loop detection");
87
88template<int T>
89const JobType JobTypeHolder<T>::GRAPH("creating operation graph for", "created operation graph for");
90
91template<int T>
92const JobType JobTypeHolder<T>::SOURCE_FOR_MODEL("source-code for model", "source-code for model");
93
94template<int T>
95const JobType JobTypeHolder<T>::SOURCE_GENERATION("generating source for", "generated source for");
96
97template<int T>
98const JobType JobTypeHolder<T>::COMPILING_FOR_MODEL("compiling object files", "compiled object files");
99
100template<int T>
101const JobType JobTypeHolder<T>::COMPILING("compiling", "compiled");
102
103template<int T>
104const JobType JobTypeHolder<T>::COMPILING_DYNAMIC_LIBRARY("compiling dynamic library", "compiled library");
105
106template<int T>
107const JobType JobTypeHolder<T>::DYNAMIC_MODEL_LIBRARY("creating library", "created library");
108
109template<int T>
110const JobType JobTypeHolder<T>::STATIC_MODEL_LIBRARY("creating library", "created library");
111
112template<int T>
113const JobType JobTypeHolder<T>::ASSEMBLE_STATIC_LIBRARY("assembling static library", "assembled static library");
114
115template<int T>
116const JobType JobTypeHolder<T>::JIT_MODEL_LIBRARY("preparing JIT library", "prepared JIT library");
117
121class Job {
122private:
126 const JobType* _type;
130 std::string _name;
134 std::chrono::steady_clock::time_point _beginTime;
138 bool _nestedJobs;
139public:
140
141 inline Job(const JobType& type,
142 const std::string& name) :
143 _type(&type),
144 _name(name),
145 _beginTime(std::chrono::steady_clock::now()),
146 _nestedJobs(false) {
147 }
148
149 inline const JobType& getType()const {
150 return *_type;
151 }
152
153 inline const std::string& name() const {
154 return _name;
155 }
156
157 inline std::chrono::steady_clock::time_point beginTime() const {
158 return _beginTime;
159 }
160
161 inline virtual ~Job() {
162 }
163
164 friend class JobTimer;
165};
166
171public:
172 using duration = std::chrono::steady_clock::duration;
173
174 virtual void jobStarted(const std::vector<Job>& job) = 0;
175
176 virtual void jobEndended(const std::vector<Job>& job,
177 duration elapsed) = 0;
178};
179
183class JobTimer : public JobTypeHolder<> {
184protected:
190private:
194 std::vector<Job> _jobs;
198 size_t _maxLineWidth;
202 size_t _indent;
206 std::ostringstream _os;
210 std::string _action;
214 std::string _actionEnd;
218 std::set<JobListener*> _listeners;
219public:
220
221 JobTimer() :
222 _verbose(false),
223 _maxLineWidth(80),
224 _indent(2) {
225 }
226
227 inline bool isVerbose() const {
228 return _verbose;
229 }
230
231 inline void setVerbose(bool verbose) {
232 _verbose = verbose;
233 }
234
235 inline size_t getMaxLineWidth() const {
236 return _maxLineWidth;
237 }
238
239 inline void setMaxLineWidth(size_t width) {
240 _maxLineWidth = width;
241 }
242
248 inline size_t getJobCount() const {
249 return _jobs.size();
250 }
251
252 inline void addListener(JobListener& l) {
253 _listeners.insert(&l);
254 }
255
256 inline bool removeListener(JobListener& l) {
257 return _listeners.erase(&l) > 0;
258 }
259
260 inline void startingJob(const std::string& jobName,
261 const JobType& type = JobTypeHolder<>::DEFAULT,
262 const std::string& prefix = "") {
263
264 _jobs.push_back(Job(type, jobName));
265
266 if (_verbose) {
267 OStreamConfigRestore osr(std::cout);
268
269 Job& job = _jobs.back();
270
271 size_t indent = 0;
272 if (_jobs.size() > 1) {
273 Job& parent = _jobs[_jobs.size() - 2]; // must be after adding job
274 if (!parent._nestedJobs) {
275 parent._nestedJobs = true;
276 std::cout << "\n";
277 }
278 indent = _indent * (_jobs.size() - 1);
279 }
280
281 _os.str("");
282 if (indent > 0) _os << std::string(indent, ' ');
283 if (!prefix.empty()) _os << prefix << " ";
284 _os << type.getActionName() << " " << job.name() << " ...";
285
286 char f = std::cout.fill();
287 std::cout << std::setw(_maxLineWidth) << std::setfill('.') << std::left << _os.str();
288 std::cout.flush();
289 std::cout.fill(f); // restore fill character
290 }
291
292 // notify listeners
293 for (JobListener* l : _listeners) {
294 l->jobStarted(_jobs);
295 }
296 }
297
298 inline void finishedJob() {
299 using namespace std::chrono;
300
301 CPPADCG_ASSERT_UNKNOWN(_jobs.size() > 0);
302
303 Job& job = _jobs.back();
304
305 std::chrono::steady_clock::duration elapsed = steady_clock::now() - job.beginTime();
306
307 if (_verbose) {
308 OStreamConfigRestore osr(std::cout);
309
310 if (job._nestedJobs) {
311 _os.str("");
312 if (!_jobs.empty())
313 _os << std::string(_indent * (_jobs.size() - 1), ' ');
314 _os << job.getType().getActionEndName() << " " << job.name() << " ...";
315
316 char f = std::cout.fill();
317 std::cout << std::setw(_maxLineWidth) << std::setfill('.') << std::left << _os.str();
318 std::cout.fill(f); // restore fill character
319 }
320
321 std::cout << " done [" << std::fixed << std::setprecision(3) << duration<float>(elapsed).count() << "]" << std::endl;
322 }
323
324 // notify listeners
325 for (JobListener* l : _listeners) {
326 l->jobEndended(_jobs, elapsed);
327 }
328
329 _jobs.pop_back();
330 }
331
332};
333
334} // END cg namespace
335} // END CppAD namespace
336
337#endif
size_t getJobCount() const