Remove template dependance on float/double in util::statistics_log_bucket
This commit is contained in:
parent
5042fbbf7e
commit
3dde4d6b55
2 changed files with 59 additions and 17 deletions
|
|
@ -21,7 +21,7 @@ namespace psemek::prof
|
||||||
profiler_tree * parent = nullptr;
|
profiler_tree * parent = nullptr;
|
||||||
std::mutex * mutex = nullptr;
|
std::mutex * mutex = nullptr;
|
||||||
|
|
||||||
util::statistics_log_bucket<double, 0.05> execution_time;
|
util::statistics_log_bucket<double> execution_time{0.05};
|
||||||
|
|
||||||
std::map<std::string, profiler_tree> children;
|
std::map<std::string, profiler_tree> children;
|
||||||
std::vector<std::map<std::string, profiler_tree>::iterator> children_list;
|
std::vector<std::map<std::string, profiler_tree>::iterator> children_list;
|
||||||
|
|
|
||||||
|
|
@ -197,10 +197,19 @@ namespace psemek::util
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, T Precision>
|
template <typename T>
|
||||||
struct statistics_log_bucket
|
struct statistics_log_bucket
|
||||||
: statistics_lite<T>
|
: statistics_lite<T>
|
||||||
{
|
{
|
||||||
|
statistics_log_bucket(T precision);
|
||||||
|
statistics_log_bucket(statistics_log_bucket && other);
|
||||||
|
|
||||||
|
statistics_log_bucket & operator = (statistics_log_bucket && other);
|
||||||
|
|
||||||
|
T precision() const { return precision_; }
|
||||||
|
|
||||||
|
T bucket_size() const { return precision() / std::log(T{2}); }
|
||||||
|
|
||||||
// Only accepts non-negative values
|
// Only accepts non-negative values
|
||||||
void push(T const & value, std::size_t count = 1);
|
void push(T const & value, std::size_t count = 1);
|
||||||
|
|
||||||
|
|
@ -209,34 +218,64 @@ namespace psemek::util
|
||||||
statistics_lite<T> & lite() { return *this; }
|
statistics_lite<T> & lite() { return *this; }
|
||||||
statistics_lite<T> const & lite() const { return *this; }
|
statistics_lite<T> const & lite() const { return *this; }
|
||||||
|
|
||||||
template <typename H, H P>
|
template <typename H>
|
||||||
friend statistics_log_bucket<H, P> merge(statistics_log_bucket<H, P> const & s1, statistics_log_bucket<H, P> const & s2);
|
friend statistics_log_bucket<H> merge(statistics_log_bucket<H> const & s1, statistics_log_bucket<H> const & s2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr T bucket_size = Precision / std::log(2.0);
|
T precision_;
|
||||||
|
|
||||||
std::size_t zero_count_ = 0;
|
std::size_t zero_count_ = 0;
|
||||||
util::spatial_array<detail::base_statistics<T>, 1, int> buckets_;
|
util::spatial_array<detail::base_statistics<T>, 1, int> buckets_;
|
||||||
mutable util::spatial_array<std::size_t, 1, int> prefix_count_;
|
mutable util::spatial_array<std::size_t, 1, int> prefix_count_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, T Precision>
|
template <typename T>
|
||||||
void statistics_log_bucket<T, Precision>::push(T const & value, std::size_t count)
|
statistics_log_bucket<T>::statistics_log_bucket(T precision)
|
||||||
|
: precision_(precision)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
statistics_log_bucket<T>::statistics_log_bucket(statistics_log_bucket && other)
|
||||||
|
: precision_(other.precision_)
|
||||||
|
, zero_count_(other.zero_count_)
|
||||||
|
, buckets_(std::move(other.buckets_))
|
||||||
|
, prefix_count_(std::move(other.prefix_count_))
|
||||||
|
{
|
||||||
|
other.zero_count_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
statistics_log_bucket<T> & statistics_log_bucket<T>::operator = (statistics_log_bucket && other)
|
||||||
|
{
|
||||||
|
if (this == &other)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
precision_ = other.precision_;
|
||||||
|
zero_count_ = other.zero_count_;
|
||||||
|
buckets_ = std::move(other.buckets_);
|
||||||
|
prefix_count_ = std::move(other.prefix_count_);
|
||||||
|
other.zero_count_ = 0;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void statistics_log_bucket<T>::push(T const & value, std::size_t count)
|
||||||
{
|
{
|
||||||
lite().push(value, count);
|
lite().push(value, count);
|
||||||
if (value == T{0}) [[unlikely]]
|
if (value == T{0}) [[unlikely]]
|
||||||
++zero_count_;
|
++zero_count_;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int const bucket = std::floor(std::log2(value) / bucket_size);
|
int const bucket = std::floor(std::log2(value) / bucket_size());
|
||||||
buckets_.get(bucket).push(value, count);
|
buckets_.get(bucket).push(value, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
prefix_count_.clear();
|
prefix_count_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, T Precision>
|
template <typename T>
|
||||||
T statistics_log_bucket<T, Precision>::percentile(double p) const
|
T statistics_log_bucket<T>::percentile(double p) const
|
||||||
{
|
{
|
||||||
if (prefix_count_.empty())
|
if (prefix_count_.empty())
|
||||||
{
|
{
|
||||||
|
|
@ -261,24 +300,27 @@ namespace psemek::util
|
||||||
|
|
||||||
int bucket = buckets_.min(0) + (it - prefix_count_.begin());
|
int bucket = buckets_.min(0) + (it - prefix_count_.begin());
|
||||||
|
|
||||||
double min = std::exp2(bucket * bucket_size);
|
double min = std::exp2(bucket * bucket_size());
|
||||||
double max = std::exp2((bucket + 1) * bucket_size);
|
double max = std::exp2((bucket + 1) * bucket_size());
|
||||||
double q = double(index - *it) / (*(it + 1) - *it);
|
double q = double(index - *it) / (*(it + 1) - *it);
|
||||||
|
|
||||||
return buckets_.at(bucket).percentile(q, min, max);
|
return buckets_.at(bucket).percentile(q, min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, T Precision>
|
template <typename T>
|
||||||
std::ostream & operator << (std::ostream & os, statistics_log_bucket<T, Precision> const & s)
|
std::ostream & operator << (std::ostream & os, statistics_log_bucket<T> const & s)
|
||||||
{
|
{
|
||||||
os << s.lite();
|
os << s.lite();
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, T Precision>
|
template <typename T>
|
||||||
statistics_log_bucket<T, Precision> merge(statistics_log_bucket<T, Precision> const & s1, statistics_log_bucket<T, Precision> const & s2)
|
statistics_log_bucket<T> merge(statistics_log_bucket<T> const & s1, statistics_log_bucket<T> const & s2)
|
||||||
{
|
{
|
||||||
statistics_log_bucket<T, Precision> result;
|
if (s1.precision() != s2.precision())
|
||||||
|
throw util::exception("Cannot merge log-bucket statistics of different precision");
|
||||||
|
|
||||||
|
statistics_log_bucket<T> result(s1.precision());
|
||||||
result.lite() = merge(s1.lite(), s2.lite());
|
result.lite() = merge(s1.lite(), s2.lite());
|
||||||
|
|
||||||
for (int bucket = s1.buckets_.min(0); bucket < s1.buckets_.max(0); ++bucket)
|
for (int bucket = s1.buckets_.min(0); bucket < s1.buckets_.max(0); ++bucket)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue