Performance: multi-thread CN_ZONE_LAYER RTree generation.

This commit is contained in:
Jeff Young 2022-02-16 14:10:43 +00:00
parent 3b292a4941
commit ca095896cb
3 changed files with 105 additions and 38 deletions

View File

@ -423,43 +423,104 @@ CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode, const KICAD_T a
void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter ) void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
{ {
int delta = 100; // Number of additions between 2 calls to the progress bar // Generate CN_ZONE_LAYERs for each island on each layer of each zone
int zoneScaler = 50; // Zones are more expensive //
int ii = 0; std::vector<CN_ZONE_LAYER*> zitems;
int size = 0;
size += aBoard->Zones().size() * zoneScaler; for( ZONE* zone : aBoard->Zones() )
{
if( zone->IsOnCopperLayer() )
{
m_itemMap[zone] = ITEM_MAP_ENTRY();
markItemNetAsDirty( zone );
for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
{
if( IsCopperLayer( layer ) )
{
for( int j = 0; j < zone->GetFilledPolysList( layer )->OutlineCount(); j++ )
zitems.push_back( new CN_ZONE_LAYER( zone, layer, j ) );
}
}
}
}
// Setup progress metrics
//
int delta = 50; // Number of additions between 2 calls to the progress bar
double size = 0.0;
size += zitems.size(); // Once for building RTrees
size += zitems.size(); // Once for adding to connectivity
size += aBoard->Tracks().size(); size += aBoard->Tracks().size();
for( FOOTPRINT* footprint : aBoard->Footprints() ) for( FOOTPRINT* footprint : aBoard->Footprints() )
size += footprint->Pads().size(); size += footprint->Pads().size();
size *= 1.5; // Our caller gets the other third of the progress bar size *= 1.5; // Our caller gets the other third of the progress bar
delta = std::max( delta, size / 10 ); delta = std::max( delta, KiROUND( size / 10 ) );
for( ZONE* zone : aBoard->Zones() ) auto report =
[&]( int progress )
{
if( aReporter && ( progress % delta ) == 0 )
{
aReporter->SetCurrentProgress( progress / size );
aReporter->KeepRefreshing( false );
}
};
// Generate RTrees for CN_ZONE_LAYER items (in parallel)
//
std::atomic<size_t> next( 0 );
std::atomic<size_t> zitems_done( 0 );
std::atomic<size_t> threads_done( 0 );
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
{ {
Add( zone ); std::thread t = std::thread(
ii += zoneScaler; [ &zitems, &zitems_done, &threads_done, &next ]( )
{
for( size_t i = next.fetch_add( 1 ); i < zitems.size(); i = next.fetch_add( 1 ) )
{
zitems[i]->BuildRTree();
zitems_done.fetch_add( 1 );
}
threads_done.fetch_add( 1 );
} );
t.detach();
}
while( threads_done < parallelThreadCount )
{
if( aReporter ) if( aReporter )
{ {
aReporter->SetCurrentProgress( (double) ii / (double) size ); aReporter->SetCurrentProgress( zitems_done / size );
aReporter->KeepRefreshing( false ); aReporter->KeepRefreshing();
} }
std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
}
// Add CN_ZONE_LAYERS, tracks, and pads to connectivity
//
int ii = zitems.size();
for( CN_ZONE_LAYER* zitem : zitems )
{
m_itemList.Add( zitem );
m_itemMap[ zitem->Parent() ].Link( zitem );
report( ++ii );
} }
for( PCB_TRACK* tv : aBoard->Tracks() ) for( PCB_TRACK* tv : aBoard->Tracks() )
{ {
Add( tv ); Add( tv );
ii++; report( ++ii );
if( aReporter && ( ii % delta ) == 0 )
{
aReporter->SetCurrentProgress( (double) ii / (double) size );
aReporter->KeepRefreshing( false );
}
} }
for( FOOTPRINT* footprint : aBoard->Footprints() ) for( FOOTPRINT* footprint : aBoard->Footprints() )
@ -467,13 +528,7 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
for( PAD* pad : footprint->Pads() ) for( PAD* pad : footprint->Pads() )
{ {
Add( pad ); Add( pad );
ii++; report( ++ii );
if( aReporter && ( ii % delta ) == 0 )
{
aReporter->SetCurrentProgress( (double) ii / (double) size );
aReporter->KeepRefreshing( false );
}
} }
} }

