mirror of https://github.com/KLayout/klayout.git
Fixing a performance regression in the merged layer computation
Problem was that while properly implementing the reverse cluster connection during cluster merges, cluster connection propagation suffered a complexity explosion during generation of the cluster interactions. Solution is to postpone the cluster joining step until a cell is finished connecting the clusters. To mitigate the performance effect of that, some optimizations are introduced (e.g. using a more efficient unordered_map).
This commit is contained in:
parent
6dd3e6b10f
commit
fb2559bf75
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
*/
|
||||
|
||||
|
||||
#include "dbHierNetworkProcessor.h"
|
||||
#include "dbShape.h"
|
||||
#include "dbShapes.h"
|
||||
|
|
@ -1794,7 +1793,7 @@ public:
|
|||
cell_clusters_box_converter (const db::Layout &layout, const hier_clusters<T> &tree)
|
||||
: mp_layout (&layout), mp_tree (&tree)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
m_cache.resize (layout.cells (), 0);
|
||||
}
|
||||
|
||||
const box_type &operator() (const db::CellInst &cell_inst) const
|
||||
|
|
@ -1804,10 +1803,10 @@ public:
|
|||
|
||||
const box_type &operator() (db::cell_index_type cell_index) const
|
||||
{
|
||||
typename std::map<db::cell_index_type, box_type>::const_iterator b = m_cache.find (cell_index);
|
||||
if (b != m_cache.end ()) {
|
||||
const box_type *b = m_cache [cell_index];
|
||||
if (b) {
|
||||
|
||||
return b->second;
|
||||
return *b;
|
||||
|
||||
} else {
|
||||
|
||||
|
|
@ -1820,13 +1819,17 @@ public:
|
|||
box += inst_array.bbox (*this);
|
||||
}
|
||||
|
||||
return m_cache.insert (std::make_pair (cell_index, box)).first->second;
|
||||
m_cached_boxes.push_front (box);
|
||||
b = m_cached_boxes.begin ().operator-> ();
|
||||
m_cache [cell_index] = b;
|
||||
return *b;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::map<db::cell_index_type, box_type> m_cache;
|
||||
mutable std::vector<const box_type *> m_cache;
|
||||
mutable tl::slist<box_type> m_cached_boxes;
|
||||
const db::Layout *mp_layout;
|
||||
const hier_clusters<T> *mp_tree;
|
||||
};
|
||||
|
|
@ -1993,10 +1996,10 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Finally join the clusters in the join set
|
||||
* @brief Finally generate cluster-to-instance interactions and join the clusters in the join set
|
||||
*
|
||||
* This step is postponed because doing this while the iteration happens would
|
||||
* invalidate the box trees.
|
||||
* invalidate the box trees and disturb the propagation mechanism.
|
||||
*/
|
||||
void finish_cluster_to_instance_interactions ()
|
||||
{
|
||||
|
|
@ -2081,7 +2084,7 @@ private:
|
|||
const db::Connectivity *mp_conn;
|
||||
const std::set<db::cell_index_type> *mp_breakout_cells;
|
||||
typedef std::list<std::set<id_type> > join_set_list;
|
||||
std::map<id_type, typename join_set_list::iterator> m_cm2join_map;
|
||||
std::unordered_map<id_type, typename join_set_list::iterator> m_cm2join_map;
|
||||
join_set_list m_cm2join_sets;
|
||||
std::map<std::pair<size_t, size_t>, int> m_soft_connections;
|
||||
std::list<ClusterInstanceInteraction> m_ci_interactions;
|
||||
|
|
@ -2551,8 +2554,8 @@ private:
|
|||
return;
|
||||
}
|
||||
|
||||
typename std::map<id_type, typename join_set_list::iterator>::const_iterator x = m_cm2join_map.find (a);
|
||||
typename std::map<id_type, typename join_set_list::iterator>::const_iterator y = m_cm2join_map.find (b);
|
||||
typename std::unordered_map<id_type, typename join_set_list::iterator>::const_iterator x = m_cm2join_map.find (a);
|
||||
typename std::unordered_map<id_type, typename join_set_list::iterator>::const_iterator y = m_cm2join_map.find (b);
|
||||
|
||||
if (x == m_cm2join_map.end ()) {
|
||||
|
||||
|
|
@ -2579,6 +2582,11 @@ private:
|
|||
|
||||
} else if (x->second != y->second) {
|
||||
|
||||
// the y set should be the smaller one for better efficiency
|
||||
if (x->second->size () < y->second->size ()) {
|
||||
std::swap (x, y);
|
||||
}
|
||||
|
||||
// join two superclusters
|
||||
typename join_set_list::iterator yset = y->second;
|
||||
x->second->insert (yset->begin (), yset->end ());
|
||||
|
|
@ -2591,12 +2599,12 @@ private:
|
|||
|
||||
#if defined(DEBUG_HIER_NETWORK_PROCESSOR)
|
||||
// concistency check for debugging
|
||||
for (typename std::map<id_type, typename join_set_list::iterator>::const_iterator j = m_cm2join_map.begin (); j != m_cm2join_map.end (); ++j) {
|
||||
for (auto j = m_cm2join_map.begin (); j != m_cm2join_map.end (); ++j) {
|
||||
tl_assert (j->second->find (j->first) != j->second->end ());
|
||||
}
|
||||
|
||||
for (typename std::list<std::set<id_type> >::const_iterator i = m_cm2join_sets.begin (); i != m_cm2join_sets.end (); ++i) {
|
||||
for (typename std::set<id_type>::const_iterator j = i->begin(); j != i->end(); ++j) {
|
||||
for (auto i = m_cm2join_sets.begin (); i != m_cm2join_sets.end (); ++i) {
|
||||
for (auto j = i->begin(); j != i->end(); ++j) {
|
||||
tl_assert(m_cm2join_map.find (*j) != m_cm2join_map.end ());
|
||||
tl_assert(m_cm2join_map[*j] == i);
|
||||
}
|
||||
|
|
@ -2604,8 +2612,8 @@ private:
|
|||
|
||||
// the sets must be disjunct
|
||||
std::set<id_type> all;
|
||||
for (typename std::list<std::set<id_type> >::const_iterator i = m_cm2join_sets.begin (); i != m_cm2join_sets.end (); ++i) {
|
||||
for (typename std::set<id_type>::const_iterator j = i->begin(); j != i->end(); ++j) {
|
||||
for (auto i = m_cm2join_sets.begin (); i != m_cm2join_sets.end (); ++i) {
|
||||
for (auto j = i->begin(); j != i->end(); ++j) {
|
||||
tl_assert(all.find (*j) == all.end());
|
||||
all.insert(*j);
|
||||
}
|
||||
|
|
@ -2700,23 +2708,13 @@ private:
|
|||
} else if (x1 != x2) {
|
||||
|
||||
int soft = ic->soft;
|
||||
|
||||
// for instance-to-instance interactions the number of connections is more important for the
|
||||
// cost of the join operation: make the one with more connections the target
|
||||
// TODO: this will be SLOW for STL's not providing a fast size()
|
||||
if (mp_cell_clusters->connections_for_cluster (x1).size () < mp_cell_clusters->connections_for_cluster (x2).size ()) {
|
||||
std::swap (x1, x2);
|
||||
soft = -soft;
|
||||
}
|
||||
|
||||
if (soft != 0) {
|
||||
|
||||
register_soft_connection (x1, x2, soft);
|
||||
|
||||
} else {
|
||||
|
||||
mp_cell_clusters->join_cluster_with (x1, x2);
|
||||
mp_cell_clusters->remove_cluster (x2);
|
||||
mark_to_join (x1, x2);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue