From a8119c5a5330d0b1b044c8d4b24a598e554bb5d5 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Wed, 18 Feb 2026 18:37:54 +0100 Subject: [PATCH] Performance improvement for hierarchical processor Problem was pushing of the results into the cell hierarchy somehow lead to thread stalling. Likely due to bbox invalidation and related effects. Solution is to store the results of the operations inside the context structure (along with the propagation information) and push it to the layout later in a single step. --- src/db/db/dbHierProcessor.cc | 35 +++++++++++++++++++++++------------ src/db/db/dbHierProcessor.h | 12 +++++++++++- src/db/db/dbHierProcessor2.cc | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index f13935fd9..a6af1f211 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -714,7 +714,6 @@ local_processor_result_computation_task::perform () { mp_cell_contexts->compute_results (*mp_contexts, mp_cell, mp_op, m_output_layers, mp_proc); - // erase the contexts we don't need any longer { tl::MutexLocker locker (& mp_contexts->lock ()); @@ -734,7 +733,10 @@ local_processor_result_computation_task::perform () } #endif - mp_contexts->context_map ().erase (mp_cell); + // release some memory + auto ctx = mp_contexts->context_map ().find (mp_cell); + tl_assert (ctx != mp_contexts->context_map ().end ()); + ctx->second.cleanup (); } } @@ -881,15 +883,6 @@ void local_processor::run (local_operation *op, unsigned compute_results (contexts, op, output_layers); } -template -void local_processor::push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set &result) const -{ - if (! result.empty ()) { - tl::MutexLocker locker (&cell->layout ()->lock ()); - cell->shapes (output_layer).insert (result.begin (), result.end ()); - } -} - template void local_processor::compute_contexts (local_processor_contexts &contexts, const local_operation *op, unsigned int subject_layer, const std::vector &intruder_layers) const { @@ -1248,7 +1241,7 @@ local_processor::compute_results (local_processor_contexts::iterator cpc = contexts.context_map ().find (&mp_subject_layout->cell (*bu)); if (cpc != contexts.context_map ().end ()) { cpc->second.compute_results (contexts, cpc->first, op, output_layers, this); - contexts.context_map ().erase (cpc); + cpc->second.cleanup (); // release some memory } } @@ -1261,6 +1254,24 @@ local_processor::compute_results (local_processor_contextslock ()); + for (auto c = contexts.begin (); c != contexts.end (); ++c) { + + db::Cell *cell = c->first; + auto r = c->second.result ().begin (); + auto rend = c->second.result ().end (); + + for (auto o = output_layers.begin (); r != rend && o != output_layers.end (); ++o, ++r) { + if (! r->empty ()) { + cell->shapes (*o).insert (r->begin (), r->end ()); + } + } + + } + } } namespace { diff --git a/src/db/db/dbHierProcessor.h b/src/db/db/dbHierProcessor.h index 44705178f..c52dd372e 100644 --- a/src/db/db/dbHierProcessor.h +++ b/src/db/db/dbHierProcessor.h @@ -244,9 +244,20 @@ public: return m_contexts.end (); } + const std::vector > &result () const + { + return m_result; + } + + void cleanup () + { + m_contexts.clear (); + } + private: const db::Cell *mp_intruder_cell; std::unordered_map > m_contexts; + std::vector > m_result; }; template @@ -558,7 +569,6 @@ private: size_t get_progress () const; void compute_contexts (db::local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const; void issue_compute_contexts (db::local_processor_contexts &contexts, db::local_processor_cell_context *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, typename local_processor_cell_contexts::context_key_type &intruders, db::Coord dist) const; - void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set &result) const; void compute_local_cell (const db::local_processor_contexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation *op, const typename local_processor_cell_contexts::context_key_type &intruders, std::vector > &result) const; bool subject_cell_is_breakout (db::cell_index_type ci) const diff --git a/src/db/db/dbHierProcessor2.cc b/src/db/db/dbHierProcessor2.cc index a7909bb9b..5f7be3cc0 100644 --- a/src/db/db/dbHierProcessor2.cc +++ b/src/db/db/dbHierProcessor2.cc @@ -446,7 +446,12 @@ local_processor_cell_contexts::compute_results (const local_processo proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, *c->first, res); } - if (common.empty ()) { + bool common_empty = true; + for (auto c = common.begin (); common_empty && c != common.end (); ++c) { + common_empty = c->empty (); + } + + if (common_empty) { CRONOLOGY_COMPUTE_BRACKET(event_propagate) for (std::vector::const_iterator o = output_layers.begin (); o != output_layers.end (); ++o) { @@ -519,9 +524,30 @@ local_processor_cell_contexts::compute_results (const local_processo } - for (std::vector::const_iterator o = output_layers.begin (); o != output_layers.end (); ++o) { - size_t oi = o - output_layers.begin (); - proc->push_results (cell, *o, common[oi]); + // store the results + + bool common_empty = true; + for (auto c = common.begin (); common_empty && c != common.end (); ++c) { + common_empty = c->empty (); + } + + if (! common_empty) { + if (m_result.empty ()) { + m_result.swap (common); + } else { + if (m_result.size () < common.size ()) { + m_result.resize (common.size ()); + } + auto t = m_result.begin (); + for (auto s = common.begin (); s != common.end (); ++s, ++t) { + if (t->empty ()) { + t->swap (*s); + } else { + t->insert (s->begin (), s->end ()); + s->clear (); + } + } + } } }