Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
BatchData.h
Go to the documentation of this file.
1 // Author: Stephan Hageboeck, CERN 10 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 #ifndef ROOFIT_ROOFITCORE_INC_BATCHDATA_H_
18 #define ROOFIT_ROOFITCORE_INC_BATCHDATA_H_
19 
20 #include "RooSpan.h"
21 #include <unordered_map>
22 #include <assert.h>
23 
24 namespace BatchHelpers {
25 
26 class BatchData {
27  public:
28  /// Status of the batch. Make sure that everything that is readable has
29  /// a status >= kReady.
30  enum Status_t {kNoBatch, kDirty, kWriting, kReady, kReadyAndConstant};
31 
32  BatchData() :
33  _ownedBatches(),
34  _foreignData(nullptr)
35  {
36 
37  }
38 
39  /// Discard all storage.
40  void clear() {
41  _ownedBatches.clear();
42  }
43 
44  /// Return the status of the batch starting at `begin`.
45  /// \param[in] begin Start of the batch.
46  /// \param[in] size Size of the batch. This is used to check if the size of an existing batch
47  /// matches the requested size. Asking for a too large size will be signalled by kNoBatch.
48  Status_t status(std::size_t begin, std::size_t size) const {
49  if (_foreignData && begin+size <= _foreignData->size())
50  return kReadyAndConstant;
51  else if (_foreignData)
52  return kNoBatch;
53 
54  if (_ownedBatches.empty())
55  return kNoBatch;
56 
57  auto item = _ownedBatches.find(begin);
58 
59  if (item == _ownedBatches.end()) {
60  // We didn't find a batch that starts with `begin`. Check if there's
61  // a batch that's enclosing the requested range.
62  // This can be slow, but a subset of a batch is asked for:
63  item = findEnclosingBatch(begin);
64  if (item == _ownedBatches.end())
65  return kNoBatch;
66 
67  auto item2 = findEnclosingBatch(begin+size-1);
68 
69  return item == item2 ? item->second.status : kNoBatch;
70  }
71 
72  const Batch& batch = item->second;
73  if (size <= batch.data.size())
74  return batch.status;
75  else
76  return kNoBatch;
77  }
78 
79  ///////////////////////////////////////////////////////////////////////////
80  /// Set the status of a batch with the given start point and size.
81  ///
82  /// The status of foreign read-only data will never change.
83  /// \return True if status successfully set, false if no such batch / not writable.
84  bool setStatus(std::size_t begin, std::size_t size, Status_t stat) {
85  if (_foreignData)
86  return false;
87 
88  auto item = _ownedBatches.find(begin);
89  if (item == _ownedBatches.end() || size != item->second.data.size())
90  return false;
91 
92  item->second.status = stat;
93  return true;
94  }
95 
96  /// Mark all batches dirty. This will trigger recomputations.
97  void markDirty() {
98  for (auto& elm : _ownedBatches) {
99  if (elm.second.status != kReadyAndConstant)
100  elm.second.status = kDirty;
101  }
102  }
103 
104 
105  RooSpan<const double> getBatch(std::size_t begin, std::size_t batchSize) const;
106 
107  RooSpan<double> makeWritableBatchUnInit(std::size_t begin, std::size_t batchSize);
108 
109  RooSpan<double> makeWritableBatchInit(std::size_t begin, std::size_t batchSize, double value);
110 
111  void attachForeignStorage(const std::vector<double>& vec);
112 
113  void print(std::ostream& os, const std::string& indent) const;
114 
115 
116 
117  private:
118 
119  struct Batch {
120  std::size_t begin;
121  std::vector<double> data;
122  Status_t status;
123 
124  bool inBatch(std::size_t evt) const {
125  return begin <= evt && evt < begin + data.size();
126  }
127 
128  RooSpan<const double> makeSpan(std::size_t evt, std::size_t batchSize) const {
129  return RooSpan<const double>(&data[evt-begin], batchSize);
130  }
131  };
132 
133 
134  bool validRange(std::size_t begin, std::size_t size) const {
135  if (_foreignData) {
136  return begin < _foreignData->size() && begin+size <= _foreignData->size();
137  }
138 
139  auto batch = findSpanInsideExistingBatch(begin, size);
140  return !batch.empty();
141  }
142 
143 
144  using Map_t = std::unordered_map<std::size_t, Batch>;
145  Map_t::const_iterator findEnclosingBatch(std::size_t evt) const {
146  for (auto it = _ownedBatches.cbegin(); it != _ownedBatches.cend(); ++it) {
147  if (it->second.inBatch(evt))
148  return it;
149  }
150 
151  return _ownedBatches.end();
152  }
153 
154  RooSpan<const double> findSpanInsideExistingBatch(std::size_t begin, std::size_t batchSize) const {
155  for (auto it = _ownedBatches.cbegin(); it != _ownedBatches.cend(); ++it) {
156  if (it->second.inBatch(begin) && it->second.inBatch(begin+batchSize-1))
157  return it->second.makeSpan(begin, batchSize);
158  }
159 
160  return RooSpan<const double>();
161  }
162 
163  Map_t _ownedBatches;
164  const std::vector<double>* _foreignData;
165 };
166 
167 }
168 
169 #endif /* ROOFIT_ROOFITCORE_INC_BATCHDATA_H_ */