9#include "MantidAPI/DllConfig.h"
15#include <nexus/NeXusFile.hpp>
17#include <boost/optional.hpp>
42 : nd(nd), m_maxId(0), m_SplitThreshold(1024), m_splitTopInto(
boost::none), m_numSplit(1), m_numTopSplit(1),
47 m_addingEvents_eventsPerTask = 1000;
48 m_significantEventsNumber = 10000000;
49 m_addingEvents_numTasksPerBlock = Kernel::ThreadPool::getNumPhysicalCores() * 5;
50 m_splitInto.resize(this->nd, 1);
58 std::string toXMLString()
const;
61 void fromXMLString(
const std::string &xml);
87 void setMaxId(
size_t newMaxId) { m_maxId = newMaxId; }
101 return (numPoints > m_SplitThreshold) && (depth < m_maxDepth);
123 return m_splitInto[dim];
142 return m_splitTopInto;
154 m_splitInto.resize(nd, num);
166 throw std::invalid_argument(
"BoxController::setSplitInto() called with "
167 "too high of a dimension index.");
168 m_splitInto[dim] = num;
180 throw std::invalid_argument(
"BoxController::setSplitTopInto() called with "
181 "too high of a dimension index.");
183 if (!m_splitTopInto) {
184 m_splitTopInto = std::vector<size_t>(nd, 1);
186 m_splitTopInto.get()[dim] = num;
196 this->m_addingEvents_eventsPerTask = m_addingEvents_eventsPerTask;
206 this->m_addingEvents_numTasksPerBlock = m_addingEvents_numTasksPerBlock;
228 eventsPerTask = m_addingEvents_eventsPerTask;
229 numTasksPerBlock = m_addingEvents_numTasksPerBlock;
261 bool shouldSplitBoxes(
size_t nEventsInOutput,
size_t eventsAdded,
size_t numMDBoxes)
const {
270 const size_t comparisonPoint = std::max(nEventsInOutput / 16, m_significantEventsNumber);
271 if (eventsAdded > comparisonPoint)
275 return ((eventsAdded / numMDBoxes) > m_SplitThreshold);
280 std::lock_guard<std::mutex> lock(m_mutexNumMDBoxes);
281 m_numMDBoxes[depth] = 0;
285 std::lock_guard<std::mutex> lock(m_mutexNumMDBoxes);
286 m_numMDGridBoxes[depth] = 0;
289 std::lock_guard<std::mutex> lock(m_mutexNumMDBoxes);
290 m_numMDGridBoxes[depth] += inc;
294 std::lock_guard<std::mutex> lock(m_mutexNumMDBoxes);
295 m_numMDBoxes[depth] += inc;
309 std::lock_guard<std::mutex> lock(m_mutexNumMDBoxes);
310 if (m_numMDBoxes[depth] > 0) {
311 m_numMDBoxes[depth]--;
313 m_numMDGridBoxes[depth]++;
316 if (depth == 0 && m_splitTopInto) {
318 const auto &splitTopInto = m_splitTopInto.get();
320 std::accumulate(splitTopInto.cbegin(), splitTopInto.cend(),
size_t{1}, std::multiplies<size_t>());
321 m_numMDBoxes[depth + 1] += numSplitTop;
323 m_numMDBoxes[depth + 1] += m_numSplit;
340 return std::accumulate(m_numMDBoxes.cbegin(), m_numMDBoxes.cend(),
size_t{0}, std::plus<size_t>());
345 return std::accumulate(m_numMDGridBoxes.cbegin(), m_numMDGridBoxes.cend(),
size_t{0}, std::plus<size_t>());
352 double maxNumberOfFinestBoxes = m_maxNumMDBoxes.back();
353 for (
size_t depth = 0; depth < m_numMDBoxes.size(); depth++) {
358 total += double(depth * m_numMDBoxes[depth]) * (maxNumberOfFinestBoxes / m_maxNumMDBoxes[depth]);
360 return total / maxNumberOfFinestBoxes;
365 std::lock_guard<std::mutex> lock(m_mutexNumMDBoxes);
366 m_numMDBoxes.clear();
367 m_numMDBoxes.resize(m_maxDepth + 1, 0);
368 m_numMDGridBoxes.resize(m_maxDepth + 1, 0);
381 void setFileBacked(
const std::shared_ptr<IBoxControllerIO> &newFileIO,
const std::string &fileName =
"");
382 void clearFileBacked();
393 size_t claimIDRange(
size_t range);
397 std::string getFilename()
const;
400 bool useWriteBuffer()
const;
406 for (
size_t d = 0;
d < nd;
d++) {
407 m_numSplit *= m_splitInto[
d];
416 for (
size_t d = 0;
d < nd;
d++) {
417 m_numTopSplit *= m_splitTopInto.get()[
d];
426 m_maxNumMDBoxes.resize(m_maxDepth + 1, 0);
427 m_maxNumMDBoxes[0] = 1;
428 for (
size_t depth = 1; depth < m_maxNumMDBoxes.size(); depth++) {
429 if (depth == 1 && m_splitTopInto) {
430 m_maxNumMDBoxes[depth] = m_maxNumMDBoxes[depth - 1] * double(m_numTopSplit);
432 m_maxNumMDBoxes[depth] = m_maxNumMDBoxes[depth - 1] * double(m_numSplit);
double value
The value of the point.
This class is used by MDBox and MDGridBox in order to intelligently determine optimal behavior.
bool shouldSplitBoxes(size_t nEventsInOutput, size_t eventsAdded, size_t numMDBoxes) const
Determine when would be a good time to split MDBoxes into MDGridBoxes.
size_t getSplitInto(size_t dim) const
Return into how many to split along a dimension.
void getAddingEventsParameters(size_t &eventsPerTask, size_t &numTasksPerBlock) const
Get parameters for adding events to a MDGridBox, trying to optimize parallel CPU use.
void incGridBoxesCounter(size_t depth, size_t inc=1)
IBoxControllerIO * getFileIO()
returns the pointer to the class, responsible for fileIO operations;
boost::optional< std::vector< size_t > > m_splitTopInto
Splittin # for all dimensions in the top level.
const std::vector< size_t > & getNumMDGridBoxes() const
Return the vector giving the number of MD Grid Boxes as a function of depth.
double getAverageDepth() const
Return the average recursion depth of gridding.
const std::vector< size_t > & getNumMDBoxes() const
Return the vector giving the number of MD Boxes as a function of depth.
std::shared_ptr< IBoxControllerIO > m_fileIO
std::vector< size_t > m_splitInto
Splitting # for all dimensions.
volatile size_t m_numEventsAtMax
number of events sitting in the boxes which should be split but are already split up to the max depth
size_t m_addingEvents_numTasksPerBlock
For adding events tasks.
bool isFileBacked() const
Returns if current box controller is file backed.
void setSplitInto(size_t dim, size_t num)
Set the way splitting will be done.
size_t m_numSplit
When you split a MDBox, it becomes this many sub-boxes.
size_t m_numTopSplit
When you split a top level MDBox by force, it becomes this many sub boxes.
void clearGridBoxesCounter(size_t depth)
void resetNumBoxes()
Reset the number of boxes tracked in m_numMDBoxes.
size_t m_maxDepth
Maximum splitting depth: don't go further than this many levels of recursion.
std::mutex m_mutexNumMDBoxes
Mutex for changing the number of MD Boxes.
size_t getNDims() const
Get # of dimensions.
size_t m_significantEventsNumber
This empirically-determined number of events takes a noticeable time to process and triggers box spli...
size_t getNumEventAtMax() const
return the numner of events, which are sitting at max depth and would be split if not due to the max ...
size_t getNumSplit() const
Return how many boxes (total) a MDGridBox will contain.
size_t getTotalNumMDBoxes() const
Return the total number of MD Boxes, irrespective of depth.
std::vector< size_t > m_numMDGridBoxes
For tracking how many MDGridBoxes (not MDBoxes) are at each recursion level.
void setSplitInto(size_t num)
Set the way splitting will be done.
void setAddingEvents_eventsPerTask(size_t m_addingEvents_eventsPerTask)
When adding events, how many events per task should be done?
size_t nd
Number of dimensions.
std::vector< size_t > m_numMDBoxes
For tracking how many MDBoxes (not MDGridBoxes) are at each recursion level.
void setSplitTopInto(size_t dim, size_t num)
Set the way splitting will be done for the top level.
size_t getAddingEvents_eventsPerTask() const
void setMaxDepth(size_t value)
Sets the max recursion depth allowed for grid box splitting.
size_t getSignificantEventsNumber() const
The number of events that triggers box splitting.
void calcNumTopSplit()
When you split an MDBox by force, it becomes this many sub boxes.
void setSplitThreshold(size_t threshold)
Set the splitting threshold.
void calcNumSplit()
When you split a MDBox, it becomes this many sub-boxes.
std::mutex & getIdMutex()
void clearBoxesCounter(size_t depth)
size_t m_addingEvents_eventsPerTask
For adding events tasks.
BoxController(size_t nd)
Constructor.
void setMaxId(size_t newMaxId)
Set the new maximum ID number anywhere in the workspace.
size_t m_SplitThreshold
Splitting threshold.
size_t getTotalNumMDGridBoxes() const
Return the total number of MDGridBox'es, irrespective of depth.
BoxController & operator=(const BoxController &)=delete
size_t getSplitThreshold() const
Return the splitting threshold, in # of events.
std::mutex m_idMutex
Mutex for getting IDs.
boost::optional< std::vector< size_t > > getSplitTopInto() const
Return into how many to split along a dimension for the top level.
void incBoxesCounter(size_t depth, size_t inc=1)
const std::vector< size_t > & getSplitIntoAll() const
Return into how many to split along a every dimension.
void trackNumBoxes(size_t depth)
Call to track the number of MDBoxes are contained in the MDEventWorkspace This should be called when ...
void resetMaxNumBoxes()
Calculate the vector of the max # of MDBoxes per level.
size_t getAddingEvents_numTasksPerBlock() const
std::vector< double > m_maxNumMDBoxes
This is the maximum number of MD boxes there could be at each recursion level (e.g.
const std::vector< double > & getMaxNumMDBoxes() const
Return the vector giving the MAXIMUM number of MD Boxes as a function of depth.
size_t getMaxDepth() const
void setAddingEvents_numTasksPerBlock(size_t m_addingEvents_numTasksPerBlock)
When adding events, how many events tasks per block should be done?
size_t m_maxId
The maximum ID number of any boxes in the workspace (not inclusive, i.e.
bool willSplit(size_t numPoints, size_t depth) const
Return true if the MDBox should split, given :
The header describes interface to IO Operations perfomed by the box controller May be replaced by a b...
std::shared_ptr< const BoxController > BoxController_const_sptr
Shared ptr to a const BoxController.
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
Helper class which provides the Collimation Length for SANS instruments.
constexpr bool operator==(const wide_integer< Bits, Signed > &lhs, const wide_integer< Bits2, Signed2 > &rhs)