Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[histv7] New benchmarks for RHist and THist #116

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions root/hist/hist/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ RB_ADD_GBENCHMARK(HistBenchmarks
LIBRARIES Core Hist MathCore)

RB_ADD_GBENCHMARK(THistBenchmarks
THistFillBenchmarks.cxx
LABEL short
LIBRARIES Hist Core)
THistFillDoubleBenchmarks.cxx
THistFillFloatBenchmarks.cxx
THistFillIntBenchmarks.cxx
LABEL short
LIBRARIES Hist Core)

if(ROOT_root7_FOUND)
RB_ADD_GBENCHMARK(RHistBenchmarks
RHistFillBenchmarks.cxx
RHistFillDoubleBenchmarks.cxx
RHistFillFloatBenchmarks.cxx
RHistFillIntBenchmarks.cxx
RHistFillLongLongBenchmarks.cxx
LABEL short
LIBRARIES ROOTHist Core)
endif()
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static void ConcurrentFillArguments(benchmark::internal::Benchmark *b)
using CoordArray_t = ROOT::Experimental::Hist::RCoordArray<2>;

// Create array for x coordinates
std::vector<CoordArray_t> MakeCoorVec(int nbOfDataPoints)
static std::vector<CoordArray_t> MakeCoorVec(int nbOfDataPoints)
{
std::vector<CoordArray_t> vec;
for (int j = 0; j < nbOfDataPoints; ++j) {
Expand All @@ -45,7 +45,7 @@ std::vector<CoordArray_t> MakeCoorVec(int nbOfDataPoints)
}

// Create array for weights
std::vector<double> MakeWeightVec(int nbOfDataPoints)
std::vector<double> MakeDoubleWeightVec(int nbOfDataPoints)
{
std::vector<double> vec;
for (int j = 0; j < nbOfDataPoints; ++j) {
Expand All @@ -56,23 +56,23 @@ std::vector<double> MakeWeightVec(int nbOfDataPoints)
}

// Arrays of coordinates and weights
std::vector<CoordArray_t> coords = MakeCoorVec(3000000);
std::vector<double> weights = MakeWeightVec(3000000);
static std::vector<CoordArray_t> coords = MakeCoorVec(3000000);
std::vector<double> weightsDouble = MakeDoubleWeightVec(3000000);

// Histograms with different bin configurations for Fill
ROOT::Experimental::RH2D hist1{{10, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist2{{10, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist3{{10, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist4{{100, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist5{{100, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist6{{100, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist7{{1000, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist8{{1000, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist9{{1000, 0.1, 1.}, {1000 / 2, 0., 10.}};

std::map<int, std::map<int, ROOT::Experimental::RH2D*>> histFill = { { 10, { { 5, &hist1 }, { 50, &hist2 }, { 500, &hist3} } },
{ 100, { { 5, &hist4 }, { 50, &hist5 }, { 500, &hist6 } } },
{ 1000, { { 5, &hist7 }, { 50, &hist8 }, { 500, &hist9 } } } };
ROOT::Experimental::RH2D hist1Double{{10, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist2Double{{10, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist3Double{{10, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist4Double{{100, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist5Double{{100, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist6Double{{100, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist7Double{{1000, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist8Double{{1000, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist9Double{{1000, 0.1, 1.}, {1000 / 2, 0., 10.}};

std::map<int, std::map<int, ROOT::Experimental::RH2D*>> histFillDouble = { { 10, { { 5, &hist1Double }, { 50, &hist2Double }, { 500, &hist3Double} } },
{ 100, { { 5, &hist4Double }, { 50, &hist5Double }, { 500, &hist6Double } } },
{ 1000, { { 5, &hist7Double }, { 50, &hist8Double }, { 500, &hist9Double } } } };

static void FillHist(int nbOfDataPoints, ROOT::Experimental::RH2D * hist)
{
Expand All @@ -89,67 +89,67 @@ static void FillHist(int nbOfDataPoints, ROOT::Experimental::RH2D * hist)
}

// Benchmark for simple Fill on 2D hist
static void BM_RHist_Fill(benchmark::State &state)
static void BM_RHist_Fill_Double(benchmark::State &state)
{
int nbOfDataPoints = state.range(0);
int nbOfBinsForFirstAxis = state.range(1);
int nbOfBinsForSecondAxis = state.range(2);

auto hist = histFill[nbOfBinsForFirstAxis][nbOfBinsForSecondAxis];
auto hist = histFillDouble[nbOfBinsForFirstAxis][nbOfBinsForSecondAxis];

for (auto _ : state)
FillHist(nbOfDataPoints, hist);
}
BENCHMARK(BM_RHist_Fill) -> Apply(FillArguments);
BENCHMARK(BM_RHist_Fill_Double) -> Apply(FillArguments);

// Histograms with different bin configurations for FillN
ROOT::Experimental::RH2D hist11{{10, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist12{{10, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist13{{10, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist14{{100, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist15{{100, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist16{{100, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist17{{1000, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist18{{1000, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist19{{1000, 0.1, 1.}, {1000 / 2, 0., 10.}};

std::map<int, std::map<int, ROOT::Experimental::RH2D*>> histFillN = { { 10, { { 5, &hist11 }, { 50, &hist12 }, { 500, &hist13} } },
{ 100, { { 5, &hist14 }, { 50, &hist15 }, { 500, &hist16 } } },
{ 1000, { { 5, &hist17 }, { 50, &hist18 }, { 500, &hist19 } } } };
ROOT::Experimental::RH2D hist11Double{{10, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist12Double{{10, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist13Double{{10, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist14Double{{100, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist15Double{{100, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist16Double{{100, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist17Double{{1000, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist18Double{{1000, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2D hist19Double{{1000, 0.1, 1.}, {1000 / 2, 0., 10.}};

std::map<int, std::map<int, ROOT::Experimental::RH2D*>> histFillNDouble = { { 10, { { 5, &hist11Double }, { 50, &hist12Double }, { 500, &hist13Double} } },
{ 100, { { 5, &hist14Double }, { 50, &hist15Double }, { 500, &hist16Double } } },
{ 1000, { { 5, &hist17Double }, { 50, &hist18Double }, { 500, &hist19Double } } } };

// Benchmark for simple FillN on 2D hist
static void BM_RHist_FillN(benchmark::State &state)
static void BM_RHist_FillN_Double(benchmark::State &state)
{
int nbOfDataPoints = state.range(0);
int nbOfBinsForFirstAxis = state.range(1);
int nbOfBinsForSecondAxis = state.range(2);

auto hist = histFillN[nbOfBinsForFirstAxis][nbOfBinsForSecondAxis];
auto hist = histFillNDouble[nbOfBinsForFirstAxis][nbOfBinsForSecondAxis];

for (auto _ : state) {
// FillN without weight
hist->FillN(std::span<const CoordArray_t>(&coords[0], nbOfDataPoints), std::span<const double>(&weights[0], nbOfDataPoints));
// FillN with weights
hist->FillN(std::span<const CoordArray_t>(&coords[0], nbOfDataPoints), std::span<const double>(&weightsDouble[0], nbOfDataPoints));
// FillN without weight
hist->FillN(std::span<const CoordArray_t>(&coords[0], nbOfDataPoints));
}
}
BENCHMARK(BM_RHist_FillN) -> Apply(FillArguments);
BENCHMARK(BM_RHist_FillN_Double) -> Apply(FillArguments);

using Filler_t = ROOT::Experimental::RHistConcurrentFiller<ROOT::Experimental::RH2D, 1024>;

// Functions for benchmarking ConcurrentFill
void fillWithoutWeight(Filler_t filler, int nbOfDataPoints)
{
for (int i = 0; i < nbOfDataPoints; ++i) {
float d = static_cast< float >(i);
double d = static_cast< double >(i);
filler.Fill({d / nbOfDataPoints, d / (nbOfDataPoints / 10)});
}
}

void fillWithWeights(Filler_t filler, int nbOfDataPoints)
{
for (int i = 0; i < nbOfDataPoints; ++i) {
float d = static_cast< float >(i);
double d = static_cast< double >(i);
filler.Fill({d / nbOfDataPoints, d / (nbOfDataPoints / 10)}, d);
}
}
Expand Down
128 changes: 128 additions & 0 deletions root/hist/hist/RHistFillFloatBenchmarks.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include "ROOT/RHist.hxx"
#include "ROOT/span.hxx"

#include "benchmark/benchmark.h"

#include <iostream>
#include <future>
#include <thread>
#include <map>
#include <vector>

// Define benchmark arguments
static void FillArguments(benchmark::internal::Benchmark *b)
{
// Number of data points
for(int i = 3; i <= 3000000; i *= 100)
// Number of bins
for(int k = 10; k <= 1000; k *= 10)
b->Args({i, k, k / 2});
}

using CoordArray_t = ROOT::Experimental::Hist::RCoordArray<2>;

// Create array for x coordinates
static std::vector<CoordArray_t> MakeCoorVec(int nbOfDataPoints)
{
std::vector<CoordArray_t> vec;
for (int j = 0; j < nbOfDataPoints; ++j) {
double d = static_cast< double >(j);
vec.push_back({ d / nbOfDataPoints, d / (nbOfDataPoints / 10) });
}
return vec;
}

// Create array for weights
std::vector<float> MakeFloatWeightVec(int nbOfDataPoints)
{
std::vector<float> vec;
for (int j = 0; j < nbOfDataPoints; ++j) {
float d = static_cast< float >(j);
vec.push_back(d);
}
return vec;
}

// Arrays of coordinates and weights
static std::vector<CoordArray_t> coords = MakeCoorVec(3000000);
std::vector<float> weightsFloat = MakeFloatWeightVec(3000000);

// Histograms with different bin configurations for Fill
ROOT::Experimental::RH2F hist1Float{{10, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist2Float{{10, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist3Float{{10, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist4Float{{100, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist5Float{{100, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist6Float{{100, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist7Float{{1000, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist8Float{{1000, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist9Float{{1000, 0.1, 1.}, {1000 / 2, 0., 10.}};

std::map<int, std::map<int, ROOT::Experimental::RH2F*>> histFillFloat = { { 10, { { 5, &hist1Float }, { 50, &hist2Float }, { 500, &hist3Float} } },
{ 100, { { 5, &hist4Float }, { 50, &hist5Float }, { 500, &hist6Float } } },
{ 1000, { { 5, &hist7Float }, { 50, &hist8Float }, { 500, &hist9Float } } } };

static void FillHist(int nbOfDataPoints, ROOT::Experimental::RH2F * hist)
{
// Fill without weight
for (int i = 0; i < nbOfDataPoints; ++i) {
double d = static_cast< double >(i);
hist->Fill({d / nbOfDataPoints, d / (nbOfDataPoints / 10)});
}
// Fill with weights
for (int i = 0; i < nbOfDataPoints; ++i) {
double d = static_cast< double >(i);
float w = static_cast< float >(i);
hist->Fill({d / nbOfDataPoints, d / (nbOfDataPoints / 10)}, w);
}
}

// Benchmark for simple Fill on 2D hist
static void BM_RHist_Fill_Float(benchmark::State &state)
{
int nbOfDataPoints = state.range(0);
int nbOfBinsForFirstAxis = state.range(1);
int nbOfBinsForSecondAxis = state.range(2);

auto hist = histFillFloat[nbOfBinsForFirstAxis][nbOfBinsForSecondAxis];

for (auto _ : state)
FillHist(nbOfDataPoints, hist);
}
BENCHMARK(BM_RHist_Fill_Float) -> Apply(FillArguments);

// Histograms with different bin configurations for FillN
ROOT::Experimental::RH2F hist11Float{{10, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist12Float{{10, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist13Float{{10, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist14Float{{100, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist15Float{{100, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist16Float{{100, 0.1, 1.}, {1000 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist17Float{{1000, 0.1, 1.}, {10 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist18Float{{1000, 0.1, 1.}, {100 / 2, 0., 10.}};
ROOT::Experimental::RH2F hist19Float{{1000, 0.1, 1.}, {1000 / 2, 0., 10.}};

std::map<int, std::map<int, ROOT::Experimental::RH2F*>> histFillNFloat = { { 10, { { 5, &hist11Float }, { 50, &hist12Float }, { 500, &hist13Float} } },
{ 100, { { 5, &hist14Float }, { 50, &hist15Float }, { 500, &hist16Float } } },
{ 1000, { { 5, &hist17Float }, { 50, &hist18Float }, { 500, &hist19Float } } } };

// Benchmark for simple FillN on 2D hist
static void BM_RHist_FillN_Float(benchmark::State &state)
{
int nbOfDataPoints = state.range(0);
int nbOfBinsForFirstAxis = state.range(1);
int nbOfBinsForSecondAxis = state.range(2);

auto hist = histFillNFloat[nbOfBinsForFirstAxis][nbOfBinsForSecondAxis];

for (auto _ : state) {
// FillN with weights
hist->FillN(std::span<const CoordArray_t>(&coords[0], nbOfDataPoints), std::span<const float>(&weightsFloat[0], nbOfDataPoints));
// FillN without weight
hist->FillN(std::span<const CoordArray_t>(&coords[0], nbOfDataPoints));
}
}
BENCHMARK(BM_RHist_FillN_Float) -> Apply(FillArguments);

// // Call main()
// BENCHMARK_MAIN();
Loading