Trying to improve deep-mode XOR and NOT performance by introducing a local sweep that eliminates shapes also found in second input.

This commit is contained in:
Matthias Koefferlein 2024-06-17 21:45:55 +02:00
parent 214e1736f0
commit f721be7e32
4 changed files with 122 additions and 11 deletions

View File

@ -758,6 +758,9 @@ bool run_deep_xor (const XORData &xor_data)
{
db::DeepShapeStore dss;
dss.set_threads (xor_data.threads);
// TODO: this conflicts with the "set_for_merged_input" optimization below.
// It seems not to be very effective then. Why?
dss.set_wants_all_cells (true); // saves time for less cell mapping operations
double dbu = std::min (xor_data.layout_a->dbu (), xor_data.layout_b->dbu ());

View File

@ -407,7 +407,7 @@ DeepRegion::begin_iter () const
} else {
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
db::RecursiveShapeIterator iter (deep_layer ().layout (), top_cell, deep_layer ().layer ());
db::RecursiveShapeIterator iter (layout, top_cell, deep_layer ().layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
@ -803,7 +803,7 @@ DeepRegion::and_with (const Region &other, PropertyConstraint property_constrain
} else {
return new DeepRegion (and_or_not_with (other_deep, true, property_constraint));
return new DeepRegion (and_with_impl (other_deep, property_constraint));
}
}
@ -827,7 +827,7 @@ DeepRegion::not_with (const Region &other, PropertyConstraint property_constrain
} else {
return new DeepRegion (and_or_not_with (other_deep, false, property_constraint));
return new DeepRegion (not_with_impl (other_deep, property_constraint));
}
}
@ -875,13 +875,13 @@ DeepRegion::andnot_with (const Region &other, PropertyConstraint property_constr
}
DeepLayer
DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op, db::PropertyConstraint property_constraint) const
DeepRegion::and_with_impl (const DeepRegion *other, db::PropertyConstraint property_constraint) const
{
DeepLayer dl_out (deep_layer ().derived ());
if (pc_skip (property_constraint)) {
db::BoolAndOrNotLocalOperation op (and_op);
db::BoolAndOrNotLocalOperation op (true);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
configure_proc (proc);
@ -893,7 +893,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op, db::PropertyC
} else {
db::BoolAndOrNotLocalOperationWithProperties op (and_op, &dl_out.layout ().properties_repository (), &deep_layer ().layout ().properties_repository (), &other->deep_layer ().layout ().properties_repository (), property_constraint);
db::BoolAndOrNotLocalOperationWithProperties op (true, &dl_out.layout ().properties_repository (), &deep_layer ().layout ().properties_repository (), &other->deep_layer ().layout ().properties_repository (), property_constraint);
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
configure_proc (proc);
@ -908,6 +908,110 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op, db::PropertyC
return dl_out;
}
DeepLayer
DeepRegion::not_with_impl (const DeepRegion *other, db::PropertyConstraint property_constraint) const
{
DeepLayer dl_prep;
// first run a local-only task, which is trivial if the layouts are the same
// TODO: consider property constraints too.
if (deep_layer ().layout_index () == other->deep_layer ().layout_index () && pc_skip (property_constraint)) {
dl_prep = deep_layer ().derived ();
unsigned int layer_this = deep_layer ().layer ();
unsigned int layer_other = other->deep_layer ().layer ();
unsigned int layer_out = dl_prep.layer ();
db::Layout &layout = dl_prep.layout ();
bool any = false;
if (layer_this != layer_other) {
std::set<db::cell_index_type> called;
deep_layer ().initial_cell ().collect_called_cells (called);
called.insert (deep_layer ().initial_cell ().cell_index ());
for (auto ci = called.begin (); ci != called.end (); ++ci) {
db::Cell &cell = layout.cell (*ci);
db::Shapes &shapes_out = cell.shapes (layer_out);
const db::Shapes &shapes_this = cell.shapes (layer_this);
const db::Shapes &shapes_other = cell.shapes (layer_other);
db::Box overlap = (shapes_this.bbox () & shapes_other.bbox ());
if (! overlap.empty ()) {
std::set<db::PolygonRef> others;
for (auto si = shapes_other.begin (db::ShapeIterator::Polygons); ! si.at_end (); ++si) {
if (si->type () == db::Shape::PolygonRef) {
others.insert (si->polygon_ref ());
}
}
for (auto si = shapes_this.begin (db::ShapeIterator::Polygons); ! si.at_end (); ++si) {
if (si->type () == db::Shape::PolygonRef && others.find (si->polygon_ref ()) != others.end ()) {
// drop duplicate
} else {
any = true;
shapes_out.insert (*si);
}
}
} else if (! shapes_this.empty ()) {
any = true;
shapes_out = shapes_this;
}
}
}
// stop if empty
if (! any) {
return dl_prep;
}
} else {
dl_prep = deep_layer ();
}
DeepLayer dl_out (deep_layer ().derived ());
if (pc_skip (property_constraint)) {
db::BoolAndOrNotLocalOperation op (false);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
configure_proc (proc);
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
proc.run (&op, dl_prep.layer (), other->deep_layer ().layer (), dl_out.layer ());
} else {
db::BoolAndOrNotLocalOperationWithProperties op (false, &dl_out.layout ().properties_repository (), &deep_layer ().layout ().properties_repository (), &other->deep_layer ().layout ().properties_repository (), property_constraint);
db::local_processor<db::PolygonRefWithProperties, db::PolygonRefWithProperties, db::PolygonRefWithProperties> proc (const_cast<db::Layout *> (&deep_layer ().layout ()), const_cast<db::Cell *> (&deep_layer ().initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell (), deep_layer ().breakout_cells (), other->deep_layer ().breakout_cells ());
configure_proc (proc);
proc.set_threads (deep_layer ().store ()->threads ());
proc.set_area_ratio (deep_layer ().store ()->max_area_ratio ());
proc.set_max_vertex_count (deep_layer ().store ()->max_vertex_count ());
proc.run (&op, dl_prep.layer (), other->deep_layer ().layer (), dl_out.layer ());
}
return dl_out;
}
std::pair<DeepLayer, DeepLayer>
DeepRegion::and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const
{
@ -1008,8 +1112,8 @@ DeepRegion::xor_with (const Region &other, db::PropertyConstraint property_const
other_deep_mapped->disable_progress ();
}
DeepLayer n1 (and_or_not_with (other_deep_mapped.get (), false, property_constraint));
DeepLayer n2 (other_deep_mapped->and_or_not_with (this, false, property_constraint));
DeepLayer n1 (not_with_impl (other_deep_mapped.get (), property_constraint));
DeepLayer n2 (other_deep_mapped->not_with_impl (this, property_constraint));
n1.add_from (n2);
return new DeepRegion (n1);

View File

@ -178,7 +178,8 @@ private:
void init ();
void ensure_merged_polygons_valid () const;
DeepLayer and_or_not_with(const DeepRegion *other, bool and_op, PropertyConstraint property_constraint) const;
DeepLayer not_with_impl (const DeepRegion *other, PropertyConstraint property_constraint) const;
DeepLayer and_with_impl (const DeepRegion *other, PropertyConstraint property_constraint) const;
std::pair<DeepLayer, DeepLayer> and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const;
DeepRegion *apply_filter (const PolygonFilterBase &filter) const;

View File

@ -1737,12 +1737,14 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
CRONOLOGY_COLLECTION_BRACKET(event_compute_contexts_unlocked)
std::map<unsigned int, const db::Shapes *> intruder_shapes;
if (intruder_cell) {
for (std::vector<unsigned int>::const_iterator l = contexts.intruder_layers ().begin (); l != contexts.intruder_layers ().end (); ++l) {
const db::Shapes *s = &intruder_cell->shapes (contexts.actual_intruder_layer (*l));
if (! s->empty ()) {
intruder_shapes.insert (std::make_pair (*l, s));
}
}
}
db::box_convert <db::CellInstArray, true> inst_bcs (*mp_subject_layout, contexts.subject_layer ());
@ -1824,8 +1826,8 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
}
// TODO: can we shortcut this if interactions is empty?
{
if (! intruders.second.empty () || ! intruder_shapes.empty ()) {
db::box_scanner2<db::CellInstArray, int, TI, int> scanner;
db::addressable_object_from_shape<TI> heap;
interaction_registration_inst2shape<TS, TI, TR> rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions);
@ -1849,6 +1851,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
}
scanner.process (rec, dist, inst_bcs, db::box_convert<TI> ());
}
// produce the tasks for computing the next-level interactions