From 67bb69f0c3a815cd0fff0d9ed67e2a092b4dba92 Mon Sep 17 00:00:00 2001 From: Thomas Liao <tliao@carboncopies.org> Date: Mon, 24 Mar 2025 19:27:42 -0700 Subject: [PATCH 1/5] Add contention mechanism for image processor pool --- Source/Core/CMakeLists.txt | 1 + Source/Core/VSDA/EM/EMRenderer.cpp | 2 +- .../VSDA/EM/VoxelSubsystem/EMSubRegion.cpp | 46 +++++++++---------- .../ImageProcessorPool/ImageProcessorPool.cpp | 2 +- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/Source/Core/CMakeLists.txt b/Source/Core/CMakeLists.txt index e69e19947..6bf6f521d 100644 --- a/Source/Core/CMakeLists.txt +++ b/Source/Core/CMakeLists.txt @@ -6,6 +6,7 @@ set(MAIN_SOURCES ${SRC_DIR}/Core/Main.h + ${SRC_DIR}/Core/Config/ConfigurationManager.cpp ${SRC_DIR}/Core/Config/ConfigurationManager.h ${SRC_DIR}/Core/Config/ConfigFileParser.cpp diff --git a/Source/Core/VSDA/EM/EMRenderer.cpp b/Source/Core/VSDA/EM/EMRenderer.cpp index e3473408d..8731dbd07 100644 --- a/Source/Core/VSDA/EM/EMRenderer.cpp +++ b/Source/Core/VSDA/EM/EMRenderer.cpp @@ -44,7 +44,7 @@ bool ExecuteSubRenderOperations(Config::Config* _Config, BG::Common::Logger::Log } _Simulation->VSDAData_.State_ = VSDA_RENDER_IN_PROGRESS; - _Logger->Log("Executing Render Job For Requested Simulation", 4); + _Logger->Log("Executing Render Job For Requested Simulation " + std::to_string(_Simulation->ID), 4); // Unpack Variables For Easier Access diff --git a/Source/Core/VSDA/EM/VoxelSubsystem/EMSubRegion.cpp b/Source/Core/VSDA/EM/VoxelSubsystem/EMSubRegion.cpp index 897516712..f1918bcc7 100644 --- a/Source/Core/VSDA/EM/VoxelSubsystem/EMSubRegion.cpp +++ b/Source/Core/VSDA/EM/VoxelSubsystem/EMSubRegion.cpp @@ -114,8 +114,29 @@ bool EMRenderSubRegion(BG::Common::Logger::LoggingSystem* _Logger, SubRegion* _S _Logger->Log("This EM Render Operation Desires " + std::to_string(VSDAData_->Params_.SliceThickness_um) + "um Slice Thickness", 5); _Logger->Log("Therefore, we are using " + std::to_string(NumVoxelsPerSlice) + "vox per slice at " + std::to_string(VSDAData_->Params_.VoxelResolution_um) + "um per vox", 5); _Logger->Log("We Will Render A Total Of " + std::to_string(NumZSlices) + " Slices", 5); + + + // Force us to wait for any other renders using the image processor pool + while (_ImageProcessorPool->GetQueueSize() > 0) { + + // Update Current Slice Information (Account for slice numbers not starting at 0) + VSDAData_->CurrentOperation_ = "Image Processing Enqueued"; + VSDAData_->TotalSliceImages_ = 0; + VSDAData_->CurrentSliceImage_ = 0; + VSDAData_->VoxelQueueLength_ = 0; + VSDAData_->TotalVoxelQueueLength_ = 0; + VSDAData_->TotalSlices_ = 0; + VSDAData_->CurrentSlice_ = 0; + VSDAData_->CurrentSlice_ = VSDAData_->TotalSlices_ - _ImageProcessorPool->GetQueueSize(); + + _Logger->Log("Waiting for ImageProcessorPool to become available; '" + std::to_string(_ImageProcessorPool->GetQueueSize()) + "' items remaining", 1); + + // Now wait a while so we don't spam the console + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } + // Update Status Bar VSDAData_->CurrentOperation_ = "Image Processing"; VSDAData_->TotalSliceImages_ = 0; @@ -147,36 +168,13 @@ bool EMRenderSubRegion(BG::Common::Logger::LoggingSystem* _Logger, SubRegion* _S // Ensure All Tasks Are Finished while (_ImageProcessorPool->GetQueueSize() > 0) { - // // Calculate Desired Image Size - // // In order for us to deal with multiple different pixel/voxel setting, we create an image of start size where one pixel = 1 voxel - // // then later on, we resample it to be the right size (for the target image) - // int VoxelsPerStepX = ceil(VSDAData_->Params_.ImageWidth_px / VSDAData_->Params_.NumPixelsPerVoxel_px); - // int VoxelsPerStepY = ceil(VSDAData_->Params_.ImageHeight_px / VSDAData_->Params_.NumPixelsPerVoxel_px); - // int NumChannels = 3; - // float CameraStepSizeX_um = VoxelsPerStepX * VSDAData_->Params_.VoxelResolution_um; - // float CameraStepSizeY_um = VoxelsPerStepY * VSDAData_->Params_.VoxelResolution_um; - - // double TotalSliceWidth = abs((double)VSDAData_->Array_->GetBoundingBox().bb_point1[0] - (double)VSDAData_->Array_->GetBoundingBox().bb_point2[0]); - // double TotalSliceHeight = abs((double)VSDAData_->Array_->GetBoundingBox().bb_point1[1] - (double)VSDAData_->Array_->GetBoundingBox().bb_point2[1]); - // int TotalXSteps = ceil(TotalSliceWidth / CameraStepSizeX_um); - // int TotalYSteps = ceil(TotalSliceHeight / CameraStepSizeY_um); - // TotalXSteps = std::min(TotalXSteps, _SubRegion->MaxImagesX); - // TotalYSteps = std::min(TotalYSteps, _SubRegion->MaxImagesY); - - // int ImagesPerSlice = TotalXSteps * TotalYSteps; - - // Update Current Slice Information (Account for slice numbers not starting at 0) VSDAData_->CurrentSlice_ = VSDAData_->TotalSlices_ - _ImageProcessorPool->GetQueueSize(); - // VSDAData_->TotalSliceImages_ = ImagesPerSlice; - // VSDAData_->CurrentSliceImage_ = _ImageProcessorPool->GetQueueSize() % ImagesPerSlice; - // Log Queue Size _Logger->Log("ImageProcessorPool Queue Length '" + std::to_string(_ImageProcessorPool->GetQueueSize()) + "'", 1); - // Now wait a while so we don't spam the console - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } diff --git a/Source/Core/VSDA/EM/VoxelSubsystem/ImageProcessorPool/ImageProcessorPool.cpp b/Source/Core/VSDA/EM/VoxelSubsystem/ImageProcessorPool/ImageProcessorPool.cpp index 6ff42463a..758aa6b6f 100644 --- a/Source/Core/VSDA/EM/VoxelSubsystem/ImageProcessorPool/ImageProcessorPool.cpp +++ b/Source/Core/VSDA/EM/VoxelSubsystem/ImageProcessorPool/ImageProcessorPool.cpp @@ -199,7 +199,7 @@ void ImageProcessorPool::EncoderThreadMainFunction(int _ThreadNumber) { Task->IsDone_ = true; // Logging - Logger_->Log("Compressed segmentation layer " + std::to_string(Task->VoxelZ) + " to " + Task->OutputPath_, 1); + //Logger_->Log("Compressed segmentation layer " + std::to_string(Task->VoxelZ) + " to " + Task->OutputPath_, 1); continue; } -- GitLab From c5031d56cc686c6fee2cd688816e8a026af969a1 Mon Sep 17 00:00:00 2001 From: Thomas Liao <tliao@carboncopies.org> Date: Mon, 24 Mar 2025 19:27:55 -0700 Subject: [PATCH 2/5] Add memory usage check --- Source/Core/VSDA/EM/EMRenderer.cpp | 33 +++++++++++++------ .../ImageProcessorPool/ImageProcessorPool.h | 4 ++- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Source/Core/VSDA/EM/EMRenderer.cpp b/Source/Core/VSDA/EM/EMRenderer.cpp index 8731dbd07..df35657be 100644 --- a/Source/Core/VSDA/EM/EMRenderer.cpp +++ b/Source/Core/VSDA/EM/EMRenderer.cpp @@ -51,16 +51,6 @@ bool ExecuteSubRenderOperations(Config::Config* _Config, BG::Common::Logger::Log MicroscopeParameters* Params = &_Simulation->VSDAData_.Params_; ScanRegion* BaseRegion = &_Simulation->VSDAData_.Regions_[_Simulation->VSDAData_.ActiveRegionID_]; - // // -- Phase -1 -- - // // We need to backpropagate the ids of the neurons to the compartments, then to us. - // for (auto Neuron : _Simulation->Neurons) { - // if (auto SCNeuron = dynamic_cast<Simulation::SCNeuron>(Neuron.get())) { - // RegisterNeuronUIDToCompartments(_N.SomaCompartmentIDs, _N.ID + 1); - // RegisterNeuronUIDToCompartments(_N.DendriteCompartmentIDs, _N.ID + 1); - // RegisterNeuronUIDToCompartments(_N.AxonCompartmentIDs, _N.ID + 1); - // } - // } - // -- Phase 0 -- // Here, we detect how much memory this machine has and then use that to make an educated guess as to the max size of the voxel array. @@ -153,6 +143,29 @@ bool ExecuteSubRenderOperations(Config::Config* _Config, BG::Common::Logger::Log BaseRegion->RegionIndexInfo_ = Info; + // Now we need to check that we have enough memory right now to begin rendering, if we dont, we need to wait until we do + // this actually just looks for other renders that are happening right now and checks its status + double CurrentRendererUsage = _ImageProcessorPool->TotalConsumedMemory_MB.load(); + + while (((_ImageProcessorPool->TotalConsumedMemory_MB.load() + MemorySize_MB) / SystemRAM_MB) > 0.9) { + + // Update Current Slice Information (Account for slice numbers not starting at 0) + _Simulation->VSDAData_.CurrentOperation_ = "Waiting for free RAM"; + _Simulation->VSDAData_.TotalSliceImages_ = 0; + _Simulation->VSDAData_.CurrentSliceImage_ = 0; + _Simulation->VSDAData_.VoxelQueueLength_ = 0; + _Simulation->VSDAData_.TotalVoxelQueueLength_ = 0; + _Simulation->VSDAData_.TotalSlices_ = 0; + _Simulation->VSDAData_.CurrentSlice_ = 0; + + _Logger->Log("Waiting for enough free RAM to become available before starting render", 1); + + // Now wait a while so we don't spam the console + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + + } + + // Now, we go through all of the steps in each direction that we identified, and calculate the bounding boxes for each std::vector<SubRegion> SubRegions; diff --git a/Source/Core/VSDA/EM/VoxelSubsystem/ImageProcessorPool/ImageProcessorPool.h b/Source/Core/VSDA/EM/VoxelSubsystem/ImageProcessorPool/ImageProcessorPool.h index 6df35589c..7f7e6d7d6 100644 --- a/Source/Core/VSDA/EM/VoxelSubsystem/ImageProcessorPool/ImageProcessorPool.h +++ b/Source/Core/VSDA/EM/VoxelSubsystem/ImageProcessorPool/ImageProcessorPool.h @@ -78,7 +78,6 @@ private: std::atomic_bool ThreadControlFlag_; /**Bool that signals threads to exit*/ - /** * @brief Thread safe enqueue function. * @@ -109,6 +108,9 @@ private: public: + std::atomic<double> TotalConsumedMemory_MB; /**Counter for emrenderer to keep track of how much memory is being used by renders*/ + + /** * @brief Initializes the imageprocessorpool with the given number of threads requested. * -- GitLab From af942ae69a04f1f37f9fb2f9f1e932efe8a83dde Mon Sep 17 00:00:00 2001 From: Thomas Liao <tliao@carboncopies.org> Date: Mon, 24 Mar 2025 19:29:20 -0700 Subject: [PATCH 3/5] Fix memory usage counter --- Source/Core/VSDA/EM/EMRenderer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/Core/VSDA/EM/EMRenderer.cpp b/Source/Core/VSDA/EM/EMRenderer.cpp index df35657be..2bf9bc21d 100644 --- a/Source/Core/VSDA/EM/EMRenderer.cpp +++ b/Source/Core/VSDA/EM/EMRenderer.cpp @@ -165,6 +165,9 @@ bool ExecuteSubRenderOperations(Config::Config* _Config, BG::Common::Logger::Log } + // Incriment counter of memory usage + _ImageProcessorPool->TotalConsumedMemory_MB += MemorySize_MB; + // Now, we go through all of the steps in each direction that we identified, and calculate the bounding boxes for each @@ -259,6 +262,11 @@ bool ExecuteSubRenderOperations(Config::Config* _Config, BG::Common::Logger::Log _Simulation->VSDAData_.Array_ = std::make_unique<VoxelArray>(_Logger, Empty, 999.); _Simulation->VSDAData_.State_ = VSDA_RENDER_DONE; + + // Decrement memory usage counter + _ImageProcessorPool->TotalConsumedMemory_MB -= MemorySize_MB; + + return true; } -- GitLab From 58b58f3d8dcef6913fe3116abd3fdc01c2ac14d0 Mon Sep 17 00:00:00 2001 From: Thomas Liao <tliao@carboncopies.org> Date: Mon, 24 Mar 2025 19:34:35 -0700 Subject: [PATCH 4/5] Bump memory consumption --- Source/Data/NES.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Data/NES.yaml b/Source/Data/NES.yaml index 6a159af40..6ec7d6ca6 100644 --- a/Source/Data/NES.yaml +++ b/Source/Data/NES.yaml @@ -1,5 +1,5 @@ Network_NES_API_Port: 8001 Network_NES_API_Host: 0.0.0.0 -VSDA_EM_PercentOfSysteMemoryLimit: 45 +VSDA_EM_PercentOfSysteMemoryLimit: 70 VSDA_EM_MaxVoxelArraySize: 5000 \ No newline at end of file -- GitLab From f5bba4f2cb1a15f908484a2b718ba1d5051f35c0 Mon Sep 17 00:00:00 2001 From: Thomas Liao <tliao@carboncopies.org> Date: Mon, 24 Mar 2025 19:56:40 -0700 Subject: [PATCH 5/5] Update config --- ThirdParty/NetmorphCMake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ThirdParty/NetmorphCMake b/ThirdParty/NetmorphCMake index b98b2cc54..66bb13e45 160000 --- a/ThirdParty/NetmorphCMake +++ b/ThirdParty/NetmorphCMake @@ -1 +1 @@ -Subproject commit b98b2cc5480fcfdcf19dff2857b9177d886648e5 +Subproject commit 66bb13e457d52db985be86e262690ec7dc053b79 -- GitLab