BioDynaMo  v1.03.58-27764645
resource_manager.h
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------
2 //
3 // Copyright (C) 2021 CERN & University of Surrey for the benefit of the
4 // BioDynaMo collaboration. All Rights Reserved.
5 //
6 // Licensed under the Apache License, Version 2.0 (the "License");
7 // you may not use this file except in compliance with the License.
8 //
9 // See the LICENSE file distributed with this work for details.
10 // See the NOTICE file distributed with this work for additional information
11 // regarding copyright ownership.
12 //
13 // -----------------------------------------------------------------------------
14 
15 #ifndef CORE_RESOURCE_MANAGER_H_
16 #define CORE_RESOURCE_MANAGER_H_
17 
18 #include <omp.h>
19 #include <sched.h>
20 #include <algorithm>
21 #include <cmath>
22 #include <limits>
23 #include <memory>
24 #include <ostream>
25 #include <set>
26 #include <string>
27 #include <unordered_map>
28 #include <utility>
29 #include <vector>
30 
31 #include "core/agent/agent.h"
33 #include "core/agent/agent_uid.h"
37 #include "core/functor.h"
39 #include "core/simulation.h"
40 #include "core/type_index.h"
41 #include "core/util/numa.h"
42 #include "core/util/root.h"
43 #include "core/util/thread_info.h"
44 #include "core/util/type.h"
45 
46 namespace bdm {
47 
53  public:
54  explicit ResourceManager(TRootIOCtor* r) {}
55 
57 
58  virtual ~ResourceManager();
59 
61  if (agents_.size() != other.agents_.size()) {
62  Log::Fatal(
63  "Restored ResourceManager has different number of NUMA nodes.");
64  }
65  for (auto& el : diffusion_grids_) {
66  delete el.second;
67  }
68  for (auto& numa_agents : agents_) {
69  for (auto* agent : numa_agents) {
70  delete agent;
71  }
72  }
73  agents_ = std::move(other.agents_);
74  agents_lb_.resize(agents_.size());
75  diffusion_grids_ = std::move(other.diffusion_grids_);
76 
78  // restore type_index_
79  if (type_index_) {
80  for (auto& numa_agents : agents_) {
81  for (auto* agent : numa_agents) {
82  type_index_->Add(agent);
83  }
84  }
85  }
86  return *this;
87  }
88 
90  // rebuild uid_ah_map_
91  uid_ah_map_.clear();
92  auto* agent_uid_generator = Simulation::GetActive()->GetAgentUidGenerator();
93  uid_ah_map_.resize(agent_uid_generator->GetHighestIndex() + 1);
94  for (AgentHandle::NumaNode_t n = 0; n < agents_.size(); ++n) {
95  for (AgentHandle::ElementIdx_t i = 0; i < agents_[n].size(); ++i) {
96  auto* agent = agents_[n][i];
97  this->uid_ah_map_.Insert(agent->GetUid(), AgentHandle(n, i));
98  }
99  }
100  }
101 
102  Agent* GetAgent(const AgentUid& uid) {
103  if (!uid_ah_map_.Contains(uid)) {
104  return nullptr;
105  }
106  auto& ah = uid_ah_map_[uid];
107  return agents_[ah.GetNumaNode()][ah.GetElementIdx()];
108  }
109 
111  return agents_[ah.GetNumaNode()][ah.GetElementIdx()];
112  }
113 
114  AgentHandle GetAgentHandle(const AgentUid& uid) { return uid_ah_map_[uid]; }
115 
116  void SwapAgents(std::vector<std::vector<Agent*>>* agents);
117 
119  uint64_t substance_id = dgrid->GetSubstanceId();
120  auto search = diffusion_grids_.find(substance_id);
121  if (search != diffusion_grids_.end()) {
122  Log::Fatal("ResourceManager::AddDiffusionGrid",
123  "You tried to add a diffusion grid with an already existing "
124  "substance id. Please choose a different substance id.");
125  } else {
126  diffusion_grids_[substance_id] = dgrid;
127  }
129  }
130 
131  void RemoveDiffusionGrid(size_t substance_id) {
132  auto search = diffusion_grids_.find(substance_id);
133  if (search != diffusion_grids_.end()) {
134  delete search->second;
135  diffusion_grids_.erase(search);
136  } else {
137  Log::Error("ResourceManager::RemoveDiffusionGrid",
138  "You tried to remove a diffusion grid that does not exist.");
139  }
140  }
141 
143  DiffusionGrid* GetDiffusionGrid(size_t substance_id) const {
144  if (substance_id >= diffusion_grids_.size()) {
145  Log::Error("ResourceManager::GetDiffusionGrid",
146  "You tried to request diffusion grid '", substance_id,
147  "', but it does not exist! Make sure that it's the correct id "
148  "correctly and that the diffusion grid is registered.");
149  return nullptr;
150  }
151  return diffusion_grids_.at(substance_id);
152  }
153 
157  DiffusionGrid* GetDiffusionGrid(const std::string& substance_name) const {
158  for (auto& el : diffusion_grids_) {
159  auto& dgrid = el.second;
160  if (dgrid->GetSubstanceName() == substance_name) {
161  return dgrid;
162  }
163  }
164  Log::Error("ResourceManager::GetDiffusionGrid",
165  "You tried to request a diffusion grid named '", substance_name,
166  "', but it does not exist! Make sure that it's spelled "
167  "correctly and that the diffusion grid is registered.");
168  return nullptr;
169  }
170 
175  template <typename TFunctor>
176  void ForEachDiffusionGrid(TFunctor&& f) const {
177  for (auto& el : diffusion_grids_) {
178  f(el.second);
179  }
180  }
181 
184  size_t GetNumAgents(int numa_node = -1) const {
185  if (numa_node == -1) {
186  size_t num_agents = 0;
187  for (auto& numa_agents : agents_) {
188  num_agents += numa_agents.size();
189  }
190  return num_agents;
191  } else {
192  return agents_[numa_node].size();
193  }
194  }
195 
196  size_t GetAgentVectorCapacity(int numa_node);
197 
206  virtual void ForEachAgent(const std::function<void(Agent*)>& function,
207  Functor<bool, Agent*>* filter = nullptr) {
208  for (auto& numa_agents : agents_) {
209  for (auto* agent : numa_agents) {
210  if (!filter || (filter && (*filter)(agent))) {
211  function(agent);
212  }
213  }
214  }
215  }
216 
217  virtual void ForEachAgent(
218  const std::function<void(Agent*, AgentHandle)>& function,
219  Functor<bool, Agent*>* filter = nullptr) {
220  for (AgentHandle::NumaNode_t n = 0; n < agents_.size(); ++n) {
221  auto& numa_agents = agents_[n];
222  for (AgentHandle::ElementIdx_t i = 0; i < numa_agents.size(); ++i) {
223  auto* a = numa_agents[i];
224  if (!filter || (filter && (*filter)(a))) {
225  function(a, AgentHandle(n, i));
226  }
227  }
228  }
229  }
230 
238  virtual void ForEachAgentParallel(Functor<void, Agent*>& function,
239  Functor<bool, Agent*>* filter = nullptr);
240 
245  virtual void ForEachAgentParallel(Operation& op,
246  Functor<bool, Agent*>* filter = nullptr);
247 
248  virtual void ForEachAgentParallel(
250  Functor<bool, Agent*>* filter = nullptr);
251 
259  virtual void ForEachAgentParallel(
260  uint64_t chunk, Functor<void, Agent*, AgentHandle>& function,
261  Functor<bool, Agent*>* filter = nullptr);
262 
265  void Reserve(size_t capacity) {
266  for (auto& numa_agents : agents_) {
267  numa_agents.reserve(capacity);
268  }
269  if (type_index_) {
270  type_index_->Reserve(capacity);
271  }
272  }
273 
277  uint64_t GrowAgentContainer(size_t additional, size_t numa_node) {
278  if (additional == 0) {
279  return agents_[numa_node].size();
280  }
281  auto current = agents_[numa_node].size();
282  if (current + additional < agents_[numa_node].size()) {
283  agents_[numa_node].reserve((current + additional) * 1.5);
284  }
285  agents_[numa_node].resize(current + additional);
286  return current;
287  }
288 
291  bool ContainsAgent(const AgentUid& uid) const {
292  return uid_ah_map_.Contains(uid);
293  }
294 
299  void ClearAgents() {
300  uid_ah_map_.clear();
301  for (auto& numa_agents : agents_) {
302  for (auto* agent : numa_agents) {
303  delete agent;
304  }
305  numa_agents.clear();
306  }
307  if (type_index_) {
308  type_index_->Clear();
309  }
310  }
311 
314  virtual void LoadBalance();
315 
316  void DebugNuma() const;
317 
321  void AddAgent(Agent* agent, // NOLINT
322  typename AgentHandle::NumaNode_t numa_node = 0) {
323  auto uid = agent->GetUid();
324  if (uid.GetIndex() >= uid_ah_map_.size()) {
325  uid_ah_map_.resize(uid.GetIndex() + 1);
326  }
327  agents_[numa_node].push_back(agent);
328  uid_ah_map_.Insert(
329  uid, AgentHandle(numa_node, static_cast<AgentHandle::ElementIdx_t>(
330  agents_[numa_node].size() - 1u)));
331  if (type_index_) {
332  type_index_->Add(agent);
333  }
335  }
336 
338  auto* agent_uid_generator = Simulation::GetActive()->GetAgentUidGenerator();
339  auto highest_idx = agent_uid_generator->GetHighestIndex();
340  auto new_size = highest_idx * 1.5 + 1;
341  if (highest_idx >= uid_ah_map_.size()) {
342  uid_ah_map_.resize(new_size);
343  }
344  if (type_index_) {
345  type_index_->Reserve(new_size);
346  }
347  }
348 
349  virtual void EndOfIteration() {}
350 
355  virtual void AddAgents(typename AgentHandle::NumaNode_t numa_node,
356  uint64_t offset,
357  const std::vector<Agent*>& new_agents) {
358  uint64_t i = 0;
359  for (auto* agent : new_agents) {
360  auto uid = agent->GetUid();
361  uid_ah_map_.Insert(
362  uid, AgentHandle(numa_node,
363  static_cast<AgentHandle::ElementIdx_t>(offset + i)));
364  agents_[numa_node][offset + i] = agent;
365  i++;
366  }
367  if (type_index_) {
368 #pragma omp critical
369  for (auto* agent : new_agents) {
370  type_index_->Add(agent);
371  }
372  }
373 #pragma omp single
374  if (new_agents.size() != 0) {
376  }
377  }
378 
383  void RemoveAgent(const AgentUid& uid) {
384  // remove from map
385  if (uid_ah_map_.Contains(uid)) {
386  auto ah = uid_ah_map_[uid];
387  uid_ah_map_.Remove(uid);
388  // remove from vector
389  auto& numa_agents = agents_[ah.GetNumaNode()];
390  Agent* agent = nullptr;
391  if (ah.GetElementIdx() == numa_agents.size() - 1) {
392  agent = numa_agents.back();
393  numa_agents.pop_back();
394  } else {
395  // swap
396  agent = numa_agents[ah.GetElementIdx()];
397  auto* reordered = numa_agents.back();
398  numa_agents[ah.GetElementIdx()] = reordered;
399  numa_agents.pop_back();
400  uid_ah_map_.Insert(reordered->GetUid(), ah);
401  }
402  if (type_index_) {
403  type_index_->Remove(agent);
404  }
405  delete agent;
407  }
409  }
410 
411  // \param uids: one vector for each thread containing one vector for each numa
412  // node
413  void RemoveAgents(const std::vector<std::vector<AgentUid>*>& uids);
414 
415  const TypeIndex* GetTypeIndex() const { return type_index_; }
416 
417  protected:
422 
425  std::vector<std::vector<Agent*>> agents_;
428  std::vector<std::vector<Agent*>> agents_lb_;
429  std::unordered_map<uint64_t, DiffusionGrid*> diffusion_grids_;
431 
433 
434  TypeIndex* type_index_ = nullptr;
435 
437  std::vector<std::vector<uint64_t>> to_right;
438  std::vector<std::vector<uint64_t>> not_to_left;
439  };
440 
443 
444  friend class SimulationBackup;
445  friend std::ostream& operator<<(std::ostream& os, const ResourceManager& rm);
447 };
448 
449 inline std::ostream& operator<<(std::ostream& os, const ResourceManager& rm) {
450  os << "\033[1mAgents per numa node\033[0m" << std::endl;
451  uint64_t cnt = 0;
452  for (auto& numa_agents : rm.agents_) {
453  os << "numa node " << cnt++ << " -> size: " << numa_agents.size()
454  << std::endl;
455  }
456  return os;
457 }
458 
459 } // namespace bdm
460 
461 #endif // CORE_RESOURCE_MANAGER_H_
bdm::ResourceManager::ContainsAgent
bool ContainsAgent(const AgentUid &uid) const
Definition: resource_manager.h:291
bdm::AgentHandle::NumaNode_t
uint16_t NumaNode_t
Definition: agent_handle.h:31
bdm::ResourceManager::EndOfIteration
virtual void EndOfIteration()
Definition: resource_manager.h:349
bdm::ResourceManager::agents_lb_
std::vector< std::vector< Agent * > > agents_lb_
Container used during load balancing.
Definition: resource_manager.h:428
agent_uid_map.h
bdm::ResourceManager::GetNumAgents
size_t GetNumAgents(int numa_node=-1) const
Definition: resource_manager.h:184
bdm::TypeIndex::Add
void Add(Agent *agent)
Definition: type_index.cc:22
agent_uid.h
bdm::ThreadInfo::GetInstance
static ThreadInfo * GetInstance()
Definition: thread_info.cc:21
bdm::ResourceManager::ResizeAgentUidMap
void ResizeAgentUidMap()
Definition: resource_manager.h:337
bdm::ResourceManager::LoadBalance
virtual void LoadBalance()
Definition: resource_manager.cc:239
agent_handle.h
bdm::ResourceManager::GetAgent
Agent * GetAgent(const AgentUid &uid)
Definition: resource_manager.h:102
bdm::ResourceManager::type_index_
TypeIndex * type_index_
Definition: resource_manager.h:434
bdm
Definition: agent.cc:39
bdm::ResourceManager::GetTypeIndex
const TypeIndex * GetTypeIndex() const
Definition: resource_manager.h:415
operation.h
bdm::ResourceManager::RemoveAgents
void RemoveAgents(const std::vector< std::vector< AgentUid > * > &uids)
Definition: resource_manager.cc:339
thread_info.h
bdm::ResourceManager::GetDiffusionGrid
DiffusionGrid * GetDiffusionGrid(size_t substance_id) const
Return the diffusion grid which holds the substance of specified id.
Definition: resource_manager.h:143
bdm::ResourceManager::Reserve
void Reserve(size_t capacity)
Definition: resource_manager.h:265
bdm::ResourceManager::ResourceManager
ResourceManager(TRootIOCtor *r)
Definition: resource_manager.h:54
bdm::ResourceManager::ParallelRemovalAuxData::to_right
std::vector< std::vector< uint64_t > > to_right
Definition: resource_manager.h:437
bdm::ResourceManager::SwapAgents
void SwapAgents(std::vector< std::vector< Agent * >> *agents)
Definition: resource_manager.cc:584
bdm::Agent::GetUid
const AgentUid & GetUid() const
Definition: agent.cc:123
bdm::ResourceManager::AddDiffusionGrid
void AddDiffusionGrid(DiffusionGrid *dgrid)
Definition: resource_manager.h:118
bdm::ResourceManager::operator=
ResourceManager & operator=(ResourceManager &&other) noexcept
Definition: resource_manager.h:60
type.h
bdm::DiffusionGrid
Definition: diffusion_grid.h:32
bdm::AgentUidGenerator::ReuseAgentUid
void ReuseAgentUid(const AgentUid &uid)
Definition: agent_uid_generator.h:60
bdm::TypeIndex
Definition: type_index.h:27
bdm::AgentHandle::ElementIdx_t
uint32_t ElementIdx_t
Definition: agent_handle.h:32
bdm::ResourceManager::GetDiffusionGrid
DiffusionGrid * GetDiffusionGrid(const std::string &substance_name) const
Definition: resource_manager.h:157
bdm::ResourceManager::parallel_remove_
ParallelRemovalAuxData parallel_remove_
auxiliary data required for parallel agent removal
Definition: resource_manager.h:442
bdm::ResourceManager::ParallelRemovalAuxData
Definition: resource_manager.h:436
bdm::ResourceManager::ForEachAgent
virtual void ForEachAgent(const std::function< void(Agent *)> &function, Functor< bool, Agent * > *filter=nullptr)
Definition: resource_manager.h:206
bdm::DiffusionGrid::GetSubstanceId
int GetSubstanceId() const
Definition: diffusion_grid.h:129
bdm::Agent
Contains code required by all agents.
Definition: agent.h:79
bdm::ResourceManager::RebuildAgentUidMap
void RebuildAgentUidMap()
Definition: resource_manager.h:89
bdm::AgentUidGenerator::GetHighestIndex
AgentUid::Index_t GetHighestIndex() const
Thread-safe.
Definition: agent_uid_generator.h:56
bdm::Functor
Definition: functor.h:24
bdm::ResourceManager::AddAgents
virtual void AddAgents(typename AgentHandle::NumaNode_t numa_node, uint64_t offset, const std::vector< Agent * > &new_agents)
Definition: resource_manager.h:355
bdm::ResourceManager::uid_ah_map_
AgentUidMap< AgentHandle > uid_ah_map_
Maps an AgentUid to its storage location in agents_ .
Definition: resource_manager.h:424
bdm::ResourceManager::RemoveAgent
void RemoveAgent(const AgentUid &uid)
Definition: resource_manager.h:383
bdm::ResourceManager::AddAgent
void AddAgent(Agent *agent, typename AgentHandle::NumaNode_t numa_node=0)
Definition: resource_manager.h:321
diffusion_grid.h
bdm::ResourceManager::ParallelRemovalAuxData::not_to_left
std::vector< std::vector< uint64_t > > not_to_left
Definition: resource_manager.h:438
bdm::ResourceManager::BDM_CLASS_DEF_NV
BDM_CLASS_DEF_NV(ResourceManager, 2)
bdm::ResourceManager::GetAgent
Agent * GetAgent(AgentHandle ah)
Definition: resource_manager.h:110
bdm::ResourceManager::GetAgentHandle
AgentHandle GetAgentHandle(const AgentUid &uid)
Definition: resource_manager.h:114
bdm::ResourceManager
Definition: resource_manager.h:52
numa.h
bdm::ResourceManager::~ResourceManager
virtual ~ResourceManager()
Definition: resource_manager.cc:45
root.h
bdm::ResourceManager::ClearAgents
void ClearAgents()
Definition: resource_manager.h:299
bdm::ResourceManager::agents_
std::vector< std::vector< Agent * > > agents_
Pointer container for all agents.
Definition: resource_manager.h:426
agent_uid_generator.h
bdm::TypeIndex::Remove
void Remove(Agent *agent)
Definition: type_index.cc:40
bdm::TypeIndex::Clear
void Clear()
Definition: type_index.cc:55
agent.h
bdm::AgentUidMap
Definition: agent_uid_map.h:31
bdm::ResourceManager::RemoveDiffusionGrid
void RemoveDiffusionGrid(size_t substance_id)
Definition: resource_manager.h:131
bdm::Log::Fatal
static void Fatal(const std::string &location, const Args &... parts)
Prints fatal error message.
Definition: log.h:115
bdm::Log::Error
static void Error(const std::string &location, const Args &... parts)
Prints error message.
Definition: log.h:79
bdm::Simulation::GetAgentUidGenerator
AgentUidGenerator * GetAgentUidGenerator()
Definition: simulation.cc:273
bdm::ResourceManager::GrowAgentContainer
uint64_t GrowAgentContainer(size_t additional, size_t numa_node)
Definition: resource_manager.h:277
bdm::ResourceManager::diffusion_grids_
std::unordered_map< uint64_t, DiffusionGrid * > diffusion_grids_
Maps a diffusion grid ID to the pointer to the diffusion grid.
Definition: resource_manager.h:430
bdm::ResourceManager::ForEachAgent
virtual void ForEachAgent(const std::function< void(Agent *, AgentHandle)> &function, Functor< bool, Agent * > *filter=nullptr)
Definition: resource_manager.h:217
type_index.h
bdm::ResourceManager::ForEachDiffusionGrid
void ForEachDiffusionGrid(TFunctor &&f) const
Definition: resource_manager.h:176
bdm::AgentUid
Definition: agent_uid.h:25
bdm::ResourceManager::ResourceManager
ResourceManager()
Definition: resource_manager.cc:30
bdm::operator<<
std::ostream & operator<<(std::ostream &o, const MathArray< T, N > &arr)
Definition: math_array.h:412
bdm::SimulationBackup
Definition: simulation_backup.h:33
bdm::ResourceManager::ForEachAgentParallel
virtual void ForEachAgentParallel(Functor< void, Agent * > &function, Functor< bool, Agent * > *filter=nullptr)
Definition: resource_manager.cc:92
bdm::ResourceManager::thread_info_
ThreadInfo * thread_info_
Definition: resource_manager.h:432
simulation.h
bdm::ResourceManager::DebugNuma
void DebugNuma() const
bdm::AgentHandle::GetNumaNode
NumaNode_t GetNumaNode() const
Definition: agent_handle.h:44
bdm::Simulation::GetActive
static Simulation * GetActive()
This function returns the currently active Simulation simulation.
Definition: simulation.cc:67
bdm::Operation
Definition: operation.h:98
bdm::AgentHandle::GetElementIdx
ElementIdx_t GetElementIdx() const
Definition: agent_handle.h:45
functor.h
bdm::ResourceManager::MarkEnvironmentOutOfSync
void MarkEnvironmentOutOfSync()
Definition: resource_manager.cc:588
bdm::ResourceManager::operator<<
friend std::ostream & operator<<(std::ostream &os, const ResourceManager &rm)
Definition: resource_manager.h:449
bdm::ThreadInfo
This class stores information about each thread. (e.g. to which NUMA node it belongs to....
Definition: thread_info.h:31
bdm::TypeIndex::Reserve
void Reserve(uint64_t capacity)
Definition: type_index.cc:63
bdm::ResourceManager::GetAgentVectorCapacity
size_t GetAgentVectorCapacity(int numa_node)
Definition: resource_manager.cc:579
bdm::AgentHandle
Definition: agent_handle.h:29