GitOrigin-RevId: 7d86e5f257
release-1.10
@@ -14,7 +14,6 @@ | |||
#include <list> | |||
#include "megbrain/imperative/transformations/trace.h" | |||
#include "megbrain/imperative/utils/map.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
#include "./tensor.h" | |||
@@ -23,9 +23,9 @@ | |||
#include "megbrain/imperative/transformations/symbol.h" | |||
#include "megbrain/imperative/transformations/trace.h" | |||
#include "megbrain/imperative/utils/map.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
#include "megbrain/opr/io.h" | |||
#include "megbrain/plugin/profiler.h" | |||
#include "megbrain/utils/stats.h" | |||
#include "./common.h" | |||
#include "./grad.h" | |||
@@ -1367,9 +1367,9 @@ void init_tensor(py::module m) { | |||
return reprs; | |||
}); | |||
m.def("print_stats", [] { imperative::Stats::print(); }); | |||
m.def("print_stats", [] { Stats::print(); }); | |||
m.def("reset_stats", [] { imperative::Stats::reset(); }); | |||
m.def("reset_stats", [] { Stats::reset(); }); | |||
m.def("_get_convert_inputs", | |||
[]() -> bool { return DTypePromoteCfg::convert_input_enabled; }); | |||
@@ -21,7 +21,6 @@ | |||
#include "megbrain/imperative/transformations/symbol.h" | |||
#include "megbrain/imperative/transformations/trace.h" | |||
#include "megbrain/imperative/utils/map.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
#include "megbrain/opr/io.h" | |||
#include "megbrain/plugin/profiler.h" | |||
@@ -14,7 +14,6 @@ | |||
#include "megbrain/imperative/utils/debug.h" | |||
#include "megbrain/imperative/utils/helper.h" | |||
#include "megbrain/imperative/utils/map.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
namespace mgb { | |||
namespace imperative { | |||
@@ -19,7 +19,6 @@ | |||
#include "megbrain/imperative/ops/backward_graph.h" | |||
#include "megbrain/imperative/ops/opr_attr.h" | |||
#include "megbrain/imperative/ops/utility.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
#include "megbrain/imperative/utils/to_string.h" | |||
#include "../blob_manager_impl.h" | |||
@@ -11,7 +11,6 @@ | |||
#include "megbrain/imperative/opr_utility.h" | |||
#include "megbrain/imperative/ops/autogen.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
#include "megbrain/opr/basic_arith.h" | |||
#include "megbrain/opr/utility.h" | |||
@@ -11,7 +11,6 @@ | |||
#include "megbrain/opr/dnn/pooling.h" | |||
#include "megbrain/imperative/ops/autogen.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
#include "megbrain/opr/utility.h" | |||
#include "megbrain/opr/internal/megdnn_opr_wrapper.h" | |||
@@ -1,5 +1,4 @@ | |||
#include "megbrain/imperative/transformation.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
namespace mgb { | |||
namespace imperative { | |||
@@ -10,7 +10,6 @@ | |||
*/ | |||
#include "megbrain/imperative/transformations/eval.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
namespace mgb { | |||
namespace imperative { | |||
@@ -15,7 +15,6 @@ | |||
#include "megbrain/imperative/graph_cache.h" | |||
#include "megbrain/imperative/resource_manager.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
#include <range/v3/all.hpp> | |||
@@ -13,7 +13,6 @@ | |||
#include "megbrain/imperative/ops/autogen.h" | |||
#include "megbrain/imperative/ops/utility.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
namespace mgb { | |||
namespace imperative { | |||
@@ -1,199 +0,0 @@ | |||
#pragma once | |||
#include <chrono> | |||
#include <iostream> | |||
#include <map> | |||
#include <memory> | |||
#include <string> | |||
#include <unordered_map> | |||
#include <vector> | |||
namespace mgb { | |||
namespace imperative { | |||
namespace stats { | |||
#define MGE_ENABLE_STATS 0 | |||
class Timer { | |||
public: | |||
using clock_t = std::chrono::system_clock; | |||
private: | |||
clock_t::duration m_duration = clock_t::duration{0}; | |||
size_t m_timing = 0; | |||
std::string m_name; | |||
uint64_t m_count = 0; | |||
size_t m_enabled = 1; | |||
bool m_default_enabled = true; | |||
struct TimeScopeRecursive { | |||
Timer& timer; | |||
clock_t::time_point start; | |||
bool released = false; | |||
TimeScopeRecursive(Timer& timer) : timer(timer) { | |||
if (timer.m_enabled && !timer.m_timing++) { | |||
start = clock_t::now(); | |||
} | |||
} | |||
~TimeScopeRecursive() { release(); } | |||
void release() { | |||
if (released) { | |||
return; | |||
} | |||
if (timer.m_enabled) { | |||
if (!--timer.m_timing) { | |||
auto duration = (clock_t::now() - start); | |||
timer.m_duration += duration; | |||
} | |||
timer.m_count++; | |||
} | |||
released = true; | |||
} | |||
}; | |||
struct EnableScope { | |||
Timer& timer; | |||
bool released = false; | |||
EnableScope(Timer& timer) : timer(timer) { timer.m_enabled++; } | |||
~EnableScope() { release(); } | |||
void release() { | |||
if (released) { | |||
return; | |||
} | |||
timer.m_enabled--; | |||
released = true; | |||
} | |||
}; | |||
public: | |||
Timer(std::string name, bool default_enabled = true); | |||
std::string name() { return m_name; } | |||
auto time_scope_recursive() { return TimeScopeRecursive(*this); }; | |||
auto enable_scope() { return EnableScope(*this); } | |||
void reset() { | |||
m_duration = clock_t::duration{0}; | |||
m_count = 0; | |||
m_enabled = m_default_enabled ? 1 : 0; | |||
} | |||
clock_t::duration get() const { return m_duration; } | |||
uint64_t count() const { return m_count; } | |||
}; | |||
} // namespace stats | |||
struct Stats { | |||
struct TimerNode { | |||
std::map<std::string, std::unique_ptr<TimerNode>> children; | |||
stats::Timer* timer = nullptr; | |||
TimerNode() {} | |||
}; | |||
static inline TimerNode sm_root; | |||
// register your timers here | |||
// for example: | |||
// | |||
// static inline stats::Timer mytimer; | |||
// | |||
// then use MGE_TIMER_SCOPE(mytimer) to collect durations in your code | |||
static std::pair<long, long> print_node( | |||
std::string name, TimerNode& node, size_t indent = 0) { | |||
auto print_indent = [&] { | |||
for (size_t i = 0; i < indent; ++i) { | |||
printf(" "); | |||
} | |||
}; | |||
long ns = 0, count = 0; | |||
if (auto* timer = node.timer) { | |||
print_indent(); | |||
printf("%s costs %'ld ns, hits %'ld times\n", name.c_str(), | |||
(long)timer->get().count(), (long)timer->count()); | |||
ns = timer->get().count(); | |||
count = timer->count(); | |||
} | |||
if (!node.children.empty()) { | |||
bool collect_children = node.timer == nullptr; | |||
if (collect_children) { | |||
print_indent(); | |||
printf("%s:\n", name.c_str()); | |||
} | |||
long ns = 0, count = 0; | |||
for (auto&& child : node.children) { | |||
auto [child_ns, child_count] = | |||
print_node(child.first, *child.second, indent + 4); | |||
if (collect_children) { | |||
ns += child_ns; | |||
count += child_count; | |||
} | |||
} | |||
if (collect_children) { | |||
print_indent(); | |||
printf("total costs %'ld ns, hits %'ld times\n", ns, count); | |||
} | |||
} | |||
return {ns, count}; | |||
} | |||
static void print() { | |||
for (auto&& child : sm_root.children) { | |||
print_node(child.first, *child.second); | |||
} | |||
} | |||
static void reset() { | |||
auto reset_node = [](TimerNode& node, auto&& reset_node) -> void { | |||
if (auto* timer = node.timer) { | |||
timer->reset(); | |||
} | |||
for (auto&& child : node.children) { | |||
reset_node(*child.second, reset_node); | |||
} | |||
}; | |||
reset_node(sm_root, reset_node); | |||
} | |||
}; | |||
inline stats::Timer::Timer(std::string name, bool default_enabled) | |||
: m_name(name), m_default_enabled(default_enabled) { | |||
std::vector<std::string> terms; | |||
Stats::TimerNode* node = &Stats::sm_root; | |||
while (true) { | |||
auto pos = name.find("."); | |||
if (pos == std::string::npos) { | |||
auto& child = node->children[name]; | |||
child = std::make_unique<Stats::TimerNode>(); | |||
node = child.get(); | |||
node->timer = this; | |||
break; | |||
} else { | |||
auto& child = node->children[name.substr(0, pos)]; | |||
if (!child) { | |||
child = std::make_unique<Stats::TimerNode>(); | |||
} | |||
node = child.get(); | |||
name = name.substr(pos + 1); | |||
} | |||
} | |||
} | |||
#if MGE_ENABLE_STATS | |||
#define MGE_TIMER_SCOPE(name) auto name = Stats::name.time_scope_recursive() | |||
#define MGE_TIMER_SCOPE_RELEASE(name) name.release() | |||
#define MGE_TIMER_SCOPE_ENABLE(name) auto name = Stats::name.enable_scope() | |||
#else | |||
#define MGE_TIMER_SCOPE(name) (void)0 | |||
#define MGE_TIMER_SCOPE_RELEASE(name) (void)0 | |||
#define MGE_TIMER_SCOPE_ENABLE(name) (void)0 | |||
#endif | |||
} // namespace imperative | |||
} // namespace mgb |
@@ -23,7 +23,6 @@ | |||
#include "megbrain/imperative/utils/debug.h" | |||
#include "megbrain/imperative/utils/local_ptr.h" | |||
#include "megbrain/imperative/utils/span.h" | |||
#include "megbrain/imperative/utils/stats.h" | |||
namespace mgb { | |||
namespace imperative { | |||
@@ -0,0 +1,89 @@ | |||
#include "megbrain/utils/stats.h" | |||
namespace mgb { | |||
Stats::TimerNode Stats::sm_root; | |||
stats::Timer& Stats::get_timer(std::string name) { | |||
auto full_name = name; | |||
Stats::TimerNode* node = &Stats::sm_root; | |||
while (true) { | |||
auto pos = name.find("_"); | |||
if (pos == std::string::npos) { | |||
auto& child = node->children[name]; | |||
child = std::make_unique<Stats::TimerNode>(); | |||
node = child.get(); | |||
auto& timer = node->timer; | |||
if (!timer) { | |||
timer = std::make_unique<stats::Timer>(full_name); | |||
} | |||
return *timer; | |||
} else { | |||
auto& child = node->children[name.substr(0, pos)]; | |||
if (!child) { | |||
child = std::make_unique<Stats::TimerNode>(); | |||
} | |||
node = child.get(); | |||
name = name.substr(pos + 1); | |||
} | |||
} | |||
} | |||
std::pair<long, long> Stats::print_node( | |||
std::string name, TimerNode& node, size_t indent) { | |||
auto print_indent = [&] { | |||
for (size_t i = 0; i < indent; ++i) { | |||
printf(" "); | |||
} | |||
}; | |||
long ns = 0, count = 0; | |||
if (auto& timer = node.timer) { | |||
print_indent(); | |||
printf("%s costs %'ld ns, hits %'ld times\n", name.c_str(), | |||
(long)timer->get().count(), (long)timer->count()); | |||
ns = timer->get().count(); | |||
count = timer->count(); | |||
} | |||
if (!node.children.empty()) { | |||
bool collect_children = node.timer == nullptr; | |||
if (collect_children) { | |||
print_indent(); | |||
printf("%s:\n", name.c_str()); | |||
} | |||
long ns = 0, count = 0; | |||
for (auto&& child : node.children) { | |||
auto&& child_res = print_node(child.first, *child.second, indent + 4); | |||
auto&& child_ns = child_res.first; | |||
auto&& child_count = child_res.second; | |||
if (collect_children) { | |||
ns += child_ns; | |||
count += child_count; | |||
} | |||
} | |||
if (collect_children) { | |||
print_indent(); | |||
printf("total costs %'ld ns, hits %'ld times\n", ns, count); | |||
} | |||
} | |||
return {ns, count}; | |||
} | |||
void Stats::print() { | |||
for (auto&& child : sm_root.children) { | |||
print_node(child.first, *child.second); | |||
} | |||
} | |||
void Stats::reset() { | |||
auto reset_node = [](TimerNode& node, auto&& reset_node) -> void { | |||
if (auto& timer = node.timer) { | |||
timer->reset(); | |||
} | |||
for (auto&& child : node.children) { | |||
reset_node(*child.second, reset_node); | |||
} | |||
}; | |||
reset_node(sm_root, reset_node); | |||
} | |||
} // namespace mgb |
@@ -0,0 +1,135 @@ | |||
#pragma once | |||
#include <chrono> | |||
#include <iostream> | |||
#include <map> | |||
#include <memory> | |||
#include <string> | |||
#include <unordered_map> | |||
#include <vector> | |||
#include "megbrain/common.h" | |||
namespace mgb { | |||
namespace stats { | |||
#define MGE_ENABLE_STATS 1 | |||
class Timer { | |||
public: | |||
using clock_t = std::chrono::system_clock; | |||
private: | |||
clock_t::duration m_duration = clock_t::duration{0}; | |||
size_t m_timing = 0; | |||
std::string m_name; | |||
uint64_t m_count = 0; | |||
size_t m_enabled = 1; | |||
bool m_default_enabled = true; | |||
struct TimeScopeRecursive { | |||
Timer& timer; | |||
clock_t::time_point start; | |||
bool released = false; | |||
TimeScopeRecursive(Timer& timer) : timer(timer) { | |||
if (timer.m_enabled && !timer.m_timing++) { | |||
start = clock_t::now(); | |||
} | |||
} | |||
~TimeScopeRecursive() { release(); } | |||
void release() { | |||
if (released) { | |||
return; | |||
} | |||
if (timer.m_enabled) { | |||
if (!--timer.m_timing) { | |||
auto duration = (clock_t::now() - start); | |||
timer.m_duration += duration; | |||
} | |||
timer.m_count++; | |||
} | |||
released = true; | |||
} | |||
}; | |||
struct EnableScope { | |||
Timer& timer; | |||
bool released = false; | |||
EnableScope(Timer& timer) : timer(timer) { timer.m_enabled++; } | |||
~EnableScope() { release(); } | |||
void release() { | |||
if (released) { | |||
return; | |||
} | |||
timer.m_enabled--; | |||
released = true; | |||
} | |||
}; | |||
public: | |||
Timer(std::string name, bool default_enabled = true) | |||
: m_name(name), m_default_enabled(default_enabled){}; | |||
std::string name() { return m_name; } | |||
auto time_scope_recursive() { return TimeScopeRecursive(*this); }; | |||
auto enable_scope() { return EnableScope(*this); } | |||
void reset() { | |||
m_duration = clock_t::duration{0}; | |||
m_count = 0; | |||
m_enabled = m_default_enabled ? 1 : 0; | |||
} | |||
clock_t::duration get() const { return m_duration; } | |||
uint64_t count() const { return m_count; } | |||
}; | |||
} // namespace stats | |||
struct Stats { | |||
private: | |||
struct TimerNode { | |||
std::map<std::string, std::unique_ptr<TimerNode>> children; | |||
std::unique_ptr<stats::Timer> timer; | |||
}; | |||
static TimerNode sm_root; | |||
// don't register your timers here | |||
// use MGE_TIMER_SCOPE(mytimer) to collect durations in your code | |||
public: | |||
MGE_WIN_DECLSPEC_FUC static stats::Timer& get_timer(std::string name); | |||
MGE_WIN_DECLSPEC_FUC static std::pair<long, long> print_node( | |||
std::string name, TimerNode& node, size_t indent = 0); | |||
MGE_WIN_DECLSPEC_FUC static void print(); | |||
MGE_WIN_DECLSPEC_FUC static void reset(); | |||
}; | |||
#if MGE_ENABLE_STATS | |||
#define MGE_TIMER_SCOPE(name) \ | |||
static auto& _timer_##name = mgb::Stats::get_timer(#name); \ | |||
auto name = _timer_##name.time_scope_recursive() | |||
#define MGE_TIMER_SCOPE_RELEASE(name) name.release() | |||
#define MGE_TIMER_SCOPE_ENABLE(name) \ | |||
static auto& _timer_##name = mgb::Stats::get_timer(#name); \ | |||
auto name = _timer_##name.enable_scope() | |||
#else | |||
#define MGE_TIMER_SCOPE(name) (void)0 | |||
#define MGE_TIMER_SCOPE_RELEASE(name) (void)0 | |||
#define MGE_TIMER_SCOPE_ENABLE(name) (void)0 | |||
#endif | |||
} // namespace mgb |