diff --git a/src/db/db/dbHash.h b/src/db/db/dbHash.h index 5f5ecb481..5c14ce12a 100644 --- a/src/db/db/dbHash.h +++ b/src/db/db/dbHash.h @@ -404,6 +404,22 @@ namespace std return hf; } }; + + /** + * @brief Generic hash for an ordered set + */ + template + struct hash > + { + size_t operator() (const std::set &o) const + { + size_t hf = 0; + for (typename std::set::const_iterator i = o.begin (); i != o.end (); ++i) { + hf = hfunc (hf, std::hash () (*i)); + } + return hf; + } + }; } #endif diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index a2f4d83d6..73fb42941 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -242,14 +242,14 @@ LocalProcessorCellContexts::LocalProcessorCellContexts (const db::Cell *intruder } db::LocalProcessorCellContext * -LocalProcessorCellContexts::find_context (const key_type &intruders) +LocalProcessorCellContexts::find_context (const context_key_type &intruders) { - std::unordered_map::iterator c = m_contexts.find (intruders); + std::unordered_map::iterator c = m_contexts.find (intruders); return c != m_contexts.end () ? &c->second : 0; } db::LocalProcessorCellContext * -LocalProcessorCellContexts::create (const key_type &intruders) +LocalProcessorCellContexts::create (const context_key_type &intruders) { return &m_contexts[intruders]; } @@ -290,6 +290,18 @@ subtract (std::unordered_set &res, const std::unordered_set &a, const std::pair &b) + { + return *a.first < *b.first; + } +}; + +} + void LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &contexts, db::Cell *cell, const LocalOperation *op, unsigned int output_layer, const LocalProcessor *proc) { @@ -300,7 +312,19 @@ LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &conte int index = 0; int total = int (m_contexts.size ()); - for (std::unordered_map::iterator c = m_contexts.begin (); c != m_contexts.end (); ++c) { + + // NOTE: we use the ordering provided by key_type::operator< rather than the unordered map to achieve + // reproducability across different platforms. unordered_map is faster, but for processing them, + // strict ordering is a more robust choice. + std::vector > sorted_contexts; + sorted_contexts.reserve (m_contexts.size ()); + for (std::unordered_map::iterator c = m_contexts.begin (); c != m_contexts.end (); ++c) { + sorted_contexts.push_back (std::make_pair (&c->first, &c->second)); + } + + std::sort (sorted_contexts.begin (), sorted_contexts.end (), context_sorter ()); + + for (std::vector >::const_iterator c = sorted_contexts.begin (); c != sorted_contexts.end (); ++c) { ++index; @@ -311,31 +335,31 @@ LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &conte if (first) { { - tl::MutexLocker locker (&c->second.lock ()); - common = c->second.propagated (); + 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); + proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, *c->first, common); first = false; } else { std::unordered_set res; { - tl::MutexLocker locker (&c->second.lock ()); - res = c->second.propagated (); + tl::MutexLocker locker (&c->second->lock ()); + res = c->second->propagated (); } { CRONOLOGY_COMPUTE_BRACKET(event_compute_local_cell) - proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, c->first, res); + proc->compute_local_cell (contexts, cell, mp_intruder_cell, op, *c->first, res); } if (common.empty ()) { CRONOLOGY_COMPUTE_BRACKET(event_propagate) - c->second.propagate (res); + c->second->propagate (res); } else if (res != common) { @@ -354,8 +378,8 @@ LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &conte if (! lost.empty ()) { subtract (common, lost, cell->layout (), proc->max_vertex_count (), proc->area_ratio ()); - for (std::unordered_map::iterator cc = m_contexts.begin (); cc != c; ++cc) { - cc->second.propagate (lost); + for (std::vector >::const_iterator cc = sorted_contexts.begin (); cc != c; ++cc) { + cc->second->propagate (lost); } } @@ -373,7 +397,7 @@ LocalProcessorCellContexts::compute_results (const LocalProcessorContexts &conte subtract (gained, common, cell->layout (), proc->max_vertex_count (), proc->area_ratio ()); if (! gained.empty ()) { - c->second.propagate (gained); + c->second->propagate (gained); } } @@ -740,7 +764,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::unordered_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, LocalProcessorCellContexts::context_key_type &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), @@ -849,7 +873,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, const L contexts.set_intruder_layer (intruder_layer); contexts.set_subject_layer (subject_layer); - std::pair, std::unordered_set > intruders; + LocalProcessorCellContexts::context_key_type intruders; issue_compute_contexts (contexts, 0, 0, mp_subject_top, db::ICplxTrans (), mp_intruder_top, intruders, op->dist ()); if (mp_cc_job.get ()) { @@ -869,7 +893,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::unordered_set > &intruders, + LocalProcessorCellContexts::context_key_type &intruders, db::Coord dist) const { bool is_small_job = subject_cell->begin ().at_end (); @@ -887,7 +911,7 @@ 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::unordered_set > &intruders, + const LocalProcessorCellContexts::context_key_type &intruders, db::Coord dist) const { CRONOLOGY_COLLECTION_BRACKET(event_compute_contexts) @@ -1008,7 +1032,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, } - for (std::unordered_set::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { + for (std::set::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { if (! inst_bci (*i).empty ()) { scanner.insert2 (i.operator-> (), ++id); } @@ -1028,7 +1052,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, } } - for (std::unordered_set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { + for (std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { scanner.insert2 (i.operator-> (), 0); } @@ -1053,7 +1077,7 @@ void LocalProcessor::compute_contexts (LocalProcessorContexts &contexts, if (! nbox.empty ()) { - std::pair, std::unordered_set > intruders_below; + LocalProcessorCellContexts::context_key_type intruders_below; db::shape_reference_translator_with_trans rt (mp_subject_layout, tni); @@ -1173,7 +1197,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::unordered_set > &intruders, std::unordered_set &result) const +LocalProcessor::compute_local_cell (const db::LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const LocalOperation *op, const LocalProcessorCellContexts::context_key_type &intruders, std::unordered_set &result) const { const db::Shapes *subject_shapes = &subject_cell->shapes (contexts.subject_layer ()); @@ -1221,7 +1245,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db:: } // TODO: TODO: can we confine this search to the subject's (sized) bounding box? - for (std::unordered_set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { + for (std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { scanner.insert (i.operator-> (), interactions.next_id ()); } @@ -1239,7 +1263,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db:: } // TODO: can we confine this search to the subject's (sized) bounding box? - for (std::unordered_set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { + for (std::set::const_iterator i = intruders.second.begin (); i != intruders.second.end (); ++i) { scanner.insert2 (i.operator-> (), interactions.next_id ()); } @@ -1284,7 +1308,7 @@ LocalProcessor::compute_local_cell (const LocalProcessorContexts &contexts, db:: } // TODO: can we confine this search to the subject's (sized) bounding box? - for (std::unordered_set::const_iterator i = intruders.first.begin (); i != intruders.first.end (); ++i) { + for (std::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/db/db/dbHierProcessor.h b/src/db/db/dbHierProcessor.h index 5ed1ecb4e..5bc2cf4d1 100644 --- a/src/db/db/dbHierProcessor.h +++ b/src/db/db/dbHierProcessor.h @@ -152,15 +152,15 @@ private: class DB_PUBLIC LocalProcessorCellContexts { public: - typedef std::pair, std::unordered_set > key_type; - typedef std::unordered_map map_type; - typedef map_type::const_iterator iterator; + typedef std::pair, std::set > context_key_type; + typedef std::unordered_map context_map_type; + typedef context_map_type::const_iterator iterator; LocalProcessorCellContexts (); LocalProcessorCellContexts (const db::Cell *intruder_cell); - db::LocalProcessorCellContext *find_context (const key_type &intruders); - db::LocalProcessorCellContext *create (const key_type &intruders); + db::LocalProcessorCellContext *find_context (const context_key_type &intruders); + db::LocalProcessorCellContext *create (const context_key_type &intruders); void compute_results (const LocalProcessorContexts &contexts, db::Cell *cell, const LocalOperation *op, unsigned int output_layer, const LocalProcessor *proc); iterator begin () const @@ -175,7 +175,7 @@ public: private: const db::Cell *mp_intruder_cell; - std::unordered_map m_contexts; + std::unordered_map m_contexts; }; class DB_PUBLIC LocalProcessorContexts @@ -260,7 +260,7 @@ class DB_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::unordered_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, LocalProcessorCellContexts::context_key_type &intruders, db::Coord dist); void perform (); private: @@ -271,7 +271,7 @@ private: db::Cell *mp_subject_cell; db::ICplxTrans m_subject_cell_inst; const db::Cell *mp_intruder_cell; - std::pair, std::unordered_set > m_intruders; + LocalProcessorCellContexts::context_key_type m_intruders; db::Coord m_dist; }; @@ -382,11 +382,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::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 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 LocalProcessorCellContexts::context_key_type &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 LocalProcessorCellContexts::context_key_type &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, LocalProcessorCellContexts::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::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; + void compute_local_cell (const db::LocalProcessorContexts &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const LocalOperation *op, const LocalProcessorCellContexts::context_key_type &intruders, std::unordered_set &result) const; }; } diff --git a/testdata/algo/deep_region_au6.gds b/testdata/algo/deep_region_au6.gds index 6609f6f40..9fecea99f 100644 Binary files a/testdata/algo/deep_region_au6.gds and b/testdata/algo/deep_region_au6.gds differ diff --git a/testdata/algo/hlp12.oas b/testdata/algo/hlp12.oas index 6abd3565c..498b14606 100644 Binary files a/testdata/algo/hlp12.oas and b/testdata/algo/hlp12.oas differ diff --git a/testdata/algo/hlp14.oas b/testdata/algo/hlp14.oas index 47926a477..6bc579ab6 100644 Binary files a/testdata/algo/hlp14.oas and b/testdata/algo/hlp14.oas differ diff --git a/testdata/algo/hlp6.oas b/testdata/algo/hlp6.oas index 92c5b9f82..7c4fd80e9 100644 Binary files a/testdata/algo/hlp6.oas and b/testdata/algo/hlp6.oas differ