ratsnest: Move ratsnest connectivity to async
This a partial pick of 59fb6d8851
but
revised for the 5.0.x branch.
This commit is contained in:
parent
839ade2c05
commit
0b5ca1a883
|
@ -27,6 +27,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
#include <connectivity_data.h>
|
#include <connectivity_data.h>
|
||||||
#include <connectivity_algo.h>
|
#include <connectivity_algo.h>
|
||||||
|
@ -90,37 +92,44 @@ void CONNECTIVITY_DATA::updateRatsnest()
|
||||||
PROF_COUNTER rnUpdate( "update-ratsnest" );
|
PROF_COUNTER rnUpdate( "update-ratsnest" );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t numDirty = std::count_if( m_nets.begin() + 1, m_nets.end(), [] ( RN_NET* aNet )
|
std::vector<RN_NET*> dirty_nets;
|
||||||
{ return aNet->IsDirty(); } );
|
|
||||||
|
|
||||||
// Start with net 1 as net 0 is reserved for not-connected
|
// Start with net 1 as net 0 is reserved for not-connected
|
||||||
std::atomic<size_t> nextNet( 1 );
|
// Nets without nodes are also ignored
|
||||||
std::atomic<size_t> threadsFinished( 0 );
|
std::copy_if( m_nets.begin() + 1, m_nets.end(), std::back_inserter( dirty_nets ),
|
||||||
|
[] ( RN_NET* aNet ) { return aNet->IsDirty() && aNet->GetNodeCount() > 0; } );
|
||||||
|
|
||||||
// We don't want to spin up a new thread for fewer than two nets (overhead costs)
|
// We don't want to spin up a new thread for fewer than 8 nets (overhead costs)
|
||||||
size_t parallelThreadCount = std::min<size_t>(
|
size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
|
||||||
std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
|
( dirty_nets.size() + 7 ) / 8 );
|
||||||
( numDirty + 1 ) / 2 );
|
|
||||||
|
|
||||||
|
std::atomic<size_t> nextNet( 0 );
|
||||||
|
std::vector<std::future<size_t>> returns( parallelThreadCount );
|
||||||
|
|
||||||
|
auto update_lambda = [&nextNet, &dirty_nets]() -> size_t
|
||||||
|
{
|
||||||
|
size_t processed = 0;
|
||||||
|
|
||||||
|
for( size_t i = nextNet++; i < dirty_nets.size(); i = nextNet++ )
|
||||||
|
{
|
||||||
|
dirty_nets[i]->Update();
|
||||||
|
processed++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return processed;
|
||||||
|
};
|
||||||
|
|
||||||
|
if( parallelThreadCount == 1 )
|
||||||
|
update_lambda();
|
||||||
|
else
|
||||||
|
{
|
||||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||||
{
|
returns[ii] = std::async( std::launch::async, update_lambda );
|
||||||
std::thread t = std::thread( [&nextNet, &threadsFinished, this]()
|
|
||||||
{
|
|
||||||
for( size_t i = nextNet.fetch_add( 1 ); i < m_nets.size(); i = nextNet.fetch_add( 1 ) )
|
|
||||||
{
|
|
||||||
if( m_nets[i]->IsDirty() )
|
|
||||||
m_nets[i]->Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
threadsFinished++;
|
|
||||||
} );
|
|
||||||
|
|
||||||
t.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finalize the ratsnest threads
|
// Finalize the ratsnest threads
|
||||||
while( threadsFinished < parallelThreadCount )
|
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||||
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
|
returns[ii].wait();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef PROFILE
|
#ifdef PROFILE
|
||||||
rnUpdate.Show();
|
rnUpdate.Show();
|
||||||
|
|
Loading…
Reference in New Issue