Browse Source

refactor(stats): use static inline variable declaration

GitOrigin-RevId: 7d86e5f257
release-1.10
Megvii Engine Team 3 years ago
parent
commit
27d4c4b36c
15 changed files with 227 additions and 213 deletions
  1. +0
    -1
      imperative/python/src/module_trace.h
  2. +3
    -3
      imperative/python/src/tensor.cpp
  3. +0
    -1
      imperative/python/src/tensor_utils.cpp
  4. +0
    -1
      imperative/src/impl/dispatch.cpp
  5. +0
    -1
      imperative/src/impl/interpreter/interpreter_impl.cpp
  6. +0
    -1
      imperative/src/impl/ops/elemwise.cpp
  7. +0
    -1
      imperative/src/impl/ops/pooling.cpp
  8. +0
    -1
      imperative/src/impl/transformation.cpp
  9. +0
    -1
      imperative/src/impl/transformations/eval.cpp
  10. +0
    -1
      imperative/src/impl/transformations/grad.cpp
  11. +0
    -1
      imperative/src/impl/transformations/scalar.cpp
  12. +0
    -199
      imperative/src/include/megbrain/imperative/utils/stats.h
  13. +0
    -1
      imperative/src/include/megbrain/imperative/value.h
  14. +89
    -0
      src/core/impl/utils/stats.cpp
  15. +135
    -0
      src/core/include/megbrain/utils/stats.h

+ 0
- 1
imperative/python/src/module_trace.h View File

@@ -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"



+ 3
- 3
imperative/python/src/tensor.cpp View File

@@ -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; });


+ 0
- 1
imperative/python/src/tensor_utils.cpp View File

@@ -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"



+ 0
- 1
imperative/src/impl/dispatch.cpp View File

@@ -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 {


+ 0
- 1
imperative/src/impl/interpreter/interpreter_impl.cpp View File

@@ -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"


+ 0
- 1
imperative/src/impl/ops/elemwise.cpp View File

@@ -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"



+ 0
- 1
imperative/src/impl/ops/pooling.cpp View File

@@ -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"


+ 0
- 1
imperative/src/impl/transformation.cpp View File

@@ -1,5 +1,4 @@
#include "megbrain/imperative/transformation.h"
#include "megbrain/imperative/utils/stats.h"

namespace mgb {
namespace imperative {


+ 0
- 1
imperative/src/impl/transformations/eval.cpp View File

@@ -10,7 +10,6 @@
*/

#include "megbrain/imperative/transformations/eval.h"
#include "megbrain/imperative/utils/stats.h"

namespace mgb {
namespace imperative {


+ 0
- 1
imperative/src/impl/transformations/grad.cpp View File

@@ -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>



+ 0
- 1
imperative/src/impl/transformations/scalar.cpp View File

@@ -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 {


+ 0
- 199
imperative/src/include/megbrain/imperative/utils/stats.h View File

@@ -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

+ 0
- 1
imperative/src/include/megbrain/imperative/value.h View File

@@ -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 {


+ 89
- 0
src/core/impl/utils/stats.cpp View File

@@ -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

+ 135
- 0
src/core/include/megbrain/utils/stats.h View File

@@ -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

Loading…
Cancel
Save