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,12 +423,35 @@ CN_CONNECTIVITY_ALGO::SearchClusters( CLUSTER_SEARCH_MODE aMode, const KICAD_T a
void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
{
int delta = 100; // Number of additions between 2 calls to the progress bar
int zoneScaler = 50; // Zones are more expensive
int ii = 0;
int size = 0;
// Generate CN_ZONE_LAYERs for each island on each layer of each zone
//
std::vector<CN_ZONE_LAYER*> zitems;
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();
for( FOOTPRINT* footprint : aBoard->Footprints() )
@ -436,30 +459,68 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
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 )
{
Add( zone );
ii += zoneScaler;
if( aReporter )
if( aReporter && ( progress % delta ) == 0 )
{
aReporter->SetCurrentProgress( (double) ii / (double) size );
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 )
{
std::thread t = std::thread(
[ &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 )
{
aReporter->SetCurrentProgress( zitems_done / size );
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() )
{
Add( tv );
ii++;
if( aReporter && ( ii % delta ) == 0 )
{
aReporter->SetCurrentProgress( (double) ii / (double) size );
aReporter->KeepRefreshing( false );
}
report( ++ii );
}
for( FOOTPRINT* footprint : aBoard->Footprints() )
@ -467,13 +528,7 @@ void CN_CONNECTIVITY_ALGO::Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter )
for( PAD* pad : footprint->Pads() )
{
Add( pad );
ii++;
if( aReporter && ( ii % delta ) == 0 )
{
aReporter->SetCurrentProgress( (double) ii / (double) size );
aReporter->KeepRefreshing( false );
}
report( ++ii );
}
}

View File

@ -205,23 +205,29 @@ CN_ITEM* CN_LIST::Add( PCB_ARC* aArc )
for( int j = 0; j < polys->OutlineCount(); j++ )
{
CN_ZONE_LAYER* zitem = new CN_ZONE_LAYER( zone, aLayer, false, j );
const SHAPE_LINE_CHAIN& outline = zone->GetFilledPolysList( aLayer )->COutline( j );
CN_ZONE_LAYER* zitem = new CN_ZONE_LAYER( zone, aLayer, j );
for( int k = 0; k < outline.PointCount(); k++ )
zitem->AddAnchor( outline.CPoint( k ) );
zitem->BuildRTree();
m_items.push_back( zitem );
zitem->SetLayer( aLayer );
addItemtoTree( zitem );
rv.push_back( zitem );
SetDirty();
for( VECTOR2I pt : zone->GetFilledPolysList( aLayer )->COutline( j ).CPoints() )
zitem->AddAnchor( pt );
rv.push_back( Add( zitem ) );
}
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 )
{
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
{
public:
CN_ZONE_LAYER( ZONE* aParent, PCB_LAYER_ID aLayer, bool aCanChangeNet, int aSubpolyIndex ) :
CN_ITEM( aParent, aCanChangeNet ),
CN_ZONE_LAYER( ZONE* aParent, PCB_LAYER_ID aLayer, int aSubpolyIndex ) :
CN_ITEM( aParent, false ),
m_subpolyIndex( aSubpolyIndex ),
m_layer( aLayer )
{
m_triangulatedPoly = aParent->GetFilledPolysList( aLayer );
SetLayers( aLayer );
}
void BuildRTree()
{
for( unsigned int ii = 0; ii < m_triangulatedPoly->TriangulatedPolyCount(); ++ii )
{
const auto* triangleSet = m_triangulatedPoly->TriangulatedPolygon( ii );
if( triangleSet->GetSourceOutlineIndex() != aSubpolyIndex )
if( triangleSet->GetSourceOutlineIndex() != m_subpolyIndex )
continue;
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( CN_ZONE_LAYER* zitem );
const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer );
private: