Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooBatchCompute.h
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Emmanouil Michalainas, CERN 6 January 2021
5 *
6 * Copyright (c) 2021, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
13#ifndef ROOFIT_BATCHCOMPUTE_ROOBATCHCOMPUTE_H
14#define ROOFIT_BATCHCOMPUTE_ROOBATCHCOMPUTE_H
15
16#include <ROOT/RSpan.hxx>
17
18#include <DllImport.h> //for R__EXTERN, needed for windows
19
20#include <cstddef>
21#include <initializer_list>
22#include <memory>
23#include <string>
24
25/**
26 * Namespace for dispatching RooFit computations to various backends.
27 *
28 * This namespace contains an interface for providing high-performance computation functions for use in
29 * RooAbsReal::doEval(), see RooBatchComputeInterface.
30 *
31 * Furthermore, several implementations of this interface can be created, which reside in RooBatchCompute::RF_ARCH,
32 * where RF_ARCH may be replaced by the architecture that this implementation targets, e.g. SSE, AVX, etc.
33 *
34 * Using the pointer RooBatchCompute::dispatch, a computation request can be dispatched to the fastest backend that is
35 * available on a specific platform.
36 */
37namespace RooBatchCompute {
38
39namespace CudaInterface {
40class CudaStream;
41} // namespace CudaInterface
42
43typedef std::span<const std::span<const double>> VarSpan;
44typedef std::span<double> ArgSpan;
45typedef const double *__restrict InputArr;
46
47constexpr std::size_t bufferSize = 64;
48
49int initCPU();
50int initCUDA();
51
52/// Minimal configuration struct to steer the evaluation of a single node with
53/// the RooBatchCompute library.
54class Config {
55public:
56 bool useCuda() const { return _cudaStream != nullptr; }
59
60 /// Number of threads to use for CPU batch computations and reductions.
61 /// Values smaller than two mean single-threaded evaluation. The CPU
62 /// backend may still evaluate small batches single-threaded to avoid
63 /// scheduling overhead.
65 int nThreads() const { return _nThreads; }
66
67private:
69 int _nThreads = 1;
70};
71
72enum class Architecture {
73 AVX512,
74 AVX2,
75 AVX,
76 SSE4,
77 GENERIC,
78 CUDA
79};
80
122
124 double nllSum = 0.0;
125 double nllSumCarry = 0.0;
126 std::size_t nInfiniteValues = 0;
127 std::size_t nNonPositiveValues = 0;
128 std::size_t nNaNValues = 0;
129};
130
132public:
133 virtual ~AbsBuffer() = default;
134
135 virtual double const *hostReadPtr() const = 0;
136 virtual double const *deviceReadPtr() const = 0;
137
138 virtual double *hostWritePtr() = 0;
139 virtual double *deviceWritePtr() = 0;
140
141 virtual void assignFromHost(std::span<const double> input) = 0;
142 virtual void assignFromDevice(std::span<const double> input) = 0;
143};
144
146public:
147 virtual ~AbsBufferManager() = default;
148
149 virtual std::unique_ptr<AbsBuffer> makeScalarBuffer() = 0;
150 virtual std::unique_ptr<AbsBuffer> makeCpuBuffer(std::size_t size) = 0;
151 virtual std::unique_ptr<AbsBuffer> makeGpuBuffer(std::size_t size) = 0;
152 virtual std::unique_ptr<AbsBuffer>
153 makePinnedBuffer(std::size_t size, CudaInterface::CudaStream *stream = nullptr) = 0;
154};
155
156/**
157 * \class RooBatchComputeInterface
158 * \ingroup roofit_dev_docs_batchcompute
159 * \brief The interface which should be implemented to provide optimised computation functions for implementations of
160 * RooAbsReal::doEval().
161 *
162 * The class RooBatchComputeInterface provides the mechanism for external modules (like RooFit) to call
163 * functions from the library. The power lies in the virtual functions that can resolve to different
164 * implementations for the functionality; for example, calling a function through dispatchCuda
165 * will resolve to efficient CUDA implementations.
166 *
167 * This interface contains the signatures of the compute functions of every PDF that has an optimised implementation
168 * available. These are the functions that perform the actual computations in batches.
169 *
170 * Several implementations of this interface may be provided, e.g. SSE, AVX, AVX2 etc. At run time, the fastest
171 * implementation of this interface is selected, and using a virtual call, the computation is dispatched to the best
172 * backend.
173 *
174 * \see RooBatchCompute::dispatch, RooBatchComputeClass, RF_ARCH
175 */
177public:
178 virtual ~RooBatchComputeInterface() = default;
179
180 /// Compute the values for a batch of events.
181 ///
182 /// The extra args (the last parameter) are read-only inputs for all
183 /// computers except `NormalizedPdf`, which uses them as output parameters
184 /// for its evaluation error counters. In the CUDA implementation, these
185 /// outputs are read back from the device *asynchronously*: they only
186 /// arrive in the caller's span with the next synchronizeCudaStream() call
187 /// on the stream of the passed config. The memory backing the extra args
188 /// of a `NormalizedPdf` call must therefore stay valid until that
189 /// synchronization, so it must not live on the caller's stack.
190 virtual void compute(Config const &cfg, Computer, std::span<double> output, VarSpan, ArgSpan) = 0;
191
192 virtual double reduceSum(Config const &cfg, InputArr input, size_t n) = 0;
193 virtual ReduceNLLOutput reduceNLL(Config const &cfg, std::span<const double> probas, std::span<const double> weights,
194 std::span<const double> offsetProbas) = 0;
195
196 virtual Architecture architecture() const = 0;
197 virtual std::string architectureName() const = 0;
198
199 virtual std::unique_ptr<AbsBufferManager> createBufferManager() const = 0;
200
203 /// Wait until all work that was enqueued on the stream has completed.
205};
206
207/**
208 * This dispatch pointer points to an implementation of the compute library, provided one has been loaded.
209 * Using a virtual call, computation requests are dispatched to backends with architecture-specific functions
210 * such as SSE, AVX, AVX2, etc.
211 *
212 * \see RooBatchComputeInterface, RooBatchComputeClass, RF_ARCH
213 */
216
218{
219 return dispatchCPU->architecture();
220}
221
222inline std::string cpuArchitectureName()
223{
225}
226
227inline void compute(Config cfg, Computer comp, std::span<double> output, VarSpan vars, ArgSpan extraArgs = {})
228{
229 auto dispatch = cfg.useCuda() ? dispatchCUDA : dispatchCPU;
230 dispatch->compute(cfg, comp, output, vars, extraArgs);
231}
232
233/// It is not possible to construct a std::span directly from an initializer
234/// list (probably it will be with C++26). That's why we need an explicit
235/// overload for this.
236inline void compute(Config cfg, Computer comp, std::span<double> output,
237 std::initializer_list<std::span<const double>> vars, ArgSpan extraArgs = {})
238{
239 compute(cfg, comp, output, VarSpan{vars.begin(), vars.end()}, extraArgs);
240}
241
242inline double reduceSum(Config cfg, InputArr input, size_t n)
243{
244 auto dispatch = cfg.useCuda() ? dispatchCUDA : dispatchCPU;
245 return dispatch->reduceSum(cfg, input, n);
246}
247
248inline ReduceNLLOutput reduceNLL(Config cfg, std::span<const double> probas, std::span<const double> weights,
249 std::span<const double> offsetProbas)
250{
251 auto dispatch = cfg.useCuda() ? dispatchCUDA : dispatchCPU;
252 return dispatch->reduceNLL(cfg, probas, weights, offsetProbas);
253}
254
255std::string getBatchComputeChoice();
256void setBatchComputeChoice(std::string const &value);
257
258} // End namespace RooBatchCompute
259
260#endif
#define R__EXTERN
Definition DllImport.h:26
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
virtual std::unique_ptr< AbsBuffer > makeScalarBuffer()=0
virtual ~AbsBufferManager()=default
virtual std::unique_ptr< AbsBuffer > makeCpuBuffer(std::size_t size)=0
virtual std::unique_ptr< AbsBuffer > makeGpuBuffer(std::size_t size)=0
virtual std::unique_ptr< AbsBuffer > makePinnedBuffer(std::size_t size, CudaInterface::CudaStream *stream=nullptr)=0
virtual double const * deviceReadPtr() const =0
virtual ~AbsBuffer()=default
virtual void assignFromHost(std::span< const double > input)=0
virtual double const * hostReadPtr() const =0
virtual double * deviceWritePtr()=0
virtual void assignFromDevice(std::span< const double > input)=0
virtual double * hostWritePtr()=0
Minimal configuration struct to steer the evaluation of a single node with the RooBatchCompute librar...
void setCudaStream(CudaInterface::CudaStream *cudaStream)
CudaInterface::CudaStream * _cudaStream
void setNThreads(int nThreads)
Number of threads to use for CPU batch computations and reductions.
CudaInterface::CudaStream * cudaStream() const
The interface which should be implemented to provide optimised computation functions for implementati...
virtual double reduceSum(Config const &cfg, InputArr input, size_t n)=0
virtual void synchronizeCudaStream(CudaInterface::CudaStream *) const =0
Wait until all work that was enqueued on the stream has completed.
virtual std::string architectureName() const =0
virtual std::unique_ptr< AbsBufferManager > createBufferManager() const =0
virtual CudaInterface::CudaStream * newCudaStream() const =0
virtual void deleteCudaStream(CudaInterface::CudaStream *) const =0
virtual Architecture architecture() const =0
virtual ReduceNLLOutput reduceNLL(Config const &cfg, std::span< const double > probas, std::span< const double > weights, std::span< const double > offsetProbas)=0
virtual void compute(Config const &cfg, Computer, std::span< double > output, VarSpan, ArgSpan)=0
Compute the values for a batch of events.
const Int_t n
Definition legend1.C:16
Namespace for dispatching RooFit computations to various backends.
R__EXTERN RooBatchComputeInterface * dispatchCUDA
std::span< double > ArgSpan
std::string cpuArchitectureName()
std::string getBatchComputeChoice()
void compute(Config cfg, Computer comp, std::span< double > output, VarSpan vars, ArgSpan extraArgs={})
R__EXTERN RooBatchComputeInterface * dispatchCPU
This dispatch pointer points to an implementation of the compute library, provided one has been loade...
void setBatchComputeChoice(std::string const &value)
constexpr std::size_t bufferSize
double reduceSum(Config cfg, InputArr input, size_t n)
ReduceNLLOutput reduceNLL(Config cfg, std::span< const double > probas, std::span< const double > weights, std::span< const double > offsetProbas)
Architecture cpuArchitecture()
const double *__restrict InputArr
std::span< const std::span< const double > > VarSpan
int initCPU()
Inspect hardware capabilities, and load the optimal library for RooFit computations.