Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
Buffers.cxx
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Jonas Rembser, CERN 11/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
14
15#include <stdexcept>
16#include <functional>
17#include <queue>
18#include <map>
19
20#ifdef ROOFIT_CUDA
23#endif
24
25namespace RooFit {
26namespace Detail {
27
29public:
32 {
33 if (size != 1)
34 throw std::runtime_error("ScalarBufferContainer can only be of size 1");
35 }
36 std::size_t size() const { return 1; }
37
38 double const *cpuReadPtr() const { return &_val; }
39 double const *gpuReadPtr() const { return &_val; }
40
41 double *cpuWritePtr() { return &_val; }
42 double *gpuWritePtr() { return &_val; }
43
44private:
45 double _val;
46};
47
49public:
50 CPUBufferContainer(std::size_t size) : _vec(size) {}
51 std::size_t size() const { return _vec.size(); }
52
53 double const *cpuReadPtr() const { return _vec.data(); }
54 double const *gpuReadPtr() const
55 {
56 throw std::bad_function_call();
57 return nullptr;
58 }
59
60 double *cpuWritePtr() { return _vec.data(); }
61 double *gpuWritePtr()
62 {
63 throw std::bad_function_call();
64 return nullptr;
65 }
66
67private:
68 std::vector<double> _vec;
69};
70
71#ifdef ROOFIT_CUDA
72class GPUBufferContainer {
73public:
74 GPUBufferContainer(std::size_t size) : _arr(size) {}
75 std::size_t size() const { return _arr.size(); }
76
77 double const *cpuReadPtr() const
78 {
79 throw std::bad_function_call();
80 return nullptr;
81 }
82 double const *gpuReadPtr() const { return _arr.data(); }
83
84 double *cpuWritePtr() const
85 {
86 throw std::bad_function_call();
87 return nullptr;
88 }
89 double *gpuWritePtr() const { return const_cast<double *>(_arr.data()); }
90
91private:
93};
94
95class PinnedBufferContainer {
96public:
97 PinnedBufferContainer(std::size_t size) : _arr{size}, _gpuBuffer{size} {}
98 std::size_t size() const { return _arr.size(); }
99
100 void setCudaStream(CudaStream *stream) { _cudaStream = stream; }
101
102 double const *cpuReadPtr() const
103 {
104
105 if (_lastAccess == LastAccessType::GPU_WRITE) {
106 CudaInterface::copyDeviceToHost(_gpuBuffer.gpuReadPtr(), const_cast<double *>(_arr.data()), size(),
107 _cudaStream);
108 }
109
110 _lastAccess = LastAccessType::CPU_READ;
111 return const_cast<double *>(_arr.data());
112 }
113 double const *gpuReadPtr() const
114 {
115
116 if (_lastAccess == LastAccessType::CPU_WRITE) {
117 CudaInterface::copyHostToDevice(_arr.data(), _gpuBuffer.gpuWritePtr(), size(), _cudaStream);
118 }
119
120 _lastAccess = LastAccessType::GPU_READ;
121 return _gpuBuffer.gpuReadPtr();
122 }
123
124 double *cpuWritePtr()
125 {
126 _lastAccess = LastAccessType::CPU_WRITE;
127 return _arr.data();
128 }
129 double *gpuWritePtr()
130 {
131 _lastAccess = LastAccessType::GPU_WRITE;
132 return _gpuBuffer.gpuWritePtr();
133 }
134
135private:
136 enum class LastAccessType { CPU_READ, GPU_READ, CPU_WRITE, GPU_WRITE };
137
139 GPUBufferContainer _gpuBuffer;
140 CudaStream *_cudaStream = nullptr;
141 mutable LastAccessType _lastAccess = LastAccessType::CPU_READ;
142};
143#endif // ROOFIT_CUDA
144
145template <class Container>
146class BufferImpl : public AbsBuffer {
147public:
148 using Queue = std::queue<std::unique_ptr<Container>>;
149 using QueuesMap = std::map<std::size_t, Queue>;
150
151 BufferImpl(std::size_t size, QueuesMap &queuesMap) : _queue{queuesMap[size]}
152 {
153 if (_queue.empty()) {
154 _vec = std::make_unique<Container>(size);
155 } else {
156 _vec = std::move(_queue.front());
157 _queue.pop();
158 }
159 }
160
161 ~BufferImpl() override { _queue.emplace(std::move(_vec)); }
162
163 double const *cpuReadPtr() const override { return _vec->cpuReadPtr(); }
164 double const *gpuReadPtr() const override { return _vec->gpuReadPtr(); }
165
166 double *cpuWritePtr() override { return _vec->cpuWritePtr(); }
167 double *gpuWritePtr() override { return _vec->gpuWritePtr(); }
168
169 Container &vec() { return *_vec; }
170
171private:
172 std::unique_ptr<Container> _vec;
174};
175
178#ifdef ROOFIT_CUDA
179using GPUBuffer = BufferImpl<GPUBufferContainer>;
180using PinnedBuffer = BufferImpl<PinnedBufferContainer>;
181#endif
182
186#ifdef ROOFIT_CUDA
187 GPUBuffer::QueuesMap gpuBufferQueuesMap;
188 PinnedBuffer::QueuesMap pinnedBufferQueuesMap;
189#endif
190};
191
193{
194 _queuesMaps = std::make_unique<BufferQueuesMaps>();
195}
196
198
199std::unique_ptr<AbsBuffer> BufferManager::makeScalarBuffer()
200{
201 return std::make_unique<ScalarBuffer>(1, _queuesMaps->scalarBufferQueuesMap);
202}
203std::unique_ptr<AbsBuffer> BufferManager::makeCpuBuffer(std::size_t size)
204{
205 return std::make_unique<CPUBuffer>(size, _queuesMaps->cpuBufferQueuesMap);
206}
207#ifdef ROOFIT_CUDA
208std::unique_ptr<AbsBuffer> BufferManager::makeGpuBuffer(std::size_t size)
209{
210 return std::make_unique<GPUBuffer>(size, _queuesMaps->gpuBufferQueuesMap);
211}
212std::unique_ptr<AbsBuffer> BufferManager::makePinnedBuffer(std::size_t size, CudaStream *stream)
213{
214 auto out = std::make_unique<PinnedBuffer>(size, _queuesMaps->pinnedBufferQueuesMap);
215 out->vec().setCudaStream(stream);
216 return out;
217}
218#endif // ROOFIT_CUDA
219
220} // end namespace Detail
221} // end namespace RooFit
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
std::map< std::size_t, Queue > QueuesMap
Definition Buffers.cxx:149
std::unique_ptr< Container > _vec
Definition Buffers.cxx:172
double * gpuWritePtr() override
Definition Buffers.cxx:167
BufferImpl(std::size_t size, QueuesMap &queuesMap)
Definition Buffers.cxx:151
double * cpuWritePtr() override
Definition Buffers.cxx:166
double const * gpuReadPtr() const override
Definition Buffers.cxx:164
std::queue< std::unique_ptr< Container > > Queue
Definition Buffers.cxx:148
double const * cpuReadPtr() const override
Definition Buffers.cxx:163
std::unique_ptr< AbsBuffer > makeScalarBuffer()
Definition Buffers.cxx:199
std::unique_ptr< BufferQueuesMaps > _queuesMaps
Definition Buffers.h:58
std::unique_ptr< AbsBuffer > makeCpuBuffer(std::size_t size)
Definition Buffers.cxx:203
CPUBufferContainer(std::size_t size)
Definition Buffers.cxx:50
std::vector< double > _vec
Definition Buffers.cxx:68
double const * gpuReadPtr() const
Definition Buffers.cxx:54
double const * cpuReadPtr() const
Definition Buffers.cxx:53
A templated class for managing an array of data using a specified memory type.
ScalarBufferContainer(std::size_t size)
Definition Buffers.cxx:31
double const * gpuReadPtr() const
Definition Buffers.cxx:39
double const * cpuReadPtr() const
Definition Buffers.cxx:38
void copyDeviceToHost(const T *src, T *dest, std::size_t n, CudaStream *=nullptr)
Copies data from the CUDA device to the host.
void copyHostToDevice(const T *src, T *dest, std::size_t n, CudaStream *=nullptr)
Copies data from the host to the CUDA device.
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition JSONIO.h:26
ScalarBuffer::QueuesMap scalarBufferQueuesMap
Definition Buffers.cxx:184
CPUBuffer::QueuesMap cpuBufferQueuesMap
Definition Buffers.cxx:185