View File

@ -205,23 +205,29 @@ CN_ITEM* CN_LIST::Add( PCB_ARC* aArc )
for( int j = 0; j < polys->OutlineCount(); j++ ) for( int j = 0; j < polys->OutlineCount(); j++ )
{ {
CN_ZONE_LAYER* zitem = new CN_ZONE_LAYER( zone, aLayer, false, j ); CN_ZONE_LAYER* zitem = new CN_ZONE_LAYER( zone, aLayer, j );
const SHAPE_LINE_CHAIN& outline = zone->GetFilledPolysList( aLayer )->COutline( j );
for( int k = 0; k < outline.PointCount(); k++ ) zitem->BuildRTree();
zitem->AddAnchor( outline.CPoint( k ) );
m_items.push_back( zitem ); for( VECTOR2I pt : zone->GetFilledPolysList( aLayer )->COutline( j ).CPoints() )
zitem->SetLayer( aLayer ); zitem->AddAnchor( pt );
addItemtoTree( zitem );
rv.push_back( zitem ); rv.push_back( Add( zitem ) );
SetDirty();
} }
return rv; return rv;
} }
CN_ITEM* CN_LIST::Add( CN_ZONE_LAYER* zitem )
{
m_items.push_back( zitem );
addItemtoTree( zitem );
SetDirty();
return zitem;
}
void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage ) void CN_LIST::RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage )
{ {
if( !m_hasInvalid ) if( !m_hasInvalid )

View File

@ -285,18 +285,22 @@ typedef std::shared_ptr<CN_ITEM> CN_ITEM_PTR;
class CN_ZONE_LAYER : public CN_ITEM class CN_ZONE_LAYER : public CN_ITEM
{ {
public: public:
CN_ZONE_LAYER( ZONE* aParent, PCB_LAYER_ID aLayer, bool aCanChangeNet, int aSubpolyIndex ) : CN_ZONE_LAYER( ZONE* aParent, PCB_LAYER_ID aLayer, int aSubpolyIndex ) :
CN_ITEM( aParent, aCanChangeNet ), CN_ITEM( aParent, false ),
m_subpolyIndex( aSubpolyIndex ), m_subpolyIndex( aSubpolyIndex ),
m_layer( aLayer ) m_layer( aLayer )
{ {
m_triangulatedPoly = aParent->GetFilledPolysList( aLayer ); m_triangulatedPoly = aParent->GetFilledPolysList( aLayer );
SetLayers( aLayer );
}
void BuildRTree()
{
for( unsigned int ii = 0; ii < m_triangulatedPoly->TriangulatedPolyCount(); ++ii ) for( unsigned int ii = 0; ii < m_triangulatedPoly->TriangulatedPolyCount(); ++ii )
{ {
const auto* triangleSet = m_triangulatedPoly->TriangulatedPolygon( ii ); const auto* triangleSet = m_triangulatedPoly->TriangulatedPolygon( ii );
if( triangleSet->GetSourceOutlineIndex() != aSubpolyIndex ) if( triangleSet->GetSourceOutlineIndex() != m_subpolyIndex )
continue; continue;
for( const SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI& tri : triangleSet->Triangles() ) for( const SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI& tri : triangleSet->Triangles() )
@ -449,6 +453,8 @@ public:
CN_ITEM* Add( PCB_VIA* via ); CN_ITEM* Add( PCB_VIA* via );
CN_ITEM* Add( CN_ZONE_LAYER* zitem );
const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer ); const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer );
private: private: