Skip to content

Commit 340d809

Browse files
committed
[RF] Vectorize RooAbsBinning interface for bin index lookups
The `RooAbsBinning` interface for bin index lookups was changed to enable vectorized implementations. Instead of having the override `RooAbsBinning::binNumber()`, the binning implementations now have to override the `RooAbsBinning::binNumbers()` function to evaluate the bin indices of multiple values in one function call. The interface of `RooAbsBinning::binNumbers()` is designed to facilitate the accregation of bin indices over multiple dimensions. The former `RooAbsBinning::binNumber()` method is now implement in terms of the vectorized version, such that we automatically get wide test coverage. It was verified that this doesn't come with a performance overhead. This will greatly facilitate the vectorization of the RooHistPdf and RooHistFunc later.
1 parent 907f3ce commit 340d809

File tree

12 files changed

+68
-37
lines changed

12 files changed

+68
-37
lines changed

README/ReleaseNotes/v628/index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ The `RooAbsMinimizerFcn` class and its implementation `RooMinimizerFcn` were rem
175175
These classes are implementation details of the RooMinimizer and should not be used in your code.
176176
In the unlikely case that this causes any problem for you, please open a GitHub issue requesting to extend the RooMinimizer by the needed functionality.
177177

178+
### Vectorize `RooAbsBinning` interface for bin index lookups
179+
180+
The `RooAbsBinning` interface for bin index lookups was changed to enable vectorized implementations.
181+
Instead of having the override `RooAbsBinning::binNumber()`, the binning implementations now have to override the `RooAbsBinning::binNumbers()` function to evaluate the bin indices of multiple values in one function call.
182+
178183
## 2D Graphics Libraries
179184

180185
- Implement the option "File": The current file name is painted on the bottom right of each plot

