pcbnew: Remove OpenMP
OpenMP is not available for macos, so moving to a std::threads implementation brings platforms into shared code. This also reduces the OpenMP overhead when computing connectivity and ratsnests. Fixes: lp:1780130 * https://bugs.launchpad.net/kicad/+bug/1780130
This commit is contained in:
parent
3e45483798
commit
c0f067bf90
|
@ -33,9 +33,6 @@
|
|||
#include <profile.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#include <omp.h>
|
||||
#endif /* USE_OPENMP */
|
||||
|
||||
using namespace std::placeholders;
|
||||
|
||||
|
@ -324,7 +321,6 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
|
|||
|
||||
#ifdef PROFILE
|
||||
garbage_collection.Show();
|
||||
PROF_COUNTER search_cnt( "search-connections" );
|
||||
PROF_COUNTER search_basic( "search-basic" );
|
||||
#endif
|
||||
|
||||
|
@ -333,49 +329,63 @@ void CN_CONNECTIVITY_ALGO::searchConnections()
|
|||
m_progressReporter->SetMaxProgress( m_itemList.IsDirty() ? m_itemList.Size() : 0 );
|
||||
}
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel num_threads( std::max( omp_get_num_procs(), 2 ) )
|
||||
if( m_itemList.IsDirty() )
|
||||
{
|
||||
if( omp_get_thread_num() == 0 && m_progressReporter )
|
||||
m_progressReporter->KeepRefreshing( true );
|
||||
#endif
|
||||
std::atomic<int> nextItem( 0 );
|
||||
std::atomic<size_t> threadsFinished( 0 );
|
||||
size_t numDirty = std::count_if( m_itemList.begin(), m_itemList.end(), [] ( CN_ITEM* aItem )
|
||||
{ return aItem->Dirty(); } );
|
||||
|
||||
if( m_itemList.IsDirty() )
|
||||
size_t parallelThreadCount = std::min<size_t>(
|
||||
std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
|
||||
numDirty );
|
||||
|
||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||
{
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for( int i = 0; i < m_itemList.Size(); i++ )
|
||||
std::thread t = std::thread( [&nextItem, &threadsFinished, this]()
|
||||
{
|
||||
auto item = m_itemList[i];
|
||||
if( item->Dirty() )
|
||||
for( int i = nextItem.fetch_add( 1 );
|
||||
i < m_itemList.Size();
|
||||
i = nextItem.fetch_add( 1 ) )
|
||||
{
|
||||
CN_VISITOR visitor( item, &m_listLock );
|
||||
m_itemList.FindNearby( item, visitor );
|
||||
auto item = m_itemList[i];
|
||||
if( item->Dirty() )
|
||||
{
|
||||
CN_VISITOR visitor( item, &m_listLock );
|
||||
m_itemList.FindNearby( item, visitor );
|
||||
}
|
||||
|
||||
if( m_progressReporter )
|
||||
m_progressReporter->AdvanceProgress();
|
||||
}
|
||||
|
||||
if( m_progressReporter )
|
||||
m_progressReporter->AdvanceProgress();
|
||||
}
|
||||
threadsFinished++;
|
||||
} );
|
||||
|
||||
t.detach();
|
||||
}
|
||||
|
||||
// Finalize the connectivity threads
|
||||
while( threadsFinished < parallelThreadCount )
|
||||
{
|
||||
if( m_progressReporter )
|
||||
m_progressReporter->KeepRefreshing();
|
||||
|
||||
// This routine is called every click while routing so keep the sleep time minimal
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PROFILE
|
||||
search_basic.Show();
|
||||
#endif
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
}
|
||||
#endif
|
||||
|
||||
m_itemList.ClearDirtyFlags();
|
||||
|
||||
#ifdef CONNECTIVITY_DEBUG
|
||||
printf("Search end\n");
|
||||
#endif
|
||||
|
||||
#ifdef PROFILE
|
||||
search_cnt.Show();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,18 +21,17 @@
|
|||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifdef PROFILE
|
||||
#include <profile.h>
|
||||
#endif
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <connectivity_data.h>
|
||||
#include <connectivity_algo.h>
|
||||
#include <ratsnest_data.h>
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#include <omp.h>
|
||||
#endif /* USE_OPENMP */
|
||||
|
||||
CONNECTIVITY_DATA::CONNECTIVITY_DATA()
|
||||
{
|
||||
m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
|
||||
|
@ -87,31 +86,40 @@ void CONNECTIVITY_DATA::Build( const std::vector<BOARD_ITEM*>& aItems )
|
|||
|
||||
void CONNECTIVITY_DATA::updateRatsnest()
|
||||
{
|
||||
int lastNet = m_connAlgo->NetCount();
|
||||
|
||||
#ifdef PROFILE
|
||||
PROF_COUNTER rnUpdate( "update-ratsnest" );
|
||||
#endif
|
||||
|
||||
int i;
|
||||
size_t numDirty = std::count_if( m_nets.begin() + 1, m_nets.end(), [] ( RN_NET* aNet )
|
||||
{ return aNet->IsDirty(); } );
|
||||
|
||||
#ifdef USE_OPENMP
|
||||
#pragma omp parallel shared(lastNet) private(i)
|
||||
{
|
||||
#pragma omp for schedule(guided, 1)
|
||||
#else /* USE_OPENMP */
|
||||
{
|
||||
#endif
|
||||
std::atomic<size_t> nextNet( 1 );
|
||||
std::atomic<size_t> threadsFinished( 0 );
|
||||
|
||||
// Start with net number 1, as 0 stands for not connected
|
||||
for( i = 1; i < lastNet; ++i )
|
||||
// We don't want to spin up a new thread for fewer than two nets (overhead costs)
|
||||
size_t parallelThreadCount = std::min<size_t>(
|
||||
std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
|
||||
numDirty / 2 );
|
||||
|
||||
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
|
||||
{
|
||||
std::thread t = std::thread( [&nextNet, &threadsFinished, this]()
|
||||
{
|
||||
if( m_nets[i]->IsDirty() )
|
||||
for( size_t i = nextNet.fetch_add( 1 ); i < m_nets.size(); i = nextNet.fetch_add( 1 ) )
|
||||
{
|
||||
m_nets[i]->Update();
|
||||
if( m_nets[i]->IsDirty() )
|
||||
m_nets[i]->Update();
|
||||
}
|
||||
}
|
||||
} /* end of parallel section */
|
||||
|
||||
threadsFinished++;
|
||||
} );
|
||||
|
||||
t.detach();
|
||||
}
|
||||
|
||||
// Finalize the ratsnest threads
|
||||
while( threadsFinished < parallelThreadCount )
|
||||
std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
|
||||
|
||||
#ifdef PROFILE
|
||||
rnUpdate.Show();
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <class_zone.h>
|
||||
#include <profile.h>
|
||||
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
|
|
Loading…
Reference in New Issue