#include <vector>
#include <chrono>
#include <iostream>
using TimePoint_t = decltype( std::chrono::high_resolution_clock::now() );
const char *fTitle;
size_t fCount;
TimePoint_t fStart;
Timer(
const char *title,
size_t count) : fTitle(title), fCount(count),
fStart(
std::chrono::high_resolution_clock::now()) {}
using namespace std::chrono;
auto end = high_resolution_clock::now();
duration<double> time_span = duration_cast<duration<double>>(end - fStart);
std::cout << fCount << " * " << fTitle << ": " << time_span.count() << " seconds, \t";
std::cout << fCount / (1e6) / time_span.count() << " millions per seconds \n";
}
};
struct BinEdges
{
static constexpr size_t fNBinsX = 4;
static constexpr size_t fNBinsY = 5;
double fXBins[4];
double fYBins[5];
BinEdges(double minValue, double maxValue) {
if (maxValue < minValue)
swap(minValue,maxValue);
double range = maxValue - minValue;
double x[fNBinsX] = {0., 0.1, 0.3, 1.};
double y[fNBinsY] = {0., 0.1, 0.2, 0.3, 1.};
for(size_t i = 0; i < fNBinsX; ++i)
fXBins[i] = minValue + range * x[i];
for(size_t i = 0; i < fNBinsY; ++i)
fYBins[i] = minValue + range * y[i];
}
AConf_t GetConfigX() const { return AConf_t(std::array_view<double>(fXBins).to_vector()); }
AConf_t GetConfigY() const { return AConf_t(std::array_view<double>(fYBins).to_vector()); }
};
template <typename T>
{
Timer t(
"GenerateInput",numbers.size());
if (minVal > maxVal) {
}
T range = maxVal - minVal;
size_t len = numbers.size();
for(auto c = numbers.begin(); c != numbers.end(); ++c) {
*c = minVal + range * r.
Rndm();
}
}
std::string
MakeTitle(std::string_view version,
std::string_view histname,
std::string_view title,
std::string_view axis)
{
std::string result = std::string(version) + " " + std::string(histname) + " " + title.to_string() + " [" + axis.to_string() + "]";
}
template <
int dim,
typename type>
const char *
GetHist();
template <typename T, unsigned short kNDim> struct Dim;
template <typename T>
struct Dim<T,2> {
constexpr static unsigned short kNDim = 2;
using InputType_t = double;
using FillFunc_t = std::add_pointer_t<long(ExpTH2 &hist, std::vector<InputType_t> &input, std::string_view
type)>;
struct EE {
static constexpr
const char *
const gType =
"regular bin size ";
template <FillFunc_t filler>
static long Execute(std::vector<InputType_t> &input, double minVal, double maxVal) {
ExpTH2 hist({100, minVal, maxVal}, {5, minVal, maxVal});
return filler(hist,input,gType);
}
};
struct II {
static constexpr const char * const gType = "irregular bin size";
template <FillFunc_t filler>
static long Execute(std::vector<InputType_t> &input, double minVal, double maxVal) {
BinEdges edges(minVal,maxVal);
ExpTH2 hist( edges.GetConfigX(), edges.GetConfigY() );
return filler(hist,input,gType);
}
};
inline static long fillN(ExpTH2 &hist, std::vector<InputType_t> &input, std::string_view gType) {
using array_t = std::array<InputType_t, 2>;
array_t *values = (array_t*)(&input[0]);
std::string title =
MakeTitle(gVersion, GetHist<kNDim, T>(),
"fills N (stride 32)", gType);
{
Timer t(title.c_str(),input.size()/2);
for (size_t i = 0; i < (input.size()-(stride*2-1)); i += (stride*2), values += 32)
hist.FillN({values,32});
}
return hist.GetNDim();
}
inline static long fillBuffered(ExpTH2 &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim, T>(),
"fills (buffered) ", gType);
{
Timer t(title.c_str(),input.size()/2);
for (size_t i = 0; i < input.size()-1; i += 2)
filler.Fill({input[i], input[i+1]});
}
return hist.GetNDim();
}
inline static long fill(ExpTH2 &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim, T>(),
"fills ", gType);
{
Timer t(title.c_str(),input.size()/2);
for (size_t i = 0; i < input.size()-1; i += 2)
hist.Fill({input[i], input[i+1]});
}
return hist.GetNDim();
}
};
template <typename T>
struct Dim<T,1> {
constexpr static unsigned short kNDim = 1;
using InputType_t = double;
using FillFunc_t = std::add_pointer_t<long(ExpTH1 &hist, std::vector<InputType_t> &input, std::string_view
type)>;
struct EE {
static constexpr const char * const gType = "regular bin size ";
template <FillFunc_t filler>
static long Execute(std::vector<InputType_t> &input, double minVal, double maxVal) {
ExpTH1 hist({100, minVal, maxVal});
return filler(hist,input,gType);
}
};
struct II {
static constexpr const char * const gType = "irregular bin size";
template <FillFunc_t filler>
static long Execute(std::vector<InputType_t> &input, double minVal, double maxVal) {
BinEdges edges(minVal,maxVal);
ExpTH1 hist( edges.GetConfigX() );
return filler(hist,input,gType);
}
};
inline static long fillN(ExpTH1 &hist, std::vector<InputType_t> &input, std::string_view gType) {
using array_t = std::array<InputType_t, 1>;
array_t *values = (array_t*)(&input[0]);
std::string title =
MakeTitle(gVersion, GetHist<kNDim, T>(),
"fills N (stride 32)", gType);
{
Timer t(title.c_str(),input.size());
for (size_t i = 0; i < (input.size()-(stride-1)); i += (stride), values += 32)
hist.FillN({values,32});
}
return hist.GetNDim();
}
inline static long fillBuffered(ExpTH1 &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim, T>(),
"fills (buffered) ", gType);
{
Timer t(title.c_str(),input.size());
for (size_t i = 0; i < input.size(); ++i)
filler.Fill({input[i]});
}
return hist.GetNDim();
}
inline static long fill(ExpTH1 &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim, T>(),
"fills ", gType);
{
Timer t(title.c_str(),input.size());
for (size_t i = 0; i < input.size(); ++i)
hist.Fill({input[i]});
}
return hist.GetNDim();
}
};
}
const char *gVersion = "R6";
template <int ndim, typename T> struct Redirect;
template <>
struct Redirect<2,float> {
using HistType_t =
TH2F; };
template <>
struct Redirect<2,double> {
using HistType_t =
TH2D; };
template <>
struct Redirect<1,float> {
using HistType_t =
TH1F; };
template <>
struct Redirect<1,double> {
using HistType_t =
TH1D; };
template <typename T, int kNDim> struct Dim;
template <typename T>
struct Dim<T,2> {
constexpr static unsigned short kNDim = 2;
using HistType_t = typename Redirect<kNDim,T>::HistType_t;
using InputType_t = double;
using FillFunc_t = std::add_pointer_t<long(HistType_t &hist, std::vector<InputType_t> &input, std::string_view
type)>;
struct EE {
static constexpr const char * const gType = "regular bin size ";
template <FillFunc_t filler>
static long Execute(std::vector<InputType_t> &input, double minVal, double maxVal) {
HistType_t hist("a", "a hist", 100, minVal, maxVal, 5, minVal, maxVal);
return filler(hist,input,gType);
}
};
struct II {
static constexpr const char * const gType = "irregular bin size";
template <FillFunc_t filler>
static long Execute(std::vector<InputType_t> &input, double minVal, double maxVal) {
BinEdges edges(minVal,maxVal);
HistType_t hist("a", "a hist", edges.fNBinsX - 1, edges.fXBins, edges.fNBinsY - 1, edges.fYBins);
return filler(hist,input,gType);
}
};
static long fillBuffered(HistType_t &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim,T>(),
"fills (buffered) ", gType);
{
Timer t(title.c_str(),input.size()/2);
for (size_t i = 0; i < input.size()-1; i += 2)
hist.Fill(input[i], input[i+1]);
}
return (long)hist.GetEntries();
}
static long fillN(HistType_t &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim,T>(),
"fills N (stride 32)", gType);
{
Timer t(title.c_str(),input.size()/2);
for (size_t i = 0; i < (input.size()-(stride*2-1)); i += (stride*2))
hist.FillN(gStride, &(input[i]), &(input[i+gStride]), nullptr);
}
return (long)hist.GetEntries();
}
static long fill(HistType_t &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim,T>(),
"fills ", gType);
{
Timer t(title.c_str(),input.size()/2);
for (size_t i = 0; i < input.size()-1; i += 2)
hist.Fill(input[i], input[i+1]);
}
return (long)hist.GetEntries();
}
};
template <typename T>
struct Dim<T,1> {
constexpr static unsigned short kNDim = 1;
using HistType_t = typename Redirect<kNDim,T>::HistType_t;
using InputType_t = double;
using FillFunc_t = std::add_pointer_t<long(HistType_t &hist, std::vector<InputType_t> &input, std::string_view
type)>;
struct EE {
static constexpr const char * const gType = "regular bin size ";
template <FillFunc_t filler>
static long Execute(std::vector<InputType_t> &input, double minVal, double maxVal) {
HistType_t hist("a", "a hist", 100, minVal, maxVal);
return filler(hist,input,gType);
}
};
struct II {
static constexpr const char * const gType = "irregular bin size";
template <FillFunc_t filler>
static long Execute(std::vector<InputType_t> &input, double minVal, double maxVal) {
BinEdges edges(minVal,maxVal);
HistType_t hist("a", "a hist", edges.fNBinsX - 1, edges.fXBins);
return filler(hist,input,gType);
}
};
static long fillBuffered(HistType_t &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim,T>(),
"fills (buffered) ", gType);
{
Timer t(title.c_str(),input.size());
for (size_t i = 0; i < input.size()-1; ++i)
hist.Fill(input[i]);
}
return (long)hist.GetEntries();
}
static long fillN(HistType_t &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim,T>(),
"fills N (stride 32)", gType);
{
Timer t(title.c_str(),input.size());
for (size_t i = 0; i < (input.size()-(stride-1)); i += (stride))
hist.FillN(gStride, &(input[i]), nullptr);
}
return (long)hist.GetEntries();
}
static long fill(HistType_t &hist, std::vector<InputType_t> &input, std::string_view gType) {
std::string title =
MakeTitle(gVersion, GetHist<kNDim,T>(),
"fills ", gType);
{
Timer t(title.c_str(),input.size());
for (size_t i = 0; i < input.size(); ++i)
hist.Fill(input[i]);
}
return (long)hist.GetEntries();
}
};
}
template <typename T,unsigned short kNDim>
void speedtest(
size_t count = (
size_t)(1e6));
template <>
using DataType_t = double;
using InputType_t = double;
static constexpr unsigned short kNDim = 2;
std::vector<InputType_t> input;
input.resize(count);
double minVal = -5.0;
double maxVal = +5.0;
minVal *= 0.9;
maxVal *= 0.9;
cout << '\n';
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered >(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered >(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
}
template <>
using DataType_t = float;
using InputType_t = double;
constexpr unsigned short kNDim = 2;
std::vector<InputType_t> input;
input.resize(count);
double minVal = -5.0;
double maxVal = +5.0;
minVal *= 0.9;
maxVal *= 0.9;
cout << '\n';
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered >(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered >(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
}
template <>
using DataType_t = double;
using InputType_t = double;
static constexpr unsigned short kNDim = 1;
std::vector<InputType_t> input;
input.resize(count);
double minVal = -5.0;
double maxVal = +5.0;
minVal *= 0.9;
maxVal *= 0.9;
cout << '\n';
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered >(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered >(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
}
template <>
using DataType_t = float;
using InputType_t = double;
static constexpr unsigned short kNDim = 1;
std::vector<InputType_t> input;
input.resize(count);
double minVal = -5.0;
double maxVal = +5.0;
minVal *= 0.9;
maxVal *= 0.9;
cout << '\n';
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered >(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered >(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::EE::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R7::Dim<DataType_t,kNDim>::II::Execute<R7::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::EE::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
cout << '\n';
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillBuffered>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
R6::Dim<DataType_t,kNDim>::II::Execute<R6::Dim<DataType_t,kNDim>::fillN>(input, minVal, maxVal);
}
{
}
int main(
int argc,
char **argv) {
size_t iter = 1e9;
}