mirror of https://github.com/KLayout/klayout.git
WIP: performance improvement of hier local processor
The solution is to take intruder instances from as far as possible in the hierarchy. This provides a performance improvement in some cases, specifically if this leads to compression of contexts.
This commit is contained in:
parent
5ed41cc345
commit
7c5ae471ab
|
|
@ -1235,7 +1235,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
|||
if (subject_cell == intruder_cell) {
|
||||
|
||||
// Use the same id's for same instances - this way we can easily detect same instances
|
||||
// and don't make the self-interacting
|
||||
// and don't make them self-interacting
|
||||
|
||||
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
|
||||
unsigned int iid = ++id;
|
||||
|
|
@ -1327,7 +1327,11 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
|||
db::ICplxTrans tk = (*j)->complex_trans (*k);
|
||||
// NOTE: no self-interactions
|
||||
if (i->first != *j || tn != tk) {
|
||||
intruders_below.first.insert (db::CellInstArray (db::CellInst ((*j)->object ().cell_index ()), tni * tk));
|
||||
// optimize the intruder instance so it will be as low as possible
|
||||
std::pair<bool, db::CellInstArray> ei = effective_instance (contexts, i->first->object ().cell_index (), (*j)->object ().cell_index (), tni * tk, dist);
|
||||
if (ei.first) {
|
||||
intruders_below.first.insert (ei.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1342,6 +1346,64 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a cell instance array suitable for adding as intruder
|
||||
*
|
||||
* The given intruder cell with the transformation ti2s - which transforms the intruder instance into
|
||||
* the coordinate system of the subject cell - is analysed and either this instance or a sub-instance
|
||||
* is chosen.
|
||||
* Sub-instances are chosen if the intruder cell does not have shapes which interact with the subject
|
||||
* cell and there is exactly one sub-instance interacting with the subject cell.
|
||||
*/
|
||||
template <class TS, class TI, class TR>
|
||||
std::pair<bool, db::CellInstArray>
|
||||
local_processor<TS, TI, TR>::effective_instance (local_processor_contexts<TS, TI, TR> &contexts, db::cell_index_type subject_cell_index, db::cell_index_type intruder_cell_index, const db::ICplxTrans &ti2s, db::Coord dist) const
|
||||
{
|
||||
db::Box bbox = safe_box_enlarged (mp_subject_layout->cell (subject_cell_index).bbox (contexts.subject_layer ()), dist - 1, dist - 1);
|
||||
if (bbox.empty ()) {
|
||||
// should not happen, but skip if it does
|
||||
return std::make_pair (false, db::CellInstArray ());
|
||||
}
|
||||
|
||||
db::Box ibbox = bbox.transformed (ti2s.inverted ());
|
||||
|
||||
const db::Cell &intruder_cell = mp_intruder_layout->cell (intruder_cell_index);
|
||||
const db::Shapes &intruder_shapes = intruder_cell.shapes (contexts.intruder_layer ());
|
||||
if (! intruder_shapes.empty () && ! intruder_shapes.begin_touching (ibbox, db::ShapeIterator::All).at_end ()) {
|
||||
return std::make_pair (true, db::CellInstArray (db::CellInst (intruder_cell_index), ti2s));
|
||||
}
|
||||
|
||||
db::box_convert <db::CellInst, true> inst_bcii (*mp_intruder_layout, contexts.intruder_layer ());
|
||||
|
||||
size_t ni = 0;
|
||||
db::cell_index_type eff_cell_index = 0;
|
||||
db::ICplxTrans eff_trans;
|
||||
|
||||
for (db::Cell::touching_iterator i = intruder_cell.begin_touching (ibbox); ! i.at_end() && ni < 2; ++i) {
|
||||
const db::CellInstArray &ci = i->cell_inst ();
|
||||
db::Box cbox = mp_intruder_layout->cell (ci.object ().cell_index ()).bbox (contexts.intruder_layer ());
|
||||
for (db::CellInstArray::iterator k = ci.begin_touching (ibbox, inst_bcii); ! k.at_end () && ni < 2; ++k) {
|
||||
db::ICplxTrans tk = ci.complex_trans (*k);
|
||||
if (ibbox.overlaps (cbox.transformed (tk))) {
|
||||
eff_trans = tk;
|
||||
eff_cell_index = ci.object ().cell_index ();
|
||||
++ni;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ni == 0) {
|
||||
// should not happen, but skip if it does
|
||||
return std::make_pair (false, db::CellInstArray ());
|
||||
} else if (ni == 1) {
|
||||
// one instance - dive down
|
||||
return effective_instance (contexts, subject_cell_index, eff_cell_index, ti2s * eff_trans, dist);
|
||||
} else {
|
||||
return std::make_pair (true, db::CellInstArray (db::CellInst (intruder_cell_index), ti2s));
|
||||
}
|
||||
}
|
||||
|
||||
template <class TS, class TI, class TR>
|
||||
|
|
|
|||
|
|
@ -434,6 +434,7 @@ private:
|
|||
void issue_compute_contexts (db::local_processor_contexts<TS, TI, TR> &contexts, db::local_processor_cell_context<TS, TI, TR> *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<TS, TI, TR>::context_key_type &intruders, db::Coord dist) const;
|
||||
void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set<TR> &result) const;
|
||||
void compute_local_cell (const db::local_processor_contexts<TS, TI, TR> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<TS, TI, TR> *op, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, std::unordered_set<TR> &result) const;
|
||||
std::pair<bool, db::CellInstArray> effective_instance (local_processor_contexts<TS, TI, TR> &contexts, db::cell_index_type subject_cell_index, db::cell_index_type intruder_cell_index, const db::ICplxTrans &ti2s, db::Coord dist) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1296,10 +1296,16 @@ CODE
|
|||
end
|
||||
|
||||
else
|
||||
|
||||
if @dss
|
||||
@dss.threads = (@tt || 1)
|
||||
end
|
||||
|
||||
res = nil
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
res = obj.send(method, *args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# enable progress
|
||||
|
|
@ -1333,10 +1339,16 @@ CODE
|
|||
res = res.value
|
||||
|
||||
else
|
||||
|
||||
if @dss
|
||||
@dss.threads = (@tt || 1)
|
||||
end
|
||||
|
||||
res = nil
|
||||
run_timed("\"#{method}\" in: #{src_line}", obj) do
|
||||
res = obj.send(method)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# enable progress
|
||||
|
|
|
|||
Loading…
Reference in New Issue