roofit/roofitcore/inc/RooAbsBinning.h

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,44 @@ class RooAbsReal ;
2525
class RooAbsBinning : public TNamed, public RooPrintable {
2626
public:
2727

28-
RooAbsBinning(const char* name=nullptr) ;
28+
RooAbsBinning(const char* name=nullptr) : TNamed{name, name} {}
2929
RooAbsBinning(const RooAbsBinning& other, const char* name=nullptr) : TNamed(name,name), RooPrintable(other) {
3030
// Copy constructor
3131
}
3232
TObject* Clone(const char* newname=nullptr) const override { return clone(newname) ; }
3333
virtual RooAbsBinning* clone(const char* name=nullptr) const = 0 ;
34-
~RooAbsBinning() override ;
3534

3635
/// Return number of bins.
3736
Int_t numBins() const {
3837
return numBoundaries()-1 ;
3938
}
4039
virtual Int_t numBoundaries() const = 0 ;
41-
virtual Int_t binNumber(double x) const = 0 ;
40+
41+
/// Compute the bin indices for multiple values of `x`.
42+
///
43+
/// For each element in the input, the corresponding output element will be
44+
/// increased by `coef * binIdx`. This is useful for aggregating
45+
/// multi-dimensional bin indices inplace.
46+
///
47+
/// param[in] x The read-only input array of values of `x`.
48+
/// param[out] bins The output array. Note that the initial values don't get
49+
/// replaced! The result is added to the array elements.
50+
/// param[in] n The size of the input and output arrays.
51+
/// param[in] coef The multiplication factor that is applied to all calculated bin indices.
52+
virtual void binNumbers(double const * x, int * bins, std::size_t n, int coef=1) const = 0 ;
53+
54+
/// Returns the bin number corresponding to the value `x`.
55+
///
56+
/// \note This `inline` function is implemented by calling the vectorized
57+
/// function `RooAbsBinning::binNumbers()`. If you want to calculate
58+
/// the bin indices for multiple values, use that one for better
59+
/// performance.
60+
inline int binNumber(double x) const {
61+
int out = 0.0;
62+
binNumbers(&x, &out, 1);
63+
return out;
64+
}
65+
4266
virtual double binCenter(Int_t bin) const = 0 ;
4367
virtual double binWidth(Int_t bin) const = 0 ;
4468
virtual double binLow(Int_t bin) const = 0 ;

roofit/roofitcore/inc/RooBinning.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class RooBinning : public RooAbsBinning {
3838
Int_t numBoundaries() const override {
3939
return _nbins+1;
4040
}
41-
Int_t binNumber(double x) const override;
41+
void binNumbers(double const * x, int * bins, std::size_t n, int coef) const override;
4242
Int_t rawBinNumber(double x) const;
4343
virtual double nearestBoundary(double x) const;
4444

roofit/roofitcore/inc/RooLinTransBinning.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class RooLinTransBinning : public RooAbsBinning {
2929
~RooLinTransBinning() override ;
3030

3131
Int_t numBoundaries() const override { return _input->numBoundaries() ; }
32-
Int_t binNumber(double x) const override { return _input->binNumber(invTrans(x)) ; }
32+
void binNumbers(double const * x, int * bins, std::size_t n, int coef) const override;
3333
double binCenter(Int_t bin) const override { return trans(_input->binCenter(binTrans(bin))) ; }
3434
double binWidth(Int_t bin) const override { return _slope*_input->binWidth(binTrans(bin)) ; }
3535
double binLow(Int_t bin) const override { if (_slope>0) return trans(_input->binLow(binTrans(bin))) ; else return trans(_input->binHigh(binTrans(bin))) ; }

roofit/roofitcore/inc/RooParamBinning.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class RooParamBinning : public RooAbsBinning {
3333
void setRange(double xlo, double xhi) override ;
3434

3535
Int_t numBoundaries() const override { return _nbins + 1 ; }
36-
Int_t binNumber(double x) const override ;
36+
void binNumbers(double const * x, int * bins, std::size_t n, int coef) const override;
3737

3838
double lowBound() const override { return xlo()->getVal() ; }
3939
double highBound() const override { return xhi()->getVal() ; }

roofit/roofitcore/inc/RooRangeBinning.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class RooRangeBinning : public RooAbsBinning {
2828
~RooRangeBinning() override ;
2929

3030
Int_t numBoundaries() const override { return 2 ; }
31-
Int_t binNumber(double) const override { return 0 ; }
31+
void binNumbers(double const * /*x*/, int * /*bins*/, std::size_t /*n*/, int /*coef*/) const override {}
3232
double binCenter(Int_t) const override { return (_range[0] + _range[1]) / 2 ; }
3333
double binWidth(Int_t) const override { return (_range[1] - _range[0]) ; }
3434
double binLow(Int_t) const override { return _range[0] ; }

roofit/roofitcore/inc/RooUniformBinning.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class RooUniformBinning : public RooAbsBinning {
3131
void setRange(double xlo, double xhi) override ;
3232

3333
Int_t numBoundaries() const override { return _nbins + 1 ; }
34-
Int_t binNumber(double x) const override ;
34+
void binNumbers(double const * x, int * bins, std::size_t n, int coef) const override;
3535
bool isUniform() const override { return true ; }
3636

3737
double lowBound() const override { return _xlo ; }

roofit/roofitcore/src/RooAbsBinning.cxx

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,6 @@ This class defines the interface to retrieve bin boundaries, ranges etc.
3434
using namespace std;
3535

3636
ClassImp(RooAbsBinning);
37-
;
38-
39-
40-
////////////////////////////////////////////////////////////////////////////////
41-
/// Constructor
42-
43-
RooAbsBinning::RooAbsBinning(const char* name) : TNamed(name,name)
44-
{
45-
}
46-
47-
48-
49-
////////////////////////////////////////////////////////////////////////////////
50-
/// Destructor
51-
52-
RooAbsBinning::~RooAbsBinning()
53-
{
54-
}
5537

5638

5739

roofit/roofitcore/src/RooBinning.cxx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,9 +185,11 @@ inline int rawBinNumberImpl(double x, std::vector<double> const& boundaries) {
185185
/// zero is the first bin with an upper boundary above the lower bound
186186
/// of the range
187187

188-
Int_t RooBinning::binNumber(double x) const
188+
void RooBinning::binNumbers(double const * x, int * bins, std::size_t n, int coef) const
189189
{
190-
return std::max(0, std::min(_nbins, rawBinNumberImpl(x, _boundaries) - _blo));
190+
for(std::size_t i = 0; i < n; ++i) {
191+
bins[i] += coef * (std::max(0, std::min(_nbins, rawBinNumberImpl(x[i], _boundaries) - _blo)));
192+
}
191193
}
192194

193195
////////////////////////////////////////////////////////////////////////////////

roofit/roofitcore/src/RooLinTransBinning.cxx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ way that RooLinearVar does
2626

2727
#include "RooLinTransBinning.h"
2828

29+
#include <stdexcept>
30+
2931
using namespace std;
3032

3133
ClassImp(RooLinTransBinning);
@@ -113,3 +115,15 @@ void RooLinTransBinning::updateInput(const RooAbsBinning& input, double slope, d
113115
_offset = offset ;
114116
}
115117

118+
119+
void RooLinTransBinning::binNumbers(double const * x, int * bins, std::size_t n, int coef) const
120+
{
121+
// We are not allowed to modify the input array, so we can't apply the
122+
// transformation in-place and then call _input->binNumbers() without
123+
// allocating additional memory. That's why we fall back to binNumber() for
124+
// now. The RooLinTransBinning is only ever used in the RooLinearVar, so if
125+
// this ever becomes a bottleneck this could be optimized.
126+
for(std::size_t i = 0; i < n; ++i) {
127+
bins[i] += coef * _input->binNumber(invTrans(x[i]));
128+
}
129+
}

0 commit comments

Comments
 (0)