From f721be7e32f19d95a5f98be6adfd7735f44d3aaa Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Mon, 17 Jun 2024 21:45:55 +0200 Subject: [PATCH] Trying to improve deep-mode XOR and NOT performance by introducing a local sweep that eliminates shapes also found in second input. --- src/buddies/src/bd/strmxor.cc | 3 + src/db/db/dbDeepRegion.cc | 120 +++++++++++++++++++++++++++++++--- src/db/db/dbDeepRegion.h | 3 +- src/db/db/dbHierProcessor.cc | 7 +- 4 files changed, 122 insertions(+), 11 deletions(-) diff --git a/src/buddies/src/bd/strmxor.cc b/src/buddies/src/bd/strmxor.cc index de1f265e4..33d8e6ca3 100644 --- a/src/buddies/src/bd/strmxor.cc +++ b/src/buddies/src/bd/strmxor.cc @@ -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 ()); diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc index d52df7f9c..27a6f97b2 100644 --- a/src/db/db/dbDeepRegion.cc +++ b/src/db/db/dbDeepRegion.cc @@ -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 proc (const_cast (&deep_layer ().layout ()), const_cast (&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 proc (const_cast (&deep_layer ().layout ()), const_cast (&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 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 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 proc (const_cast (&deep_layer ().layout ()), const_cast (&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 proc (const_cast (&deep_layer ().layout ()), const_cast (&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 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); diff --git a/src/db/db/dbDeepRegion.h b/src/db/db/dbDeepRegion.h index 1d5537554..6ddda9e14 100644 --- a/src/db/db/dbDeepRegion.h +++ b/src/db/db/dbDeepRegion.h @@ -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 and_and_not_with (const DeepRegion *other, PropertyConstraint property_constraint) const; DeepRegion *apply_filter (const PolygonFilterBase &filter) const; diff --git a/src/db/db/dbHierProcessor.cc b/src/db/db/dbHierProcessor.cc index b2b5ae467..c5d123d7c 100644 --- a/src/db/db/dbHierProcessor.cc +++ b/src/db/db/dbHierProcessor.cc @@ -1737,12 +1737,14 @@ void local_processor::compute_contexts (local_processor_contexts intruder_shapes; if (intruder_cell) { + for (std::vector::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 inst_bcs (*mp_subject_layout, contexts.subject_layer ()); @@ -1824,8 +1826,8 @@ void local_processor::compute_contexts (local_processor_contexts scanner; db::addressable_object_from_shape heap; interaction_registration_inst2shape rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions); @@ -1849,6 +1851,7 @@ void local_processor::compute_contexts (local_processor_contexts ()); + } // produce the tasks for computing the next-level interactions