Performance: multi-thread CN_ZONE_LAYER RTree generation.
This commit is contained in:
parent
3b292a4941
commit
ca095896cb
|
@ -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 )
|
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() )
|
||||||
|
@ -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
|
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 );
|
if( aReporter && ( progress % delta ) == 0 )
|
||||||
ii += zoneScaler;
|
|
||||||
|
|
||||||
if( aReporter )
|
|
||||||
{
|
{
|
||||||
aReporter->SetCurrentProgress( (double) ii / (double) size );
|
aReporter->SetCurrentProgress( progress / size );
|
||||||
aReporter->KeepRefreshing( false );
|
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() )
|
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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue