From 17f53cf54ec191ef836ecef7da7448d6b94d2d64 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 3 Nov 2018 12:28:27 +0100 Subject: [PATCH] WIP: some performance improvements, cronology debugging support (experimental) --- src/klayout.pri | 6 + .../tools/netx/db_plugin/dbHierProcessor.cc | 257 +++++++++++++----- .../tools/netx/db_plugin/dbHierProcessor.h | 82 ++++-- .../tools/netx/db_plugin/dbLocalOperation.cc | 8 +- .../tools/netx/db_plugin/dbLocalOperation.h | 10 +- .../netx/unit_tests/dbHierProcessorTests.cc | 4 +- 6 files changed, 277 insertions(+), 90 deletions(-) diff --git a/src/klayout.pri b/src/klayout.pri index 298273ebc..c09f225ce 100644 --- a/src/klayout.pri +++ b/src/klayout.pri @@ -97,6 +97,12 @@ equals(HAVE_RUBY, "1") { } } +equals(HAVE_CRONOLOGY, "1") { + DEFINES += HAVE_CRONOLOGY + LIBS += $$CRONOLOGY_LIB + INCLUDEPATH += $$CRONOLOGY_INCLUDE +} + msvc { QMAKE_CXXFLAGS += \ diff --git a/src/plugins/tools/netx/db_plugin/dbHierProcessor.cc b/src/plugins/tools/netx/db_plugin/dbHierProcessor.cc index faf06d33e..d390a4ab4 100644 --- a/src/plugins/tools/netx/db_plugin/dbHierProcessor.cc +++ b/src/plugins/tools/netx/db_plugin/dbHierProcessor.cc @@ -31,6 +31,33 @@ #include "tlTimer.h" #include "tlInternational.h" +// --------------------------------------------------------------------------------------------- +// Cronology debugging support (TODO: experimental) + +#if defined(HAVE_CRONOLOGY) + +#include + +CRONOLOGY_MAKE_EVENT(event_compute_contexts, "Compute contexts") +CRONOLOGY_MAKE_EVENT(event_compute_contexts_unlocked, "Compute contexts (unlocked)") + +cronology::events::event_collection collect_events; + +#define CRONOLOGY_COLLECTION_BRACKET(event_name) cronology::EventBracket __bracket##event_name (collect_events.threadwise ()->event ().event ()); + +CRONOLOGY_MAKE_EVENT(event_compute_results, "Compute results") +CRONOLOGY_MAKE_EVENT(event_compute_local_cell, "Compute local cell results") +CRONOLOGY_MAKE_EVENT(event_propagate, "Propagate local cell results") + +cronology::events::event_collection compute_events; + +#define CRONOLOGY_COMPUTE_BRACKET(event_name) cronology::EventBracket __bracket##event_name (compute_events.threadwise ()->event ().event ()); + +#else +#define CRONOLOGY_COLLECTION_BRACKET(event_name) +#define CRONOLOGY_COMPUTE_BRACKET(event_name) +#endif + namespace db { @@ -42,6 +69,7 @@ class shape_reference_translator { public: typedef typename Ref::shape_type shape_type; + typedef typename Ref::trans_type ref_trans_type; shape_reference_translator (db::Layout *target_layout) : mp_layout (target_layout) @@ -51,21 +79,102 @@ public: Ref operator() (const Ref &ref) const { - tl::MutexLocker locker (&mp_layout->lock ()); - shape_type sh = ref.obj ().transformed (ref.trans ()); - return Ref (sh, mp_layout->shape_repository ()); + typename std::unordered_map::const_iterator m = m_cache.find (ref.ptr ()); + if (m != m_cache.end ()) { + + return Ref (m->second, ref.trans ()); + + } else { + + const shape_type *ptr; + { + tl::MutexLocker locker (&mp_layout->lock ()); + ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (ref.obj ()); + } + + m_cache[ref.ptr ()] = ptr; + return Ref (ptr, ref.trans ()); + + } } template Ref operator() (const Ref &ref, const Trans &tr) const { - tl::MutexLocker locker (&mp_layout->lock ()); - shape_type sh = ref.obj ().transformed (tr * Trans (ref.trans ())); - return Ref (sh, mp_layout->shape_repository ()); + shape_type sh = ref.obj ().transformed (Trans (ref_trans_type (tr).inverted ()) * tr); + ref_trans_type red_trans; + sh.reduce (red_trans); + + typename std::unordered_map >::const_iterator m = m_cache_by_shape.find (sh); + if (m != m_cache_by_shape.end ()) { + + return Ref (m->second.first, ref_trans_type (tr * Trans (ref.trans ())) * m->second.second); + + } else { + + const shape_type *ptr; + { + tl::MutexLocker locker (&mp_layout->lock ()); + ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (sh); + } + + m_cache_by_shape[sh] = std::make_pair (ptr, red_trans); + return Ref (ptr, ref_trans_type (tr * Trans (ref.trans ())) * red_trans); + + } } private: db::Layout *mp_layout; + mutable std::unordered_map m_cache; + mutable std::unordered_map > m_cache_by_shape; +}; + +template +class shape_reference_translator_with_trans +{ +public: + typedef typename Ref::shape_type shape_type; + typedef typename Ref::trans_type ref_trans_type; + + shape_reference_translator_with_trans (db::Layout *target_layout, const Trans &trans) + : mp_layout (target_layout), m_trans (trans), m_ref_trans (trans), m_bare_trans (Trans (m_ref_trans.inverted ()) * trans) + { + // .. nothing yet .. + } + + Ref operator() (const Ref &ref) const + { + typename std::unordered_map >::const_iterator m = m_cache.find (ref.ptr ()); + if (m != m_cache.end ()) { + + return Ref (m->second.first, ref_trans_type (m_trans * Trans (ref.trans ())) * m->second.second); + + } else { + + shape_type sh = ref.obj ().transformed (m_bare_trans); + ref_trans_type red_trans; + sh.reduce (red_trans); + + const shape_type *ptr; + { + tl::MutexLocker locker (&mp_layout->lock ()); + ptr = mp_layout->shape_repository ().repository (typename shape_type::tag ()).insert (sh); + } + + m_cache[ref.ptr ()] = std::make_pair (ptr, red_trans); + + return Ref (ptr, ref_trans_type (m_trans * Trans (ref.trans ())) * red_trans); + + } + } + +private: + db::Layout *mp_layout; + Trans m_trans; + ref_trans_type m_ref_trans; + Trans m_bare_trans; + mutable std::unordered_map > m_cache; }; // --------------------------------------------------------------------------------------------- @@ -83,7 +192,7 @@ LocalProcessorCellContext::add (db::LocalProcessorCellContext *parent_context, d } void -LocalProcessorCellContext::propagate (const std::set &res) +LocalProcessorCellContext::propagate (const std::unordered_set &res) { if (res.empty ()) { return; @@ -95,13 +204,19 @@ LocalProcessorCellContext::propagate (const std::set &res) tl_assert (d->parent != 0); db::Layout *subject_layout = d->parent->layout (); - shape_reference_translator rt (subject_layout); - for (std::set::const_iterator r = res.begin (); r != res.end (); ++r) { - d->parent_context->propagated ().insert (rt (*r, d->cell_inst)); + shape_reference_translator_with_trans rt (subject_layout, d->cell_inst); + std::vector new_refs; + new_refs.reserve (res.size ()); + for (std::unordered_set::const_iterator r = res.begin (); r != res.end (); ++r) { + new_refs.push_back (rt (*r)); + } + + { + tl::MutexLocker locker (&d->parent_context->lock ()); + d->parent_context->propagated ().insert (new_refs.begin (), new_refs.end ()); } } - } // --------------------------------------------------------------------------------------------- @@ -122,7 +237,7 @@ LocalProcessorCellContexts::LocalProcessorCellContexts (const db::Cell *intruder db::LocalProcessorCellContext * LocalProcessorCellContexts::find_context (const key_type &intruders) { - std::map::iterator c = m_contexts.find (intruders); + std::unordered_map::iterator c = m_contexts.find (intruders); return c != m_contexts.end () ? &c->second : 0; } @@ -135,12 +250,14 @@ LocalProcessorCellContexts::create (const key_type &intruders) void LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &contexts, db::Cell *cell, const LocalOperation *op, unsigned int output_layer, const LocalProcessor *proc) { + CRONOLOGY_COMPUTE_BRACKET(event_compute_results) + bool first = true; - std::set common; + std::unordered_set common; int index = 0; int total = int (m_contexts.size ()); - for (std::map::iterator c = m_contexts.begin (); c != m_contexts.end (); ++c) { + for (std::unordered_map::iterator c = m_contexts.begin (); c != m_contexts.end (); ++c) { ++index; @@ -151,54 +268,68 @@ LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &conte if (first) { { - tl::MutexLocker locker (&contexts.lock ()); + tl::MutexLocker locker (&c->second.lock ()); common = c->second.propagated (); } + CRONOLOGY_COMPUTE_BRACKET(event_compute_local_cell) proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, c->first, common); first = false; } else { - std::set res; + std::unordered_set res; { - tl::MutexLocker locker (&contexts.lock ()); + tl::MutexLocker locker (&c->second.lock ()); res = c->second.propagated (); } - proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, c->first, res); + { + CRONOLOGY_COMPUTE_BRACKET(event_compute_local_cell) + proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, c->first, res); + } if (common.empty ()) { - tl::MutexLocker locker (&contexts.lock ()); + CRONOLOGY_COMPUTE_BRACKET(event_propagate) c->second.propagate (res); } else if (res != common) { - std::set lost; - std::set_difference (common.begin (), common.end (), res.begin (), res.end (), std::inserter (lost, lost.end ())); + CRONOLOGY_COMPUTE_BRACKET(event_propagate) + + std::unordered_set lost; + for (std::unordered_set::const_iterator i = common.begin (); i != common.end (); ++i) { + if (res.find (*i) == res.end ()) { + lost.insert (*i); + } + } if (! lost.empty ()) { - std::set new_common; - std::set_intersection (common.begin (), common.end (), res.begin (), res.end (), std::inserter (new_common, new_common.end ())); + std::unordered_set new_common; + for (std::unordered_set::const_iterator i = common.begin (); i != common.end (); ++i) { + if (res.find (*i) != res.end ()) { + new_common.insert (*i); + } + } common.swap (new_common); - for (std::map::iterator cc = m_contexts.begin (); cc != c; ++cc) { - tl::MutexLocker locker (&contexts.lock ()); + for (std::unordered_map::iterator cc = m_contexts.begin (); cc != c; ++cc) { cc->second.propagate (lost); } } - std::set gained; - std::set_difference (res.begin (), res.end (), common.begin (), common.end (), std::inserter (gained, gained.end ())); - - { - tl::MutexLocker locker (&contexts.lock ()); - c->second.propagate (gained); + std::unordered_set gained; + for (std::unordered_set::const_iterator i = res.begin (); i != res.end (); ++i) { + if (common.find (*i) == common.end ()) { + gained.insert (*i); + } } + c->second.propagate (gained); + } } @@ -256,7 +387,7 @@ ShapeInteractions::intruders_for (unsigned int subject_id) const const db::PolygonRef & ShapeInteractions::shape (unsigned int id) const { - std::map::const_iterator i = m_shapes.find (id); + std::unordered_map::const_iterator i = m_shapes.find (id); if (i == m_shapes.end ()) { static db::PolygonRef s; return s; @@ -363,7 +494,7 @@ private: unsigned int m_intruder_layer; db::Coord m_dist; ShapeInteractions *mp_result; - std::map, unsigned int> m_inst_shape_ids; + std::unordered_map, unsigned int> m_inst_shape_ids; void add_shapes_from_intruder_inst (unsigned int id1, const db::Cell &intruder_cell, const db::ICplxTrans &tn, unsigned int inst_id, const db::Box ®ion) { @@ -380,7 +511,7 @@ private: // reuse the same id for shapes from the same instance -> this avoid duplicates with different IDs on // the intruder side. - std::map, unsigned int>::const_iterator k = m_inst_shape_ids.find (std::make_pair (inst_id, ref2)); + std::unordered_map, unsigned int>::const_iterator k = m_inst_shape_ids.find (std::make_pair (inst_id, ref2)); if (k == m_inst_shape_ids.end ()) { k = m_inst_shape_ids.insert (std::make_pair (std::make_pair (inst_id, ref2), mp_result->next_id ())).first; @@ -408,7 +539,7 @@ instances_interact (const db::Layout *layout1, const db::CellInstArray *inst1, u const db::Cell &cell2 = layout2->cell (inst2->object ().cell_index ()); db::box_convert inst2_bc (*layout2, layer2); - std::set relative_trans_seen; + std::unordered_set relative_trans_seen; for (db::CellInstArray::iterator n = inst1->begin (); ! n.at_end (); ++n) { @@ -465,9 +596,9 @@ struct InteractionRegistrationInst2Inst : db::box_scanner_receiver2 { public: - typedef std::pair, std::set > interaction_value_type; + typedef std::pair, std::unordered_set > interaction_value_type; - InteractionRegistrationInst2Inst (const db::Layout *subject_layout, unsigned int subject_layer, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, std::map *result) + InteractionRegistrationInst2Inst (const db::Layout *subject_layout, unsigned int subject_layer, const db::Layout *intruder_layout, unsigned int intruder_layer, db::Coord dist, std::unordered_map *result) : mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), m_subject_layer (subject_layer), m_intruder_layer (intruder_layer), m_dist (dist), mp_result (result) { // nothing yet .. @@ -500,8 +631,8 @@ private: const db::Layout *mp_subject_layout, *mp_intruder_layout; unsigned int m_subject_layer, m_intruder_layer; db::Coord m_dist; - std::map, std::set > > *mp_result; - std::set > m_interactions; + std::unordered_map, std::unordered_set > > *mp_result; + std::unordered_set > m_interactions; }; static bool @@ -537,7 +668,7 @@ struct InteractionRegistrationInst2Shape : db::box_scanner_receiver2 { public: - InteractionRegistrationInst2Shape (const db::Layout *subject_layout, unsigned int subject_layer, db::Coord dist, std::map, std::set > > *result) + InteractionRegistrationInst2Shape (const db::Layout *subject_layout, unsigned int subject_layer, db::Coord dist, std::unordered_map, std::unordered_set > > *result) : mp_subject_layout (subject_layout), m_subject_layer (subject_layer), m_dist (dist), mp_result (result) { // nothing yet .. @@ -554,7 +685,7 @@ private: const db::Layout *mp_subject_layout; unsigned int m_subject_layer; db::Coord m_dist; - std::map, std::set > > *mp_result; + std::unordered_map, std::unordered_set > > *mp_result; }; } @@ -562,7 +693,7 @@ private: // --------------------------------------------------------------------------------------------- // LocalProcessorContextComputationTask implementation -LocalProcessorContextComputationTask::LocalProcessorContextComputationTask (const LocalProcessor *proc, LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair, std::set > &intruders, db::Coord dist) +LocalProcessorContextComputationTask::LocalProcessorContextComputationTask (const LocalProcessor *proc, LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair, std::unordered_set > &intruders, db::Coord dist) : tl::Task (), mp_proc (proc), mp_contexts (&contexts), mp_parent_context (parent_context), mp_subject_parent (subject_parent), mp_subject_cell (subject_cell), m_subject_cell_inst (subject_cell_inst), @@ -630,7 +761,7 @@ void LocalProcessor::run (LocalOperation *op, unsigned int subject_layer, unsign compute_results (contexts, op, output_layer); } -void LocalProcessor::push_results (db::Cell *cell, unsigned int output_layer, const std::set &result) const +void LocalProcessor::push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set &result) const { if (! result.empty ()) { tl::MutexLocker locker (&cell->layout ()->lock ()); @@ -654,7 +785,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const L contexts.set_intruder_layer (intruder_layer); contexts.set_subject_layer (subject_layer); - std::pair, std::set > intruders; + std::pair, std::unordered_set > intruders; issue_compute_contexts (contexts, 0, 0, mp_subject_top, db::ICplxTrans (), mp_intruder_top, intruders, op->dist ()); if (mp_cc_job.get ()) { @@ -674,7 +805,7 @@ void LocalProcessor::issue_compute_contexts (LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, - std::pair, std::set > &intruders, + std::pair, std::unordered_set > &intruders, db::Coord dist) const { bool is_small_job = subject_cell->begin ().at_end (); @@ -692,9 +823,11 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, - const std::pair, std::set > &intruders, + const std::pair, std::unordered_set > &intruders, db::Coord dist) const { + CRONOLOGY_COLLECTION_BRACKET(event_compute_contexts) + if (tl::verbosity () >= 30) { if (! subject_parent) { tl::log << tr ("Computing context for top cell ") << mp_subject_layout->cell_name (subject_cell->cell_index ()); @@ -726,6 +859,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, // perform the actual task .. + CRONOLOGY_COLLECTION_BRACKET(event_compute_contexts_unlocked) const db::Shapes *intruder_shapes = 0; if (intruder_cell) { intruder_shapes = &intruder_cell->shapes (contexts.intruder_layer ()); @@ -740,9 +874,9 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, if (! subject_cell->begin ().at_end ()) { - typedef std::pair, std::set > interaction_value_type; + typedef std::pair, std::unordered_set > interaction_value_type; - std::map interactions; + std::unordered_map interactions; // insert dummy interactions to handle at least the child cell vs. itself // - this is important so we will always handle the instances unless they are @@ -792,7 +926,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, } - for (std::set::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { + for (std::unordered_set::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { if (! inst_bci (*i).empty ()) { scanner.insert2 (i.operator-> (), ++id); } @@ -811,7 +945,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, } } - for (std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { + for (std::unordered_set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { scanner.insert2 (i.operator-> (), 0); } @@ -824,10 +958,9 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, scanner.process (rec, dist, inst_bcs, db::box_convert ()); } - for (std::map::const_iterator i = interactions.begin (); i != interactions.end (); ++i) { + for (std::unordered_map::const_iterator i = interactions.begin (); i != interactions.end (); ++i) { db::Cell &subject_child_cell = mp_subject_layout->cell (i->first->object ().cell_index ()); - db::shape_reference_translator rt (mp_subject_layout); for (db::CellInstArray::iterator n = i->first->begin (); ! n.at_end (); ++n) { @@ -837,17 +970,19 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, if (! nbox.empty ()) { - std::pair, std::set > intruders_below; + std::pair, std::unordered_set > intruders_below; - for (std::set::const_iterator p = i->second.second.begin (); p != i->second.second.end (); ++p) { + db::shape_reference_translator_with_trans rt (mp_subject_layout, tni); + + for (std::unordered_set::const_iterator p = i->second.second.begin (); p != i->second.second.end (); ++p) { if (nbox.overlaps (p->box ())) { - intruders_below.second.insert (rt (*p, tni)); + intruders_below.second.insert (rt (*p)); } } // TODO: in some cases, it may be possible to optimize this for arrays - for (std::set::const_iterator j = i->second.first.begin (); j != i->second.first.end (); ++j) { + for (std::unordered_set::const_iterator j = i->second.first.begin (); j != i->second.first.end (); ++j) { for (db::CellInstArray::iterator k = (*j)->begin_touching (nbox.enlarged (db::Vector (-1, -1)), inst_bcii); ! k.at_end (); ++k) { db::ICplxTrans tk = (*j)->complex_trans (*k); // NOTE: no self-interactions @@ -899,7 +1034,7 @@ LocalProcessor::compute_results (LocalProcessorContexts &contexts, const LocalOp tl::SelfTimer timer (tl::verbosity () >= 21, tl::sprintf (tl::to_string (tr ("Computing results iteration #%d")), iter)); bool any = false; - std::set later; + std::unordered_set later; std::vector next_cells_bu; next_cells_bu.reserve (cells_bu.size ()); @@ -954,7 +1089,7 @@ LocalProcessor::compute_results (LocalProcessorContexts &contexts, const LocalOp } void -LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const db::LocalOperation *op, const std::pair, std::set > &intruders, std::set &result) const +LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const db::LocalOperation *op, const std::pair, std::unordered_set > &intruders, std::unordered_set &result) const { const db::Shapes *subject_shapes = &subject_cell->shapes (contexts.subject_layer ()); @@ -1001,7 +1136,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db:: scanner.insert (ref, id++); } - for (std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { + for (std::unordered_set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { scanner.insert (i.operator-> (), interactions.next_id ()); } @@ -1018,7 +1153,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db:: scanner.insert1 (ref, id++); } - for (std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { + for (std::unordered_set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { scanner.insert2 (i.operator-> (), interactions.next_id ()); } @@ -1060,7 +1195,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db:: } } - for (std::set::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { + for (std::unordered_set::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { if (! inst_bci (*i).empty ()) { scanner.insert2 (i.operator-> (), ++inst_id); } diff --git a/src/plugins/tools/netx/db_plugin/dbHierProcessor.h b/src/plugins/tools/netx/db_plugin/dbHierProcessor.h index 948352e13..307d32569 100644 --- a/src/plugins/tools/netx/db_plugin/dbHierProcessor.h +++ b/src/plugins/tools/netx/db_plugin/dbHierProcessor.h @@ -33,6 +33,46 @@ #include #include #include +#include +#include + +// @@@ should go into dbHash.h +#include "dbHash.h" + +namespace std +{ + template + struct hash > + { + size_t operator() (const db::disp_trans &t) const + { + return hfunc (t.disp ()); + } + }; + + template + struct hash > + { + size_t operator() (const db::polygon_ref &o) const + { + return hfunc (size_t (o.ptr ()), std::hash () (o.trans ())); + } + }; + + template + struct hash > + { + size_t operator() (const std::unordered_set &o) const + { + size_t hf = 0; + for (typename std::unordered_set::const_iterator i = o.begin (); i != o.end (); ++i) { + hf = hfunc (hf, std::hash () (*i)); + } + return hf; + } + }; +} + namespace db { @@ -45,7 +85,7 @@ class LocalProcessorContexts; class DB_PLUGIN_PUBLIC ShapeInteractions { public: - typedef std::map > container; + typedef std::unordered_map > container; typedef container::const_iterator iterator; typedef container::value_type::second_type::const_iterator iterator2; @@ -74,8 +114,8 @@ public: } private: - std::map > m_interactions; - std::map m_shapes; + std::unordered_map > m_interactions; + std::unordered_map m_shapes; unsigned int m_id; }; @@ -102,14 +142,14 @@ public: LocalProcessorCellContext (); void add (db::LocalProcessorCellContext *parent_context, db::Cell *parent, const db::ICplxTrans &cell_inst); - void propagate (const std::set &res); + void propagate (const std::unordered_set &res); - std::set &propagated () + std::unordered_set &propagated () { return m_propagated; } - const std::set &propagated () const + const std::unordered_set &propagated () const { return m_propagated; } @@ -119,16 +159,22 @@ public: return m_drops.size (); } + tl::Mutex &lock () + { + return m_lock; + } + private: - std::set m_propagated; + std::unordered_set m_propagated; std::vector m_drops; + tl::Mutex m_lock; }; class DB_PLUGIN_PUBLIC LocalProcessorCellContexts { public: - typedef std::pair, std::set > key_type; - typedef std::map map_type; + typedef std::pair, std::unordered_set > key_type; + typedef std::unordered_map map_type; typedef map_type::const_iterator iterator; LocalProcessorCellContexts (); @@ -150,13 +196,13 @@ public: private: const db::Cell *mp_intruder_cell; - std::map m_contexts; + std::unordered_map m_contexts; }; class DB_PLUGIN_PUBLIC LocalProcessorContexts { public: - typedef std::map contexts_per_cell_type; + typedef std::unordered_map contexts_per_cell_type; typedef contexts_per_cell_type::iterator iterator; LocalProcessorContexts () @@ -229,7 +275,7 @@ class DB_PLUGIN_PUBLIC LocalProcessorContextComputationTask : public tl::Task { public: - LocalProcessorContextComputationTask (const LocalProcessor *proc, LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair, std::set > &intruders, db::Coord dist); + LocalProcessorContextComputationTask (const LocalProcessor *proc, LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair, std::unordered_set > &intruders, db::Coord dist); void perform (); private: @@ -240,7 +286,7 @@ private: db::Cell *mp_subject_cell; db::ICplxTrans m_subject_cell_inst; const db::Cell *mp_intruder_cell; - std::pair, std::set > m_intruders; + std::pair, std::unordered_set > m_intruders; db::Coord m_dist; }; @@ -324,11 +370,11 @@ private: mutable std::auto_ptr > mp_cc_job; std::string description (const LocalOperation *op) const; - void compute_contexts (db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const std::pair, std::set > &intruders, db::Coord dist) const; - void do_compute_contexts (db::LocalProcessorCellContext *cell_context, const db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const std::pair, std::set > &intruders, db::Coord dist) const; - void issue_compute_contexts (db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair, std::set > &intruders, db::Coord dist) const; - void push_results (db::Cell *cell, unsigned int output_layer, const std::set &result) const; - void compute_local_cell (const db::LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const LocalOperation *op, const std::pair, std::set > &intruders, std::set &result) const; + void compute_contexts (db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const std::pair, std::unordered_set > &intruders, db::Coord dist) const; + void do_compute_contexts (db::LocalProcessorCellContext *cell_context, const db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, const std::pair, std::unordered_set > &intruders, db::Coord dist) const; + void issue_compute_contexts (db::LocalProcessorContexts &contexts, db::LocalProcessorCellContext *parent_context, db::Cell *subject_parent, db::Cell *subject_cell, const db::ICplxTrans &subject_cell_inst, const db::Cell *intruder_cell, std::pair, std::unordered_set > &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::LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const LocalOperation *op, const std::pair, std::unordered_set > &intruders, std::unordered_set &result) const; }; } diff --git a/src/plugins/tools/netx/db_plugin/dbLocalOperation.cc b/src/plugins/tools/netx/db_plugin/dbLocalOperation.cc index 744342b0b..a9e5300f8 100644 --- a/src/plugins/tools/netx/db_plugin/dbLocalOperation.cc +++ b/src/plugins/tools/netx/db_plugin/dbLocalOperation.cc @@ -47,7 +47,7 @@ public: /** * @brief Constructor specifying an external vector for storing the polygons */ - PolygonRefGenerator (db::Layout *layout, std::set &polyrefs) + PolygonRefGenerator (db::Layout *layout, std::unordered_set &polyrefs) : PolygonSink (), mp_layout (layout), mp_polyrefs (&polyrefs) { } @@ -62,7 +62,7 @@ public: private: db::Layout *mp_layout; - std::set *mp_polyrefs; + std::unordered_set *mp_polyrefs; }; } @@ -88,7 +88,7 @@ BoolAndOrNotLocalOperation::description () const } void -BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set &result) const +BoolAndOrNotLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set &result) const { db::EdgeProcessor ep; @@ -147,7 +147,7 @@ SelfOverlapMergeLocalOperation::SelfOverlapMergeLocalOperation (unsigned int wra // .. nothing yet .. } -void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set &result) const +void SelfOverlapMergeLocalOperation::compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set &result) const { if (m_wrap_count == 0) { return; diff --git a/src/plugins/tools/netx/db_plugin/dbLocalOperation.h b/src/plugins/tools/netx/db_plugin/dbLocalOperation.h index 6f726dd24..330d71441 100644 --- a/src/plugins/tools/netx/db_plugin/dbLocalOperation.h +++ b/src/plugins/tools/netx/db_plugin/dbLocalOperation.h @@ -28,8 +28,8 @@ #include "dbLayout.h" #include "dbPluginCommon.h" -#include -#include +#include +#include #include namespace db @@ -87,7 +87,7 @@ public: * @param interactions The interaction set * @param result The container to which the results are written */ - virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set &result) const = 0; + virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set &result) const = 0; /** * @brief Indicates the desired behaviour when a shape does not have an intruder @@ -115,7 +115,7 @@ class DB_PLUGIN_PUBLIC BoolAndOrNotLocalOperation public: BoolAndOrNotLocalOperation (bool is_and); - virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set &result) const; + virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set &result) const; virtual on_empty_intruder_mode on_empty_intruder_hint () const; virtual std::string description () const; @@ -134,7 +134,7 @@ class DB_PLUGIN_PUBLIC SelfOverlapMergeLocalOperation public: SelfOverlapMergeLocalOperation (unsigned int wrap_count); - virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::set &result) const; + virtual void compute_local (db::Layout *layout, const ShapeInteractions &interactions, std::unordered_set &result) const; virtual on_empty_intruder_mode on_empty_intruder_hint () const; virtual std::string description () const; diff --git a/src/plugins/tools/netx/unit_tests/dbHierProcessorTests.cc b/src/plugins/tools/netx/unit_tests/dbHierProcessorTests.cc index d28ee65b5..94ac38232 100644 --- a/src/plugins/tools/netx/unit_tests/dbHierProcessorTests.cc +++ b/src/plugins/tools/netx/unit_tests/dbHierProcessorTests.cc @@ -55,7 +55,7 @@ public: // .. nothing yet .. } - virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &interactions, std::set &result) const + virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &interactions, std::unordered_set &result) const { db::ShapeInteractions sized_interactions = interactions; for (db::ShapeInteractions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) { @@ -91,7 +91,7 @@ public: // .. nothing yet .. } - virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &interactions, std::set &result) const + virtual void compute_local (db::Layout *layout, const db::ShapeInteractions &interactions, std::unordered_set &result) const { db::ShapeInteractions sized_interactions = interactions; for (db::ShapeInteractions::iterator i = sized_interactions.begin (); i != sized_interactions.end (); ++i) {