11 #include "cpp-common.hh"
24 concept Integral = std::is_integral<T>::value;
26 template <
typename T,
typename I>
27 concept Averageable = Integral<I> && requires(T a, T b, I c) {
33 class StatsCollection {
35 static std::vector<StatsBase *> stats;
43 std::string stat_name;
44 std::string stat_desc;
49 StatsCollection::stats.push_back(
this);
53 void init(
const std::string &name,
const std::string &desc) {
54 this->stat_name = name;
55 this->stat_desc = desc;
58 virtual double avg()
const {
return 0; }
59 virtual std::string str()
const {
return ""; }
60 virtual std::string latex(
const std::string &prefix =
"")
const {
67 class StatsScalar :
public StatsBase {
76 StatsScalar(
bool reg =
true) : StatsBase(reg), total(0), count(0){};
78 void init(
const std::string &name,
const std::string &desc,
79 bool is_time =
false, time_unit unit = time_unit::any_unit) {
80 StatsBase::init(name, desc);
81 this->is_time = is_time;
85 friend StatsScalar operator+(StatsScalar lhs,
const auto rhs) {
91 StatsScalar &operator+=(
const auto rhs) {
98 double avg()
const override {
return total / (double)count; }
101 std::string
str()
const override {
102 std::stringstream ss;
103 ss << stat_name <<
" = " <<
avg();
106 ss <<
" (" << ns_to_hr(this->
avg()) <<
")";
109 if (stat_desc !=
"") {
110 ss <<
" # " << stat_desc;
116 std::string latex(
const std::string &prefix =
"")
const override {
117 std::string name =
"stat" + prefix + this->stat_name;
118 std::string result =
"";
119 size_t ns, us, ms, s;
121 name =
nvsl::zip(nvsl::split(name,
"_"),
"");
124 us = this->
avg() / 1000;
125 ms = this->
avg() / 1000000;
126 s = this->
avg() / 1000000000;
129 case nvsl::time_unit::s_unit:
130 result = to_latex(name, ns,
"~s", 1000000000);
132 case nvsl::time_unit::ms_unit:
133 result = to_latex(name, ns,
"~ms", 1000000);
135 case nvsl::time_unit::us_unit:
136 result = to_latex(name, ns,
"~\\us{}", 1000);
138 case nvsl::time_unit::ns_unit:
139 result = to_latex(name, ns,
"~ns", 1);
141 case nvsl::time_unit::any_unit:
143 result = to_latex(name, ns,
"~s", 1000000000);
145 result = to_latex(name, ns,
"~ms", 1000000);
147 result = to_latex(name, ns,
"~\\us{}", 1000);
149 result = to_latex(name, ns,
"~ns", 1);
153 result = result +
" % total ops = " + std::to_string(this->count);
160 class StatsNamedVector :
public StatsBase {
162 std::map<std::string, StatsScalar> vec;
166 StatsNamedVector(
bool reg =
true) : StatsBase(reg){};
168 void init(
const std::string &name,
const std::string &desc,
169 time_unit unit = time_unit::any_unit) {
170 StatsBase::init(name, desc);
174 StatsScalar &operator[](
const std::string &memb_name) {
175 const auto memb = this->vec.find(memb_name);
176 const auto exists = memb != this->vec.end();
179 vec.emplace(std::make_pair(memb_name,
false));
180 vec[memb_name].init(memb_name,
"",
false, this->unit);
183 return vec[memb_name];
187 std::string
str()
const override {
188 std::stringstream ss;
190 for (
const auto &[k, v] : this->vec) {
191 ss << this->stat_name <<
"." << k <<
" = " << v.avg() << std::endl;
197 std::string latex(
const std::string &prefix =
"")
const override {
198 std::stringstream ss;
200 for (
const auto &[k, v] : this->vec) {
201 ss << v.latex(prefix + this->stat_name) << std::endl;
208 inline StatsCollection::~StatsCollection() {
209 if (get_env_val(NVSL_GEN_STATS_ENV)) {
210 std::cout << std::endl <<
"==== Stats ====" << std::endl;
211 for (
const auto stat : StatsCollection::stats) {
212 std::cout << stat->str() << std::endl;
213 std::cerr << stat->latex() << std::endl;