30 static const double value = []
32 const char*
const text = std::getenv(
"OPENNN_PEAK_GBPS");
33 if (text ==
nullptr)
return 0.0;
35 const double parsed = std::atof(text);
36 return parsed > 0.0 ? parsed : 0.0;
47 void add(
const string& key,
double ms,
double bytes = 0.0)
49 const std::lock_guard lock(entries_mutex);
50 Entry& entry = entries[key];
56 void set(
const string& key,
double total_ms,
long calls,
double total_bytes = 0.0)
58 if (calls <= 0)
return;
60 const std::lock_guard lock(entries_mutex);
61 entries[key] = {
total_ms, calls, total_bytes};
66 const std::lock_guard lock(entries_mutex);
72 const std::lock_guard lock(entries_mutex);
75 for (
const auto& entry : entries)
76 total += entry.second.total_ms;
83 const std::lock_guard lock(entries_mutex);
84 const auto found = entries.find(key);
85 return found == entries.end() ? 0 : found->second.calls;
89 string_view category =
"PROFILE")
const
100 string_view category =
"PROFILE")
const
102 vector<pair<string, Entry>> sorted;
104 const std::lock_guard lock(entries_mutex);
105 sorted.assign(entries.begin(), entries.end());
107 ranges::sort(sorted, greater<>{}, [](
const auto& entry) {
return entry.second.total_ms; });
109 bool any_bytes =
false;
110 for (
const auto& entry : sorted)
111 if (entry.second.total_bytes > 0.0) { any_bytes =
true;
break; }
115 os <<
"\n[" << category <<
"] " << title <<
"\n";
116 os <<
" " << left << setw(48) <<
"section"
117 << right << setw(12) <<
"total_ms"
118 << setw(10) <<
"calls"
119 << setw(12) <<
"ms/call";
120 if (
total_ms > 0.0) os << setw(8) <<
"%";
123 os << setw(14) <<
"GiB" << setw(10) <<
"GB/s";
124 if (peak > 0.0) os << setw(8) <<
"%peak";
128 for (
const auto& [key, entry] : sorted)
130 os <<
" " << left << setw(48) << key
131 << right << setw(12) << fixed << setprecision(2) << entry.total_ms
132 << setw(10) << entry.calls
133 << setw(12) << fixed << setprecision(3) << (entry.total_ms / double(entry.calls));
135 os << setw(7) << fixed << setprecision(1) << (entry.total_ms /
total_ms * 100.0) <<
"%";
139 const bool measured = entry.total_bytes > 0.0 && entry.total_ms > 0.0;
143 const double gbps = measured ? entry.total_bytes / (entry.total_ms * 1.0e6) : 0.0;
150 os << setw(14) << fixed << setprecision(6) << (entry.total_bytes / 1073741824.0)
151 << setw(10) << fixed << setprecision(1) << gbps;
153 os << setw(14) <<
"-" << setw(10) <<
"-";
172 if (measured && gbps <= peak)
173 os << setw(7) << fixed << setprecision(1) << (gbps / peak * 100.0) <<
"%";
175 os << setw(8) <<
">peak";
177 os << setw(8) <<
"-";
186 map<string, Entry> entries;
187 mutable std::mutex entries_mutex;
192 static Stats instance;
201 static std::atomic_bool enabled{std::getenv(
"OPENNN_PROFILE") !=
nullptr};
232 ScopedTimer(
string new_key,
bool synchronize_gpu =
true,
double moved_bytes = 0.0)
233 : key(std::move(new_key)),
235 sync_gpu(synchronize_gpu),
241 start = chrono::steady_clock::now();
246 void set_bytes(
double moved_bytes)
noexcept { bytes = moved_bytes; }
252 const auto end_time = chrono::steady_clock::now();
253 const double elapsed_ms = chrono::duration<double, milli>(end_time - start).count();
254 stats().
add(key, elapsed_ms, bytes);
263 chrono::steady_clock::time_point start;
274 stats().
log(
"profile (OPENNN_PROFILE)");
281#define OPENNN_PROFILE_CAT_INNER(a, b) a##b
282#define OPENNN_PROFILE_CAT(a, b) OPENNN_PROFILE_CAT_INNER(a, b)
284#define PROFILE_SCOPE_IMPL(name, sync) \
285 ::opennn::profiler::ScopedTimer OPENNN_PROFILE_CAT(_profile_, __LINE__)( \
286 ::opennn::profiler::is_enabled() ? string(name) : string{}, sync)
288#define PROFILE_SCOPE(name) PROFILE_SCOPE_IMPL(name, true)
289#define PROFILE_SCOPE_HOST(name) PROFILE_SCOPE_IMPL(name, false)
295#define PROFILE_SCOPE_BYTES(name, bytes) \
296 ::opennn::profiler::ScopedTimer OPENNN_PROFILE_CAT(_profile_, __LINE__)( \
297 ::opennn::profiler::is_enabled() ? string(name) : string{}, true, double(bytes))
301#define PROFILE_SCOPE_NAMED(timer, name) \
302 ::opennn::profiler::ScopedTimer timer( \
303 ::opennn::profiler::is_enabled() ? string(name) : string{}, true)
ScopedTimer(const ScopedTimer &)=delete
ScopedTimer & operator=(const ScopedTimer &)=delete
void set_bytes(double moved_bytes) noexcept
Definition profiler.h:246
~ScopedTimer()
Definition profiler.h:248
ScopedTimer(string new_key, bool synchronize_gpu=true, double moved_bytes=0.0)
Definition profiler.h:232
void clear()
Definition profiler.h:64
void set(const string &key, double total_ms, long calls, double total_bytes=0.0)
Definition profiler.h:56
void log(const string &title, double total_ms=0.0, string_view category="PROFILE") const
Definition profiler.h:88
void add(const string &key, double ms, double bytes=0.0)
Definition profiler.h:47
void print(ostream &os, const string &title, double total_ms=0.0, string_view category="PROFILE") const
Definition profiler.h:97
double total_ms() const
Definition profiler.h:70
long call_count(const string &key) const
Definition profiler.h:81
void synchronize(DeviceStream=nullptr)
void write(Level, std::string_view)
bool enabled(Level) noexcept
@ Info
Definition log.h:26
Definition profiler.h:197
ExitDump & exit_dump()
Definition profiler.h:211
std::atomic_bool & enabled_flag()
Definition profiler.h:199
double peak_gbps()
Definition profiler.h:28
Stats & stats()
Definition profiler.h:190
void set_enabled(bool enabled) noexcept
Definition profiler.h:224
bool is_enabled() noexcept
Definition profiler.h:219
long calls
Definition profiler.h:45
double total_bytes
Definition profiler.h:45
double total_ms
Definition profiler.h:45
Definition profiler.h:206
ExitDump()
Definition profiler.h:207
~ExitDump()
Definition profiler.h:271