Logo ROOT  
Reference Guide
BatchData.cxx
Go to the documentation of this file.
1 // Author: Stephan Hageboeck, CERN 12 Apr 2019
2 
3 /*****************************************************************************
4  * RooFit
5  * Authors: *
6  * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7  * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8  * *
9  * Copyright (c) 2000-2019, Regents of the University of California *
10  * and Stanford University. All rights reserved. *
11  * *
12  * Redistribution and use in source and binary forms, *
13  * with or without modification, are permitted according to the terms *
14  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15  *****************************************************************************/
16 
17 #include "BatchData.h"
18 
19 #include <ostream>
20 #include <iomanip>
21 
22 namespace BatchHelpers {
23 
24 ///////////////////////////////////////////////////////////////////////////
25 /// Return the status of the batch starting at `begin`.
26 /// \param[in] begin Start of the batch.
27 /// \param[in] normSet Optional normSet pointer to distinguish differently normalised computations.
28 /// \param[in] ownerTag Optional owner tag. This avoids reusing batch memory for e.g. getVal() and getLogVal().
29 /// \return One state of the Status_t enum.
30 BatchData::Status_t BatchData::status(std::size_t begin, const RooArgSet* const normSet, Tag_t ownerTag) const {
31  if (_foreignData)
32  return begin < _foreignData->size() ? kReadyAndConstant : kNoBatch;
33  else if (_ownedBatches.empty())
34  return kNoBatch;
35 
36  auto item = _ownedBatches.find(std::make_tuple(begin, normSet, ownerTag));
37  if (item != _ownedBatches.end()) {
38  return item->second.status;
39  } else if ( (item = findEnclosingBatch(begin, normSet, ownerTag)) != _ownedBatches.end() ){
40  // We didn't find a batch that starts with `begin`, but `begin` might be
41  // inside of an existing batch. This search is slower.
42  return item->second.status;
43  }
44 
45  return kNoBatch;
46 }
47 
48 
49 ///////////////////////////////////////////////////////////////////////////
50 /// Set the status of a batch with the given properties.
51 ///
52 /// The status of foreign read-only data will never change.
53 /// \param[in] begin Begin index of the batch.
54 /// \param[in] size Size of the batch for checking that enough data is available.
55 /// \param[in] normSet Optional normSet pointer to destinguish differently normalised computations.
56 /// \param[in] ownerTag Optional owner tag. This avoids reusing batch memory for e.g. getVal() and getLogVal().
57 /// \return True if status successfully set, false if no such batch / not writable.
58 bool BatchData::setStatus(std::size_t begin, std::size_t size, Status_t stat,
59  const RooArgSet* const normSet, Tag_t ownerTag) {
60  if (_foreignData)
61  return false;
62 
63  auto item = _ownedBatches.find(std::make_tuple(begin, normSet, ownerTag));
64  if (item == _ownedBatches.end() || size != item->second.data.size())
65  return false;
66 
67  item->second.status = stat;
68  return true;
69 }
70 
71 
72 ///////////////////////////////////////////////////////////////////////////
73 /// Retrieve an existing batch.
74 ///
75 /// \param[in] begin Begin index of the batch.
76 /// \param[in] maxSize Requested size. Batch may come out smaller than this.
77 /// \param[in] normSet Optional normSet pointer to distinguish differently normalised computations.
78 /// \param[in] ownerTag Optional owner tag. This avoids reusing batch memory for e.g. getVal() and getLogVal().
79 /// \return Non-mutable contiguous batch data.
80 RooSpan<const double> BatchData::getBatch(std::size_t begin, std::size_t maxSize,
81  const RooArgSet* const normSet, Tag_t ownerTag) const {
82  if (_foreignData) {
83  if (begin >= _foreignData->size())
84  return {};
85 
86  const double* dataBegin = &*(_foreignData->begin()+begin);
87  maxSize = std::min(maxSize, _foreignData->size() - begin);
88  return RooSpan<const double>(dataBegin, maxSize);
89  }
90 
91  if (_ownedBatches.empty())
92  return {};
93 
94  const auto item = _ownedBatches.find(std::make_tuple(begin, normSet, ownerTag));
95  if (item == _ownedBatches.end()) {
96  // If requesting a batch inside another, a slower search algorithm must be used
97  return createSpanInsideExistingBatch(begin, maxSize, normSet, ownerTag);
98  }
99 
100  const auto& batch = item->second;
101  maxSize = std::min(maxSize, batch.data.size() - (begin-batch.begin));
102 
103  return RooSpan<const double>(batch.data.data(), maxSize);
104 }
105 
106 
107 ////////////////////////////////////////////////////////////////////////////////
108 /// Make a batch and return a span pointing to the pdf-local memory.
109 /// The batch status is switched to `kWriting`, but the batch is not initialised.
110 /// If a batch at this start point exists, the storage will be resized to fit the required
111 /// size.
112 ///
113 /// \param[in] begin Begin of the batch.
114 /// \param[in] batchSize Size of the batch.
115 /// \param[in] normSet Optional normSet pointer to distinguish differently normalised computations.
116 /// \param[in] ownerTag Optional owner tag. This avoids reusing batch memory for e.g. getVal() and getLogVal().
117 /// \return An uninitialised RooSpan starting at event `begin`.
118 RooSpan<double> BatchData::makeWritableBatchUnInit(std::size_t begin, std::size_t batchSize,
119  const RooArgSet* const normSet, Tag_t ownerTag) {
120  auto item = _ownedBatches.find(std::make_tuple(begin, normSet, ownerTag));
121  if (item == _ownedBatches.end()) {
122  auto inserted = _ownedBatches.emplace(std::piecewise_construct,
123  std::forward_as_tuple(begin, normSet, ownerTag),
124  std::forward_as_tuple(Batch{begin, std::vector<double>(batchSize), kWriting}));
125  return RooSpan<double>(inserted.first->second.data);
126  }
127 
128  Batch& batch = item->second;
129  batch.status = kWriting;
130  if (batch.data.size() != batchSize) {
131  batch.data.resize(batchSize);
132  }
133 
134  return RooSpan<double>(batch.data);
135 }
136 
137 
138 ////////////////////////////////////////////////////////////////////////////////
139 /// Make a batch and return a span pointing to the pdf-local memory.
140 /// Calls makeWritableBatchUnInit() and initialises the memory.
141 ///
142 /// \param[in] begin Begin of the batch.
143 /// \param[in] batchSize End of the batch (not included)
144 /// \param[in] value Value to initialise with (defaults to 0.).
145 /// \param[in] normSet Optional normSet pointer to distinguish differently normalised computations.
146 /// \param[in] ownerTag Optional owner tag. This avoids reusing batch memory for e.g. getVal() and getLogVal().
147 /// \return An initialised RooSpan starting at event `begin`.
148 RooSpan<double> BatchData::makeWritableBatchInit(std::size_t begin, std::size_t batchSize, double value,
149  const RooArgSet* const normSet, Tag_t ownerTag) {
150  auto batch = makeWritableBatchUnInit(begin, batchSize, normSet, ownerTag);
151  for (auto& elm : batch) {
152  elm = value;
153  }
154 
155  return batch;
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 /// Attach a foreign storage. Batches coming from this storage will be read only.
160 void BatchData::attachForeignStorage(const std::vector<double>& vec) {
161  clear();
162 
163  _foreignData = &vec;
164  _ownedBatches.clear();
165 }
166 
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 /// Print to given output stream.
170 void BatchData::print(std::ostream& os, const std::string& indent) const {
171  os << indent << "Batch data access";
172  if (_ownedBatches.empty() && !_foreignData) {
173  os << " not initialised." << std::endl;
174  return;
175  }
176 
177  using std::setw;
178 
179  os << " with " << (_foreignData ? "(foreign)" : "(owned)") << " data:";
180  os << "\n" << indent << std::right << std::setw(8) << "Batch #" << std::setw(8) << "Start"
181  << std::setw(7) << "Status";
182 
183  unsigned int i=0;
184  for (auto item : _ownedBatches) {
185  auto key = item.first;
186  const Batch& batch = item.second;
187 
188  os << "\n" << indent
189  << std::setw(8) << i << std::setw(8) << std::get<0>(key) << std::setw(8) << std::get<2>(key)
190  << std::setw(7) << batch.status << ": {";
191  for (unsigned int j=0; j < 5 && j < batch.data.size(); ++j) {
192  os << batch.data[j] << ", ";
193  }
194  os << "...}";
195  }
196  os << std::resetiosflags(std::ios::adjustfield) << std::endl;
197 }
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// Find the batch that contains the event with number `evt`.
201 /// \param[in] evt Index of the event to find.
202 /// \param[in] normSet Optional normalisation set defining what this batch was normalised to.
203 /// \param[in] ownerTag Optional owner tag to prevent sharing of memory between e.g. getVal() and getLogVal().
204 BatchData::Map_t::const_iterator BatchData::findEnclosingBatch(std::size_t evt,
205  const RooArgSet* const normSet, Tag_t ownerTag) const {
206  for (auto it = _ownedBatches.cbegin(); it != _ownedBatches.cend(); ++it) {
207  if (normSet == std::get<1>(it->first)
208  && ownerTag == std::get<2>(it->first)
209  && it->second.inBatch(evt))
210  return it;
211  }
212 
213  return _ownedBatches.end();
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Create a span pointing to existing batch memory.
218 /// \param[in] begin Index of the event to find.
219 /// \param[in] batchSize Requested size of the span. May come out smaller if no more data exists.
220 /// \param[in] normSet Optional normalisation set defining what this batch was normalised to.
221 /// \param[in] ownerTag Optional owner tag to prevent sharing of memory between e.g. getVal() and getLogVal().
222 /// \return RooSpan pointing inside an existing batch or an empty span if no such batch.
223 RooSpan<const double> BatchData::createSpanInsideExistingBatch(std::size_t begin, std::size_t batchSize,
224  const RooArgSet* const normSet, Tag_t ownerTag) const {
225  for (auto it = _ownedBatches.cbegin(); it != _ownedBatches.cend(); ++it) {
226  if (normSet == std::get<1>(it->first)
227  && ownerTag == std::get<2>(it->first)
228  && it->second.inBatch(begin))
229  return it->second.makeSpan(begin, batchSize);
230  }
231 
232  return {};
233 }
234 
235 }
BatchHelpers::BatchData::kReadyAndConstant
@ kReadyAndConstant
Definition: BatchData.h:36
BatchHelpers::BatchData::Status_t
Status_t
Status of the batch.
Definition: BatchData.h:36
BatchHelpers::BatchData::attachForeignStorage
void attachForeignStorage(const std::vector< double > &vec)
Attach a foreign storage. Batches coming from this storage will be read only.
Definition: BatchData.cxx:172
BatchHelpers::BatchData::createSpanInsideExistingBatch
RooSpan< const double > createSpanInsideExistingBatch(std::size_t begin, std::size_t batchSize, const RooArgSet *const normSet, Tag_t ownerTag) const
Create a span pointing to existing batch memory.
Definition: BatchData.cxx:235
indent
static void indent(ostringstream &buf, int indent_level)
Definition: TClingCallFunc.cxx:87
BatchHelpers::BatchData::Batch::status
Status_t status
Definition: BatchData.h:85
BatchHelpers::BatchData::Tag_t
Tag_t
Definition: BatchData.h:37
BatchHelpers::BatchData::makeWritableBatchInit
RooSpan< double > makeWritableBatchInit(std::size_t begin, std::size_t batchSize, double value, const RooArgSet *const normSet=nullptr, Tag_t ownerTag=kUnspecified)
Make a batch and return a span pointing to the pdf-local memory.
Definition: BatchData.cxx:160
BatchHelpers::BatchData::_foreignData
const std::vector< double > * _foreignData
Definition: BatchData.h:113
BatchHelpers::BatchData::kWriting
@ kWriting
Definition: BatchData.h:36
BatchHelpers::BatchData::Batch::data
std::vector< double > data
Definition: BatchData.h:84
BatchHelpers::BatchData::findEnclosingBatch
Map_t::const_iterator findEnclosingBatch(std::size_t evt, const RooArgSet *const normSet, Tag_t ownerTag) const
Find the batch that contains the event with number evt.
Definition: BatchData.cxx:216
BatchHelpers
Definition: BatchData.h:29
BatchHelpers::BatchData::Batch
Definition: BatchData.h:82
BatchHelpers::BatchData::setStatus
bool setStatus(std::size_t begin, std::size_t size, Status_t stat, const RooArgSet *const normSet=nullptr, Tag_t ownerTag=kUnspecified)
Set the status of a batch with the given properties.
Definition: BatchData.cxx:70
BatchHelpers::BatchData::print
void print(std::ostream &os, const std::string &indent) const
Print to given output stream.
Definition: BatchData.cxx:182
BatchHelpers::BatchData::kNoBatch
@ kNoBatch
Definition: BatchData.h:36
BatchHelpers::BatchData::clear
void clear()
Discard all storage.
Definition: BatchData.h:47
BatchData.h
BatchHelpers::BatchData::_ownedBatches
Map_t _ownedBatches
Definition: BatchData.h:112
BatchHelpers::BatchData::getBatch
RooSpan< const double > getBatch(std::size_t begin, std::size_t maxSize, const RooArgSet *const normSet=nullptr, Tag_t ownerTag=kUnspecified) const
Retrieve an existing batch.
Definition: BatchData.cxx:92
BatchHelpers::BatchData::status
Status_t status(std::size_t begin, const RooArgSet *const normSet=nullptr, Tag_t ownerTag=kUnspecified) const
Return the status of the batch starting at begin.
Definition: BatchData.cxx:42
BatchHelpers::BatchData::makeWritableBatchUnInit
RooSpan< double > makeWritableBatchUnInit(std::size_t begin, std::size_t batchSize, const RooArgSet *const normSet=nullptr, Tag_t ownerTag=kUnspecified)
Make a batch and return a span pointing to the pdf-local memory.
Definition: BatchData.cxx:130
RooSpan
A simple container to hold a batch of data values.
Definition: RooSpan.h:33
RooArgSet
Definition: RooArgSet.h:28