Speedup dynamic ratsnest

Removes some unneeded calculations and threads the remaining.

Threading was previously removed to avoid overhead issues with small
boards.  This is no longer needed with the thread pool implementation

Fixes https://gitlab.com/kicad/code/kicad/issues/12131
This commit is contained in:
Seth Hillbrand 2022-10-04 17:00:08 -07:00
parent a0865082fb
commit 87171f53c7
3 changed files with 28 additions and 17 deletions

View File

@ -313,10 +313,12 @@ void CONNECTIVITY_DATA::ComputeLocalRatsnest( const std::vector<BOARD_ITEM*>& aI
return; return;
m_dynamicRatsnest.clear(); m_dynamicRatsnest.clear();
std::mutex dynamic_ratsnest_mutex;
// This gets connections between the stationary board and the // This gets connections between the stationary board and the
// moving selection // moving selection
for( unsigned int nc = 1; nc < aDynamicData->m_nets.size(); nc++ )
auto update_lambda = [&]( int nc )
{ {
RN_NET* dynamicNet = aDynamicData->m_nets[nc]; RN_NET* dynamicNet = aDynamicData->m_nets[nc];
RN_NET* staticNet = m_nets[nc]; RN_NET* staticNet = m_nets[nc];
@ -329,17 +331,25 @@ void CONNECTIVITY_DATA::ComputeLocalRatsnest( const std::vector<BOARD_ITEM*>& aI
{ {
VECTOR2I pos1, pos2; VECTOR2I pos1, pos2;
if( staticNet->NearestBicoloredPair( *dynamicNet, &pos1, &pos2 ) ) if( staticNet->NearestBicoloredPair( dynamicNet, pos1, pos2 ) )
{ {
RN_DYNAMIC_LINE l; RN_DYNAMIC_LINE l;
l.a = pos1; l.a = pos1;
l.b = pos2; l.b = pos2;
l.netCode = nc; l.netCode = nc;
std::lock_guard<std::mutex> lock( dynamic_ratsnest_mutex );
m_dynamicRatsnest.push_back( l ); m_dynamicRatsnest.push_back( l );
} }
} }
} };
GetKiCadThreadPool().parallelize_loop( 1, aDynamicData->m_nets.size(),
[&]( const int a, const int b)
{
for( int ii = a; ii < b; ++ii )
update_lambda( ii );
}).wait();
// This gets the ratsnest for internal connections in the moving set // This gets the ratsnest for internal connections in the moving set
const std::vector<CN_EDGE>& edges = GetRatsnestForItems( aItems ); const std::vector<CN_EDGE>& edges = GetRatsnestForItems( aItems );

View File

@ -494,7 +494,7 @@ void RN_NET::AddCluster( std::shared_ptr<CN_CLUSTER> aCluster )
} }
bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, VECTOR2I* aPos1, VECTOR2I* aPos2 ) const bool RN_NET::NearestBicoloredPair( RN_NET* aOtherNet, VECTOR2I& aPos1, VECTOR2I& aPos2 ) const
{ {
bool rv = false; bool rv = false;
@ -511,32 +511,36 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, VECTOR2I* aPos1, VEC
{ {
rv = true; rv = true;
distMax_sq = dist_sq; distMax_sq = dist_sq;
*aPos1 = aTestNode1->Pos(); aPos1 = aTestNode1->Pos();
*aPos2 = aTestNode2->Pos(); aPos2 = aTestNode2->Pos();
} }
}; };
std::multiset<std::shared_ptr<CN_ANCHOR>, CN_PTR_CMP> nodes_b;
std::copy_if( m_nodes.begin(), m_nodes.end(), std::inserter( nodes_b, nodes_b.end() ),
[]( const std::shared_ptr<CN_ANCHOR> &aVal )
{ return !aVal->GetNoLine(); } );
/// Sweep-line algorithm to cut the number of comparisons to find the closest point /// Sweep-line algorithm to cut the number of comparisons to find the closest point
/// ///
/// Step 1: The outer loop needs to be the subset (selected nodes) as it is a linear search /// Step 1: The outer loop needs to be the subset (selected nodes) as it is a linear search
for( const std::shared_ptr<CN_ANCHOR>& nodeA : aOtherNet.m_nodes ) for( const std::shared_ptr<CN_ANCHOR>& nodeA : aOtherNet->m_nodes )
{ {
if( nodeA->GetNoLine() ) if( nodeA->GetNoLine() )
continue; continue;
/// Step 2: O( log n ) search to identify a close element ordered by x /// Step 2: O( log n ) search to identify a close element ordered by x
/// The fwd_it iterator will move forward through the elements while /// The fwd_it iterator will move forward through the elements while
/// the rev_it iterator will move backward through the same set /// the rev_it iterator will move backward through the same set
auto fwd_it = m_nodes.lower_bound( nodeA ); auto fwd_it = nodes_b.lower_bound( nodeA );
auto rev_it = std::make_reverse_iterator( fwd_it ); auto rev_it = std::make_reverse_iterator( fwd_it );
for( ; fwd_it != m_nodes.end(); ++fwd_it ) for( ; fwd_it != nodes_b.end(); ++fwd_it )
{ {
const std::shared_ptr<CN_ANCHOR>& nodeB = *fwd_it; const std::shared_ptr<CN_ANCHOR>& nodeB = *fwd_it;
if( nodeB->GetNoLine() )
continue;
SEG::ecoord distX_sq = SEG::Square( nodeA->Pos().x - nodeB->Pos().x ); SEG::ecoord distX_sq = SEG::Square( nodeA->Pos().x - nodeB->Pos().x );
/// As soon as the x distance (primary sort) is larger than the smallest distance, /// As soon as the x distance (primary sort) is larger than the smallest distance,
@ -548,13 +552,10 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, VECTOR2I* aPos1, VEC
} }
/// Step 3: using the same starting point, check points backwards for closer points /// Step 3: using the same starting point, check points backwards for closer points
for( ; rev_it != m_nodes.rend(); ++rev_it ) for( ; rev_it != nodes_b.rend(); ++rev_it )
{ {
const std::shared_ptr<CN_ANCHOR>& nodeB = *rev_it; const std::shared_ptr<CN_ANCHOR>& nodeB = *rev_it;
if( nodeB->GetNoLine() )
continue;
SEG::ecoord distX_sq = SEG::Square( nodeA->Pos().x - nodeB->Pos().x ); SEG::ecoord distX_sq = SEG::Square( nodeA->Pos().x - nodeB->Pos().x );
if( distX_sq > distMax_sq ) if( distX_sq > distMax_sq )

View File

@ -90,7 +90,7 @@ public:
const std::vector<CN_EDGE>& GetEdges() const { return m_rnEdges; } const std::vector<CN_EDGE>& GetEdges() const { return m_rnEdges; }
std::vector<CN_EDGE>& GetEdges() { return m_rnEdges; } std::vector<CN_EDGE>& GetEdges() { return m_rnEdges; }
bool NearestBicoloredPair( const RN_NET& aOtherNet, VECTOR2I* aPos1, VECTOR2I* aPos2 ) const; bool NearestBicoloredPair( RN_NET* aOtherNet, VECTOR2I& aPos1, VECTOR2I& aPos2 ) const;
protected: protected:
///< Recompute ratsnest from scratch. ///< Recompute ratsnest from scratch.