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) {
35 static std::vector<StatsBase *> stats;
43 std::string stat_name;
44 std::string stat_desc;
49 #ifdef NVSL_ENABLE_COLLECTION_REGISTRATION
50 StatsCollection::stats.push_back(
this);
55 void init(
const std::string &name,
const std::string &desc) {
56 this->stat_name = name;
57 printf(
"Stat name = %s\n", this->stat_name.c_str());
58 this->stat_desc = desc;
61 virtual double avg()
const {
return 0; }
62 virtual std::string str()
const {
return ""; }
63 virtual std::string latex(
const std::string &prefix =
"")
const {
73 template <
typename T =
size_t>
77 T bucket_min, bucket_max, bucket_sz;
78 size_t *counts, underflow_cnt, overflow_cnt;
96 void init(
const std::string &name,
const std::string &desc,
97 size_t bucket_cnt, T bucket_min, T bucket_max) {
99 NVSL_ASSERT(bucket_cnt != 0,
"Bucket size cannot be zero");
101 "Bucket max cannot be smaller than bucket min");
103 assert(bucket_cnt != 0 &&
"Bucket size cannot be zero");
104 assert(bucket_max > bucket_min &&
105 "Bucket max cannot be smaller than bucket min");
108 StatsBase::init(name, desc);
110 this->bucket_cnt = bucket_cnt;
111 this->bucket_min = bucket_min;
112 this->bucket_max = bucket_max;
113 this->bucket_sz = (bucket_max-bucket_min)/bucket_cnt;
114 this->underflow_cnt = 0;
115 this->overflow_cnt = 0;
117 this->counts =
new size_t[bucket_cnt];
118 memset(counts, 0,
sizeof(counts[0])*bucket_cnt);
126 void add(T val,
size_t count = 1) {
127 if (val < bucket_min) {
129 }
else if (val >= bucket_max) {
132 size_t bucket_idx = (val-bucket_min)/bucket_sz;
133 counts[bucket_idx]++;
142 return underflow_cnt + overflow_cnt +
143 std::accumulate(counts, counts+bucket_cnt, 0);
152 return counts[bucket];
162 return (underflow_cnt ? this->underflow_cnt : 0) +
163 (overflow_cnt ? this->overflow_cnt : 0);
170 std::stringstream ss;
171 ss << stat_name +
".bucket_count: " << bucket_cnt <<
"\t# " + stat_desc <<
"\n"
172 << stat_name +
".bucket_min: " << bucket_min <<
"\t# " + stat_desc <<
"\n"
173 << stat_name +
".bucket_max: " << bucket_max <<
"\t# " + stat_desc <<
"\n"
174 << stat_name +
".bucket_size: " << bucket_sz <<
"\t# " + stat_desc <<
"\n"
175 << stat_name +
".underflow_count: " << underflow_cnt <<
"\t# " + stat_desc <<
"\n"
176 << stat_name +
".overflow_count: " << overflow_cnt <<
"\t# " + stat_desc <<
"\n";
178 for (
size_t i = 0; i < bucket_cnt; i++) {
179 ss << stat_name +
".bucket[" << i <<
"]: " << counts[i] << std::endl;
192 printf(
"Counter constructed\n");
195 void init(
const std::string &name,
const std::string &desc) {
196 StatsBase::init(name, desc);
211 size_t value()
const {
212 return this->counter;
216 std::string
str()
const override {
217 std::stringstream ss;
218 ss << StatsBase::stat_name <<
" = " << value();
220 if (stat_desc !=
"") {
221 ss <<
" # " << stat_desc;
240 void init(
const std::string &name,
const std::string &desc,
241 bool is_time =
false, time_unit unit = time_unit::any_unit) {
242 StatsBase::init(name, desc);
243 this->is_time = is_time;
260 double avg()
const override {
return total / (double)count; }
263 std::string
str()
const override {
264 std::stringstream ss;
265 ss << stat_name <<
" = " <<
avg();
268 ss <<
" (" << ns_to_hr(this->
avg()) <<
")";
271 if (stat_desc !=
"") {
272 ss <<
" # " << stat_desc;
278 std::string latex(
const std::string &prefix =
"")
const override {
279 std::string name =
"stat" + prefix + this->stat_name;
280 std::string result =
"";
281 size_t ns, us, ms, s;
283 name =
nvsl::zip(nvsl::split(name,
"_"),
"");
286 us = this->
avg() / 1000;
287 ms = this->
avg() / 1000000;
288 s = this->
avg() / 1000000000;
291 case nvsl::time_unit::s_unit:
292 result = to_latex(name, ns,
"~s", 1000000000);
294 case nvsl::time_unit::ms_unit:
295 result = to_latex(name, ns,
"~ms", 1000000);
297 case nvsl::time_unit::us_unit:
298 result = to_latex(name, ns,
"~\\us{}", 1000);
300 case nvsl::time_unit::ns_unit:
301 result = to_latex(name, ns,
"~ns", 1);
303 case nvsl::time_unit::any_unit:
305 result = to_latex(name, ns,
"~s", 1000000000);
307 result = to_latex(name, ns,
"~ms", 1000000);
309 result = to_latex(name, ns,
"~\\us{}", 1000);
311 result = to_latex(name, ns,
"~ns", 1);
315 result = result +
" % total ops = " + std::to_string(this->count);
324 std::map<std::string, StatsScalar> vec;
330 void init(
const std::string &name,
const std::string &desc,
331 time_unit unit = time_unit::any_unit) {
332 StatsBase::init(name, desc);
336 StatsScalar &operator[](
const std::string &memb_name) {
337 const auto memb = this->vec.find(memb_name);
338 const auto exists = memb != this->vec.end();
341 vec.emplace(std::make_pair(memb_name,
false));
342 vec[memb_name].init(memb_name,
"",
false, this->unit);
345 return vec[memb_name];
349 std::string
str()
const override {
350 std::stringstream ss;
352 for (
const auto &[k, v] : this->vec) {
353 ss << this->stat_name <<
"." << k <<
" = " << v.avg() << std::endl;
359 std::string latex(
const std::string &prefix =
"")
const override {
360 std::stringstream ss;
362 for (
const auto &[k, v] : this->vec) {
363 ss << v.latex(prefix + this->stat_name) << std::endl;
370 inline StatsCollection::~StatsCollection() {
371 if (get_env_val(NVSL_GEN_STATS_ENV)) {
372 std::cout << std::endl <<
"==== Stats ====" << std::endl;
373 for (
const auto stat : StatsCollection::stats) {
374 std::cout << stat->str() << std::endl;
375 std::cerr << stat->latex() << std::endl;