From 706e2242f20b208dc9734879c3caee729c9afd84 Mon Sep 17 00:00:00 2001 From: "Stanley C." <19547104+stanbot8@users.noreply.github.com> Date: Mon, 7 Sep 2026 13:47:44 -0700 Subject: [PATCH] Scope allocation ownership --- src/core/resource_manager.cc | 39 +++--------- src/core/resource_manager.h | 70 +++++---------------- test/unit/core/resource_manager_test.cc | 5 -- test/unit/core/resource_manager_test.h | 83 ++++--------------------- 4 files changed, 36 insertions(+), 161 deletions(-) diff --git a/src/core/resource_manager.cc b/src/core/resource_manager.cc index 0b439f817..69dc4a78e 100644 --- a/src/core/resource_manager.cc +++ b/src/core/resource_manager.cc @@ -22,19 +22,13 @@ #include "core/environment/environment.h" #include "core/simulation.h" #include "core/util/partition.h" -#include "core/util/plot_memory_layout.h" #include "core/util/timing.h" namespace bdm { ResourceManager::ResourceManager() { - // Must be called prior any other function call to libnuma - if (auto ret = numa_available() == -1) { - Log::Fatal("ResourceManager", - "Call to numa_available failed with return code: ", ret); - } - agents_.resize(numa_num_configured_nodes()); - agents_lb_.resize(numa_num_configured_nodes()); + agents_.resize(thread_info_->GetNumaNodes()); + agents_lb_.resize(thread_info_->GetNumaNodes()); auto* param = Simulation::GetActive()->GetParam(); if (param->export_visualization || param->insitu_visualization) { @@ -65,8 +59,6 @@ void ResourceManager::ForEachAgentParallel( auto nid = thread_info_->GetNumaNode(tid); auto threads_in_numa = thread_info_->GetThreadsInNumaNode(nid); auto& numa_agents = agents_[nid]; - assert(thread_info_->GetNumaNode(tid) == numa_node_of_cpu(sched_getcpu())); - // use static scheduling for now auto correction = numa_agents.size() % threads_in_numa == 0 ? 0 : 1; auto chunk = numa_agents.size() / threads_in_numa + correction; @@ -156,8 +148,6 @@ void ResourceManager::ForEachAgentParallel( auto p_numa_nodes = thread_info_->GetNumaNodes(); auto p_max_threads = omp_get_max_threads(); auto p_chunk = chunk; - assert(thread_info_->GetNumaNode(tid) == numa_node_of_cpu(sched_getcpu())); - // dynamic scheduling uint64_t start = 0; uint64_t end = 0; @@ -190,7 +180,7 @@ void ResourceManager::ForEachAgentParallel( old_count = (*(counters[current_tid]))++; } } // work stealing loop numa_nodes_ - } // work stealing loop threads + } // work stealing loop threads } for (auto* counter : counters) { @@ -242,10 +232,6 @@ void ResourceManager::LoadBalance() { // the environment before accessing it again. MarkEnvironmentOutOfSync(); auto* param = Simulation::GetActive()->GetParam(); - if (param->plot_memory_layout) { - PlotNeighborMemoryHistogram(true); - } - // balance agents per numa node according to the number of // threads associated with each numa domain auto numa_nodes = thread_info_->GetNumaNodes(); @@ -268,10 +254,12 @@ void ResourceManager::LoadBalance() { // using first touch policy - page will be allocated to the numa domain of // the thread that accesses it first. // alternative, use numa_alloc_onnode. - int ret = numa_run_on_node(0); - if (ret != 0) { - Log::Fatal("ResourceManager", - "Run on numa node failed. Return code: ", ret); + if (thread_info_->IsNumaAvailable()) { + int ret = numa_run_on_node(0); + if (ret != 0) { + Log::Fatal("ResourceManager", + "Run on numa node failed. Return code: ", ret); + } } auto* env = Simulation::GetActive()->GetEnvironment(); auto lbi = env->GetLoadBalanceInfo(); @@ -295,8 +283,6 @@ void ResourceManager::LoadBalance() { #pragma omp barrier auto threads_in_numa = thread_info_->GetThreadsInNumaNode(nid); - assert(thread_info_->GetNumaNode(tid) == numa_node_of_cpu(sched_getcpu())); - // use static scheduling auto correction = agent_per_numa[nid] % threads_in_numa == 0 ? 0 : 1; auto chunk = agent_per_numa[nid] / threads_in_numa + correction; @@ -321,13 +307,6 @@ void ResourceManager::LoadBalance() { for (int n = 0; n < numa_nodes; n++) { agents_[n].swap(agents_lb_[n]); - if (param->plot_memory_layout) { - PlotMemoryLayout(agents_[n], n); - PlotMemoryHistogram(agents_[n], n); - } - } - if (param->plot_memory_layout) { - PlotNeighborMemoryHistogram(); } if (Simulation::GetActive()->GetParam()->debug_numa) { diff --git a/src/core/resource_manager.h b/src/core/resource_manager.h index 50f1b76f3..ad5602ed9 100644 --- a/src/core/resource_manager.h +++ b/src/core/resource_manager.h @@ -40,7 +40,6 @@ #include "core/simulation.h" #include "core/type_index.h" #include "core/util/numa.h" -#include "core/util/root.h" #include "core/util/thread_info.h" #include "core/util/type.h" @@ -52,53 +51,14 @@ namespace bdm { /// simulation. class ResourceManager { public: - explicit ResourceManager(TRootIOCtor* r) {} - ResourceManager(); virtual ~ResourceManager(); - ResourceManager& operator=(ResourceManager&& other) noexcept { - if (agents_.size() != other.agents_.size()) { - Log::Fatal( - "Restored ResourceManager has different number of NUMA nodes."); - } - for (auto& el : continuum_models_) { - delete el.second; - } - for (auto& numa_agents : agents_) { - for (auto* agent : numa_agents) { - delete agent; - } - } - agents_ = std::move(other.agents_); - agents_lb_.resize(agents_.size()); - continuum_models_ = std::move(other.continuum_models_); - - RebuildAgentUidMap(); - // restore type_index_ - if (type_index_) { - for (auto& numa_agents : agents_) { - for (auto* agent : numa_agents) { - type_index_->Add(agent); - } - } - } - return *this; - } - - void RebuildAgentUidMap() { - // rebuild uid_ah_map_ - uid_ah_map_.clear(); - auto* agent_uid_generator = Simulation::GetActive()->GetAgentUidGenerator(); - uid_ah_map_.resize(agent_uid_generator->GetHighestIndex() + 1); - for (AgentHandle::NumaNode_t n = 0; n < agents_.size(); ++n) { - for (AgentHandle::ElementIdx_t i = 0; i < agents_[n].size(); ++i) { - auto* agent = agents_[n][i]; - this->uid_ah_map_.Insert(agent->GetUid(), AgentHandle(n, i)); - } - } - } + ResourceManager(const ResourceManager&) = delete; + ResourceManager& operator=(const ResourceManager&) = delete; + ResourceManager(ResourceManager&&) = delete; + ResourceManager& operator=(ResourceManager&&) = delete; Agent* GetAgent(const AgentUid& uid) { if (!uid_ah_map_.Contains(uid)) { @@ -431,20 +391,21 @@ class ResourceManager { /// not overlap! virtual void AddAgents(typename AgentHandle::NumaNode_t numa_node, uint64_t offset, - const std::vector& new_agents) { + std::vector>& new_agents) { uint64_t i = 0; - for (auto* agent : new_agents) { + for (auto& new_agent : new_agents) { + auto* agent = new_agent.get(); auto uid = agent->GetUid(); uid_ah_map_.Insert( uid, AgentHandle(numa_node, static_cast(offset + i))); - agents_[numa_node][offset + i] = agent; + agents_[numa_node][offset + i] = new_agent.release(); i++; } if (type_index_) { #pragma omp critical - for (auto* agent : new_agents) { - type_index_->Add(agent); + for (uint64_t j = 0; j < new_agents.size(); ++j) { + type_index_->Add(agents_[numa_node][offset + j]); } } #pragma omp single @@ -498,13 +459,13 @@ class ResourceManager { void MarkEnvironmentOutOfSync() const; /// Maps an AgentUid to its storage location in `agents_` \n - AgentUidMap uid_ah_map_ = AgentUidMap(100u); //! + AgentUidMap uid_ah_map_ = AgentUidMap(100u); /// Pointer container for all agents std::vector> agents_; /// Container used during load balancing - std::vector> agents_lb_; //! + std::vector> agents_lb_; - ThreadInfo* thread_info_ = ThreadInfo::GetInstance(); //! + ThreadInfo* thread_info_ = ThreadInfo::GetInstance(); TypeIndex* type_index_ = nullptr; @@ -514,16 +475,13 @@ class ResourceManager { }; /// auxiliary data required for parallel agent removal - ParallelRemovalAuxData parallel_remove_; //! + ParallelRemovalAuxData parallel_remove_; - friend class SimulationBackup; friend std::ostream& operator<<(std::ostream& os, const ResourceManager& rm); private: /// Maps a continuum ID to the pointer to the continuum models std::unordered_map continuum_models_; - - BDM_CLASS_DEF_NV(ResourceManager, 2); }; inline std::ostream& operator<<(std::ostream& os, const ResourceManager& rm) { diff --git a/test/unit/core/resource_manager_test.cc b/test/unit/core/resource_manager_test.cc index 4080c1a23..b725e47a9 100644 --- a/test/unit/core/resource_manager_test.cc +++ b/test/unit/core/resource_manager_test.cc @@ -15,7 +15,6 @@ // I/O related code must be in header file #include "unit/core/resource_manager_test.h" #include "core/model_initializer.h" -#include "unit/test_util/io_test.h" #include "unit/test_util/test_agent.h" namespace bdm { @@ -144,10 +143,6 @@ TEST(ResourceManagerTest, ForEachAgentParallel) { RunForEachAgentParallelTest(); } -#ifdef USE_DICT -TEST(ResourceManagerTest, IO) { RunIOTest(); } -#endif // USE_DICT - TEST(ResourceManagerTest, PushBackAndGetAgentTest) { RunPushBackAndGetAgentTest(); } diff --git a/test/unit/core/resource_manager_test.h b/test/unit/core/resource_manager_test.h index 13cfe5398..8869b97bd 100644 --- a/test/unit/core/resource_manager_test.h +++ b/test/unit/core/resource_manager_test.h @@ -22,17 +22,14 @@ #include "core/diffusion/euler_grid.h" #include "core/environment/environment.h" #include "core/resource_manager.h" -#include "core/util/io.h" #include "core/util/type.h" #include "unit/test_util/test_agent.h" #include "unit/test_util/test_util.h" -#define ROOTFILE "bdmFile.root" - namespace bdm { class A : public TestAgent { - BDM_AGENT_HEADER(A, TestAgent, 1); + BDM_AGENT_HEADER(A, TestAgent); public: A() = default; @@ -45,7 +42,7 @@ class A : public TestAgent { }; class B : public TestAgent { - BDM_AGENT_HEADER(B, TestAgent, 1); + BDM_AGENT_HEADER(B, TestAgent); public: B() = default; @@ -322,8 +319,13 @@ struct CheckForEachAgentFunctor : Functor { if (numa_checks && handle.GetNumaNode() != GetNumaNodeForMemory(agent)) { numa_memory_errors++; } - if (numa_checks && - handle.GetNumaNode() != numa_node_of_cpu(sched_getcpu())) { + unsigned int current_numa_node = 0; +#ifdef USE_NUMA + if (numa_checks) { + EXPECT_EQ(0, getcpu(nullptr, ¤t_numa_node)); + } +#endif + if (numa_checks && handle.GetNumaNode() != current_numa_node) { numa_thread_errors++; } @@ -385,7 +387,8 @@ inline void RunSortAndForEachAgentParallel(uint64_t num_agent_per_type) { simulation.GetEnvironment()->Update(); rm->LoadBalance(); - CheckForEachAgent(rm, num_agent_per_type, true); + CheckForEachAgent(rm, num_agent_per_type, + ThreadInfo::GetInstance()->IsNumaAvailable()); // check if agent uids still point to the correct object for (auto& entry : a_x_values) { @@ -556,7 +559,8 @@ inline void RunSortAndForEachAgentParallelDynamic(uint64_t num_agent_per_type, simulation.GetEnvironment()->Update(); rm->LoadBalance(); - CheckForEachAgentDynamic(rm, num_agent_per_type, batch_size, true); + CheckForEachAgentDynamic(rm, num_agent_per_type, batch_size, + ThreadInfo::GetInstance()->IsNumaAvailable()); // check if agent uids still point to the correct object for (auto& entry : a_x_values) { @@ -588,67 +592,6 @@ inline void RunSortAndForEachAgentParallelDynamic() { } } -inline void RunIOTest() { - const real_t kEpsilon = abs_error::value; - Simulation simulation("ResourceManagerTest-RunIOTest"); - auto* rm = simulation.GetResourceManager(); - - auto ref_uid = AgentUid(simulation.GetAgentUidGenerator()->GetHighestIndex()); - remove(ROOTFILE); - - // setup - rm->AddAgent(new A(12)); - rm->AddAgent(new A(34)); - rm->AddAgent(new A(42)); - - rm->AddAgent(new B(3.14)); - rm->AddAgent(new B(6.28)); - - DiffusionGrid* dgrid_1 = new EulerGrid(0, "Kalium", 0.4, 0, 2); - DiffusionGrid* dgrid_2 = new EulerGrid(1, "Natrium", 0.2, 0.1, 1); - rm->AddContinuum(dgrid_1); - rm->AddContinuum(dgrid_2); - - // backup - WritePersistentObject(ROOTFILE, "rm", *rm, "new"); - - rm->ClearAgents(); - - // restore - ResourceManager* restored_rm = nullptr; - GetPersistentObject(ROOTFILE, "rm", restored_rm); - restored_rm->RebuildAgentUidMap(); - - // validate - EXPECT_EQ(5u, restored_rm->GetNumAgents()); - - EXPECT_EQ(12, dynamic_cast(restored_rm->GetAgent(ref_uid))->GetData()); - EXPECT_EQ(34, - dynamic_cast(restored_rm->GetAgent(ref_uid + 1))->GetData()); - EXPECT_EQ(42, - dynamic_cast(restored_rm->GetAgent(ref_uid + 2))->GetData()); - - EXPECT_NEAR(3.14, - dynamic_cast(restored_rm->GetAgent(ref_uid + 3))->GetData(), - kEpsilon); - EXPECT_NEAR(6.28, - dynamic_cast(restored_rm->GetAgent(ref_uid + 4))->GetData(), - kEpsilon); - - EXPECT_EQ(0, restored_rm->GetDiffusionGrid(0)->GetContinuumId()); - EXPECT_EQ(1, restored_rm->GetDiffusionGrid(1)->GetContinuumId()); - EXPECT_EQ("Kalium", restored_rm->GetDiffusionGrid(0)->GetContinuumName()); - EXPECT_EQ("Natrium", restored_rm->GetDiffusionGrid(1)->GetContinuumName()); - EXPECT_EQ(real_t(0.6), - restored_rm->GetDiffusionGrid(0)->GetDiffusionCoefficients()[0]); - EXPECT_EQ(real_t(0.8), - restored_rm->GetDiffusionGrid(1)->GetDiffusionCoefficients()[0]); - - delete restored_rm; - - remove(ROOTFILE); -} - } // namespace bdm #endif // UNIT_CORE_RESOURCE_MANAGER_TEST_H_