Unverified Commit a2643466 authored by Guolin Ke's avatar Guolin Ke Committed by GitHub
Browse files

Make timer thread-safe (#2800)

* Make timer thread-safe

* Update common.h

* refines
parent 224b8b98
...@@ -1028,60 +1028,83 @@ class AlignmentAllocator { ...@@ -1028,60 +1028,83 @@ class AlignmentAllocator {
} }
}; };
// Note: this class is not thread-safe, don't use it inside omp blocks
class Timer { class Timer {
public: public:
Timer() {} Timer() {
#ifdef TIMETAG
~Timer() { int num_threads = 1;
Print(); #pragma omp parallel
#pragma omp master
{ num_threads = omp_get_num_threads(); }
start_time_.resize(num_threads);
stats_.resize(num_threads);
#endif // TIMETAG
} }
#ifdef TIMETAG ~Timer() { Print(); }
#ifdef TIMETAG
void Start(const std::string& name) { void Start(const std::string& name) {
auto cur_time = std::chrono::steady_clock::now(); auto tid = omp_get_thread_num();
start_time_[name] = cur_time; start_time_[tid][name] = std::chrono::steady_clock::now();
} }
void Stop(const std::string& name) { void Stop(const std::string& name) {
if (stats_.find(name) == stats_.end()) { auto cur_time = std::chrono::steady_clock::now();
stats_[name] = std::chrono::duration<double, std::milli>(0); auto tid = omp_get_thread_num();
if (stats_[tid].find(name) == stats_[tid].end()) {
stats_[tid][name] = std::chrono::duration<double, std::milli>(0);
} }
stats_[name] += std::chrono::steady_clock::now() - start_time_[name]; stats_[tid][name] += cur_time - start_time_[tid][name];
} }
#else #else
void Start(const std::string&) { } void Start(const std::string&) {}
void Stop(const std::string&) { } void Stop(const std::string&) {}
#endif // TIMETAG #endif // TIMETAG
void Print() const { void Print() const {
#ifdef TIMETAG #ifdef TIMETAG
std::map<std::string, std::chrono::duration<double, std::milli>> ordered(stats_.begin(), stats_.end()); std::unordered_map<std::string, std::chrono::duration<double, std::milli>>
stats(stats_[0].begin(), stats_[0].end());
for (size_t i = 1; i < stats_.size(); ++i) {
for (auto it = stats_[i].begin(); it != stats_[i].end(); ++it) {
if (stats.find(it->first) == stats.end()) {
stats[it->first] = it->second;
} else {
stats[it->first] += it->second;
}
}
}
std::map<std::string, std::chrono::duration<double, std::milli>> ordered(
stats.begin(), stats.end());
for (auto it = ordered.begin(); it != ordered.end(); ++it) { for (auto it = ordered.begin(); it != ordered.end(); ++it) {
Log::Info("%s costs:\t %f", it->first.c_str(), it->second * 1e-3); Log::Info("%s costs:\t %f", it->first.c_str(), it->second * 1e-3);
} }
#endif // TIMETAG #endif // TIMETAG
} }
#ifdef TIMETAG
std::unordered_map<std::string, std::chrono::steady_clock::time_point> start_time_; std::vector<
std::unordered_map<std::string, std::chrono::duration<double, std::milli>> stats_; std::unordered_map<std::string, std::chrono::steady_clock::time_point>>
start_time_;
std::vector<std::unordered_map<std::string,
std::chrono::duration<double, std::milli>>>
stats_;
#endif // TIMETAG
}; };
// Note: this class is not thread-safe, don't use it inside omp blocks // Note: this class is not thread-safe, don't use it inside omp blocks
class FunctionTimer { class FunctionTimer {
public: public:
FunctionTimer(const std::string& name, Timer& timer): timer_(timer) { FunctionTimer(const std::string& name, Timer& timer) : timer_(timer) {
timer.Start(name); timer.Start(name);
#ifdef TIMETAG #ifdef TIMETAG
name_ = name; name_ = name;
#endif // TIMETAG #endif // TIMETAG
} }
~FunctionTimer() { ~FunctionTimer() { timer_.Stop(name_); }
timer_.Stop(name_);
}
private: private:
std::string name_; std::string name_;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment