Removing OpenMP

This commit finishes the removal of OpenMP from the KiCad codebase.
Removed in this commit are the OpenMP calls in 3d-viewer and
qa/polygon_triangulation as well as all references in CMakeLists.txt

std::thread is used instead for multithreaded computation
This commit is contained in:
Seth Hillbrand 2018-09-20 21:23:15 -07:00
parent 21485e6f24
commit f8784f30a8
16 changed files with 905 additions and 881 deletions

View File

@ -40,7 +40,7 @@
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h" #include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
#include "../3d_rendering/3d_render_raytracing/shapes3D/ccylinder.h" #include "../3d_rendering/3d_render_raytracing/shapes3D/ccylinder.h"
#include "../3d_rendering/3d_render_raytracing/shapes3D/clayeritem.h" #include "../3d_rendering/3d_render_raytracing/shapes3D/clayeritem.h"
#include <openmp_mutex.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
#include <class_pad.h> #include <class_pad.h>
@ -845,11 +845,7 @@ void CINFO3D_VISU::AddSolidAreasShapesToContainer( const ZONE_CONTAINER* aZoneCo
PCB_LAYER_ID aLayerId ) PCB_LAYER_ID aLayerId )
{ {
// Copy the polys list because we have to simplify it // Copy the polys list because we have to simplify it
SHAPE_POLY_SET polyList = SHAPE_POLY_SET(aZoneContainer->GetFilledPolysList()); SHAPE_POLY_SET polyList = SHAPE_POLY_SET( aZoneContainer->GetFilledPolysList(), true );
polyList.Simplify( SHAPE_POLY_SET::PM_FAST );
if( polyList.IsEmpty() )
return;
// This convert the poly in outline and holes // This convert the poly in outline and holes
Convert_shape_line_polygon_to_triangles( polyList, Convert_shape_line_polygon_to_triangles( polyList,

View File

@ -40,7 +40,7 @@
#include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h" #include "../3d_rendering/3d_render_raytracing/accelerators/ccontainer2d.h"
#include "../3d_rendering/3d_render_raytracing/shapes3D/ccylinder.h" #include "../3d_rendering/3d_render_raytracing/shapes3D/ccylinder.h"
#include "../3d_rendering/3d_render_raytracing/shapes3D/clayeritem.h" #include "../3d_rendering/3d_render_raytracing/shapes3D/clayeritem.h"
#include <openmp_mutex.h>
#include <class_board.h> #include <class_board.h>
#include <class_module.h> #include <class_module.h>
#include <class_pad.h> #include <class_pad.h>
@ -52,6 +52,9 @@
#include <trigo.h> #include <trigo.h>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <thread>
#include <algorithm>
#include <atomic>
#include <profile.h> #include <profile.h>
@ -788,36 +791,43 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter )
// Add zones objects // Add zones objects
// ///////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////
for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx ) std::atomic<size_t> nextZone( 0 );
std::atomic<size_t> threadsFinished( 0 );
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
{ {
const PCB_LAYER_ID curr_layer_id = layer_id[lIdx]; std::thread t = std::thread( [&]()
if( aStatusTextReporter )
aStatusTextReporter->Report( wxString::Format( _( "Create zones of layer %s" ),
LSET::Name( curr_layer_id ) ) );
wxASSERT( m_layers_container2D.find( curr_layer_id ) != m_layers_container2D.end() );
CBVHCONTAINER2D *layerContainer = m_layers_container2D[curr_layer_id];
// ADD COPPER ZONES
for( int ii = 0; ii < m_board->GetAreaCount(); ++ii )
{ {
const ZONE_CONTAINER* zone = m_board->GetArea( ii ); for( size_t areaId = nextZone.fetch_add( 1 );
const PCB_LAYER_ID zonelayer = zone->GetLayer(); areaId < static_cast<size_t>( m_board->GetAreaCount() );
areaId = nextZone.fetch_add( 1 ) )
if( zonelayer == curr_layer_id )
{ {
AddSolidAreasShapesToContainer( zone, const ZONE_CONTAINER* zone = m_board->GetArea( areaId );
layerContainer,
curr_layer_id ); if( zone == nullptr )
break;
auto layerContainer = m_layers_container2D.find( zone->GetLayer() );
if( layerContainer != m_layers_container2D.end() )
AddSolidAreasShapesToContainer( zone, layerContainer->second,
zone->GetLayer() );
} }
}
threadsFinished++;
} );
t.detach();
} }
while( threadsFinished < parallelThreadCount )
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
} }
#ifdef PRINT_STATISTICS_3D_VIEWER #ifdef PRINT_STATISTICS_3D_VIEWER
printf( "T13: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 ); printf( "fill zones T13: %.3f ms\n", (float)( GetRunningMicroSecs() - start_Time ) / 1e3 );
start_Time = GetRunningMicroSecs(); start_Time = GetRunningMicroSecs();
#endif #endif
@ -825,29 +835,18 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter )
GetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS ) && GetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS ) &&
(m_render_engine == RENDER_ENGINE_OPENGL_LEGACY) ) (m_render_engine == RENDER_ENGINE_OPENGL_LEGACY) )
{ {
// Add zones poly contourns // ADD COPPER ZONES
// ///////////////////////////////////////////////////////////////////// for( int ii = 0; ii < m_board->GetAreaCount(); ++ii )
for( unsigned int lIdx = 0; lIdx < layer_id.size(); ++lIdx )
{ {
const PCB_LAYER_ID curr_layer_id = layer_id[lIdx]; const ZONE_CONTAINER* zone = m_board->GetArea( ii );
wxASSERT( m_layers_poly.find( curr_layer_id ) != m_layers_poly.end() ); if( zone == nullptr )
break;
SHAPE_POLY_SET *layerPoly = m_layers_poly[curr_layer_id]; auto layerContainer = m_layers_poly.find( zone->GetLayer() );
// ADD COPPER ZONES if( layerContainer != m_layers_poly.end() )
for( int ii = 0; ii < m_board->GetAreaCount(); ++ii ) zone->TransformSolidAreasShapesToPolygonSet( *layerContainer->second, segcountforcircle, correctionFactor );
{
const ZONE_CONTAINER* zone = m_board->GetArea( ii );
const LAYER_NUM zonelayer = zone->GetLayer();
if( zonelayer == curr_layer_id )
{
zone->TransformSolidAreasShapesToPolygonSet( *layerPoly,
segcountforcircle,
correctionFactor );
}
}
} }
} }
@ -865,22 +864,35 @@ void CINFO3D_VISU::createLayers( REPORTER *aStatusTextReporter )
if( GetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS ) && if( GetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS ) &&
(m_render_engine == RENDER_ENGINE_OPENGL_LEGACY) ) (m_render_engine == RENDER_ENGINE_OPENGL_LEGACY) )
{ {
const int nLayers = layer_id.size(); std::atomic<size_t> nextItem( 0 );
std::atomic<size_t> threadsFinished( 0 );
#pragma omp parallel for size_t parallelThreadCount = std::min<size_t>(
for( signed int lIdx = 0; lIdx < nLayers; ++lIdx ) std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
layer_id.size() );
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
{ {
const PCB_LAYER_ID curr_layer_id = layer_id[lIdx]; std::thread t = std::thread( [&nextItem, &threadsFinished, &layer_id, this]()
{
for( size_t i = nextItem.fetch_add( 1 );
i < layer_id.size();
i = nextItem.fetch_add( 1 ) )
{
auto layerPoly = m_layers_poly.find( layer_id[i] );
wxASSERT( m_layers_poly.find( curr_layer_id ) != m_layers_poly.end() ); if( layerPoly != m_layers_poly.end() )
// This will make a union of all added contours
layerPoly->second->Simplify( SHAPE_POLY_SET::PM_FAST );
}
SHAPE_POLY_SET *layerPoly = m_layers_poly[curr_layer_id]; threadsFinished++;
} );
wxASSERT( layerPoly != NULL ); t.detach();
// This will make a union of all added contourns
layerPoly->Simplify( SHAPE_POLY_SET::PM_FAST );
} }
while( threadsFinished < parallelThreadCount )
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
} }
#ifdef PRINT_STATISTICS_3D_VIEWER #ifdef PRINT_STATISTICS_3D_VIEWER

View File

@ -30,6 +30,9 @@
#include "clayer_triangles.h" #include "clayer_triangles.h"
#include <wx/debug.h> // For the wxASSERT #include <wx/debug.h> // For the wxASSERT
#include <mutex>
#include <thread>
#include <atomic>
CLAYER_TRIANGLE_CONTAINER::CLAYER_TRIANGLE_CONTAINER( unsigned int aNrReservedTriangles, CLAYER_TRIANGLE_CONTAINER::CLAYER_TRIANGLE_CONTAINER( unsigned int aNrReservedTriangles,
@ -219,8 +222,8 @@ void CLAYER_TRIANGLES::AddToMiddleContourns( const std::vector< SFVEC2F > &aCont
const SFVEC2F &v0 = aContournPoints[i + 0]; const SFVEC2F &v0 = aContournPoints[i + 0];
const SFVEC2F &v1 = aContournPoints[i + 1]; const SFVEC2F &v1 = aContournPoints[i + 1];
#pragma omp critical
{ {
std::lock_guard<std::mutex> lock( m_middle_layer_lock );
m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ), m_layer_middle_contourns_quads->AddQuad( SFVEC3F( v0.x, v0.y, zTop ),
SFVEC3F( v1.x, v1.y, zTop ), SFVEC3F( v1.x, v1.y, zTop ),
SFVEC3F( v1.x, v1.y, zBot ), SFVEC3F( v1.x, v1.y, zBot ),
@ -305,21 +308,41 @@ void CLAYER_TRIANGLES::AddToMiddleContourns( const SHAPE_POLY_SET &aPolySet,
m_layer_middle_contourns_quads->Reserve_More( nrContournPointsToReserve * 2, m_layer_middle_contourns_quads->Reserve_More( nrContournPointsToReserve * 2,
true ); true );
#pragma omp parallel for std::atomic<int> nextItem( 0 );
for( signed int i = 0; i < aPolySet.OutlineCount(); ++i ) std::atomic<size_t> threadsFinished( 0 );
size_t parallelThreadCount = std::min<size_t>(
std::max<size_t>( std::thread::hardware_concurrency(), 2 ),
static_cast<size_t>( aPolySet.OutlineCount() ) );
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
{ {
// Add outline std::thread t = std::thread( [&]()
const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
AddToMiddleContourns( pathOutline, zBot, zTop, aBiuTo3Du, aInvertFaceDirection );
// Add holes for this outline
for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
{ {
const SHAPE_LINE_CHAIN &hole = aPolySet.CHole( i, h ); for( int i = nextItem.fetch_add( 1 );
AddToMiddleContourns( hole, zBot, zTop, aBiuTo3Du, aInvertFaceDirection ); i < aPolySet.OutlineCount();
} i = nextItem.fetch_add( 1 ) )
{
// Add outline
const SHAPE_LINE_CHAIN& pathOutline = aPolySet.COutline( i );
AddToMiddleContourns( pathOutline, zBot, zTop, aBiuTo3Du, aInvertFaceDirection );
// Add holes for this outline
for( int h = 0; h < aPolySet.HoleCount( i ); ++h )
{
const SHAPE_LINE_CHAIN &hole = aPolySet.CHole( i, h );
AddToMiddleContourns( hole, zBot, zTop, aBiuTo3Du, aInvertFaceDirection );
}
}
threadsFinished++;
} );
t.detach();
} }
while( threadsFinished < parallelThreadCount )
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
} }

View File

@ -35,6 +35,7 @@
#include <geometry/shape_line_chain.h> #include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h> #include <geometry/shape_poly_set.h>
#include <vector> #include <vector>
#include <mutex>
typedef std::vector< SFVEC3F > SFVEC3F_VECTOR; typedef std::vector< SFVEC3F > SFVEC3F_VECTOR;
@ -174,6 +175,8 @@ public:
float zTop, float zTop,
bool aInvertFaceDirection ); bool aInvertFaceDirection );
std::mutex m_middle_layer_lock;
CLAYER_TRIANGLE_CONTAINER *m_layer_top_segment_ends; CLAYER_TRIANGLE_CONTAINER *m_layer_top_segment_ends;
CLAYER_TRIANGLE_CONTAINER *m_layer_top_triangles; CLAYER_TRIANGLE_CONTAINER *m_layer_top_triangles;
CLAYER_TRIANGLE_CONTAINER *m_layer_middle_contourns_quads; CLAYER_TRIANGLE_CONTAINER *m_layer_middle_contourns_quads;

View File

@ -29,6 +29,7 @@
#include "ccontainer2d.h" #include "ccontainer2d.h"
#include <vector> #include <vector>
#include <mutex>
#include <boost/range/algorithm/partition.hpp> #include <boost/range/algorithm/partition.hpp>
#include <boost/range/algorithm/nth_element.hpp> #include <boost/range/algorithm/nth_element.hpp>
#include <wx/debug.h> #include <wx/debug.h>
@ -46,6 +47,7 @@ CGENERICCONTAINER2D::CGENERICCONTAINER2D( OBJECT2D_TYPE aObjType )
void CGENERICCONTAINER2D::Clear() void CGENERICCONTAINER2D::Clear()
{ {
std::lock_guard<std::mutex> lock( m_lock );
m_bbox.Reset(); m_bbox.Reset();
for( LIST_OBJECT2D::iterator ii = m_objects.begin(); for( LIST_OBJECT2D::iterator ii = m_objects.begin();

View File

@ -32,6 +32,7 @@
#include "../shapes2D/cobject2d.h" #include "../shapes2D/cobject2d.h"
#include <list> #include <list>
#include <mutex>
typedef std::list<COBJECT2D *> LIST_OBJECT2D; typedef std::list<COBJECT2D *> LIST_OBJECT2D;
typedef std::list<const COBJECT2D *> CONST_LIST_OBJECT2D; typedef std::list<const COBJECT2D *> CONST_LIST_OBJECT2D;
@ -52,6 +53,7 @@ public:
{ {
if( aObject ) // Only add if it is a valid pointer if( aObject ) // Only add if it is a valid pointer
{ {
std::lock_guard<std::mutex> lock( m_lock );
m_objects.push_back( aObject ); m_objects.push_back( aObject );
m_bbox.Union( aObject->GetBBox() ); m_bbox.Union( aObject->GetBBox() );
} }
@ -70,6 +72,7 @@ public:
CONST_LIST_OBJECT2D &aOutList ) const = 0; CONST_LIST_OBJECT2D &aOutList ) const = 0;
private: private:
std::mutex m_lock;
}; };

View File

@ -131,7 +131,7 @@ private:
unsigned long int m_stats_start_rendering_time; unsigned long int m_stats_start_rendering_time;
/// Save the number of blocks progress of the render /// Save the number of blocks progress of the render
long m_nrBlocksRenderProgress; size_t m_nrBlocksRenderProgress;
CPOSTSHADER_SSAO m_postshader_ssao; CPOSTSHADER_SSAO m_postshader_ssao;
@ -165,7 +165,7 @@ private:
std::vector< SFVEC2UI > m_blockPositions; std::vector< SFVEC2UI > m_blockPositions;
/// this flags if a position was already processed (cleared each new render) /// this flags if a position was already processed (cleared each new render)
std::vector< bool > m_blockPositionsWasProcessed; std::vector< int > m_blockPositionsWasProcessed;
/// this encodes the Morton code positions (on fast preview mode) /// this encodes the Morton code positions (on fast preview mode)
std::vector< SFVEC2UI > m_blockPositionsFast; std::vector< SFVEC2UI > m_blockPositionsFast;

View File

@ -31,6 +31,10 @@
#include "buffers_debug.h" #include "buffers_debug.h"
#include <string.h> // For memcpy #include <string.h> // For memcpy
#include <atomic>
#include <thread>
#include <chrono>
#ifndef CLAMP #ifndef CLAMP
#define CLAMP(n, min, max) {if( n < min ) n=min; else if( n > max ) n = max;} #define CLAMP(n, min, max) {if( n < min ) n=min; else if( n > max ) n = max;}
#endif #endif
@ -469,34 +473,51 @@ void CIMAGE::EfxFilter( CIMAGE *aInImg, E_FILTER aFilterType )
aInImg->m_wraping = WRAP_CLAMP; aInImg->m_wraping = WRAP_CLAMP;
m_wraping = WRAP_CLAMP; m_wraping = WRAP_CLAMP;
#pragma omp parallel for std::atomic<size_t> nextRow( 0 );
for( int iy = 0; iy < (int)m_height; iy++) std::atomic<size_t> threadsFinished( 0 );
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
{ {
for( int ix = 0; ix < (int)m_width; ix++ ) std::thread t = std::thread( [&]()
{ {
int v = 0; for( size_t iy = nextRow.fetch_add( 1 );
iy < m_height;
for( int sy = 0; sy < 5; sy++ ) iy = nextRow.fetch_add( 1 ) )
{ {
for( int sx = 0; sx < 5; sx++ ) for( size_t ix = 0; ix < m_width; ix++ )
{ {
int factor = filter.kernel[sx][sy]; int v = 0;
unsigned char pixelv = aInImg->Getpixel( ix + sx - 2,
iy + sy - 2 );
v += pixelv * factor; for( size_t sy = 0; sy < 5; sy++ )
{
for( size_t sx = 0; sx < 5; sx++ )
{
int factor = filter.kernel[sx][sy];
unsigned char pixelv = aInImg->Getpixel( ix + sx - 2,
iy + sy - 2 );
v += pixelv * factor;
}
}
v /= filter.div;
v += filter.offset;
CLAMP(v, 0, 255);
//TODO: This needs to write to a separate buffer
m_pixels[ix + iy * m_width] = v;
} }
} }
v /= filter.div; threadsFinished++;
} );
v += filter.offset; t.detach();
CLAMP(v, 0, 255);
m_pixels[ix + iy * m_width] = v;
}
} }
while( threadsFinished < parallelThreadCount )
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
} }

View File

@ -1,81 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Mario Luzeiro <mrluzeiro@ua.pt>
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file openmp_mutex.h
* @brief a mutex for openmp got from the website:
* http://bisqwit.iki.fi/story/howto/openmp/
* by Joel Yliluoma <bisqwit@iki.fi>
*/
#ifndef _OPENMP_MUTEX_H
#define _OPENMP_MUTEX_H
#ifdef _OPENMP
# include <omp.h>
struct MutexType
{
MutexType() { omp_init_lock( &lock ); }
~MutexType() { omp_destroy_lock( &lock ); }
void Lock() { omp_set_lock( &lock ); }
void Unlock() { omp_unset_lock( &lock ); }
MutexType( const MutexType& ) { omp_init_lock( &lock ); }
MutexType& operator= ( const MutexType& ) { return *this; }
public:
omp_lock_t lock;
};
#else
/// A dummy mutex that doesn't actually exclude anything,
/// but as there is no parallelism either, no worries.
struct MutexType
{
void Lock() {}
void Unlock() {}
};
#endif
/// An exception-safe scoped lock-keeper.
struct ScopedLock
{
explicit ScopedLock( MutexType& m ) : mut( m ), locked( true ) { mut.Lock(); }
~ScopedLock() { Unlock(); }
void Unlock() { if( !locked ) return; locked = false; mut.Unlock(); }
void LockAgain() { if( locked ) return; mut.Lock(); locked = true; }
private:
MutexType& mut;
bool locked;
private: // prevent copying the scoped lock.
void operator=(const ScopedLock&);
ScopedLock(const ScopedLock&);
};
#endif // _OPENMP_MUTEX_H

View File

@ -543,24 +543,6 @@ include( ExternalProject )
#================================================ #================================================
include( CheckFindPackageResult ) include( CheckFindPackageResult )
#
# Find OpenMP support, optional
#
find_package( OpenMP )
if( OPENMP_FOUND )
set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" )
add_definitions( -DUSE_OPENMP )
# MinGW does not include the OpenMP link library and FindOpenMP.cmake does not
# set it either. Not sure this is the most elegant solution but it works.
if( MINGW )
set( OPENMP_LIBRARIES gomp )
endif()
endif()
# #
# Find wxWidgets library, required # Find wxWidgets library, required
# #

View File

@ -52,9 +52,18 @@ SHAPE_POLY_SET::SHAPE_POLY_SET() :
} }
SHAPE_POLY_SET::SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther ) : SHAPE_POLY_SET::SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther, bool aDeepCopy ) :
SHAPE( SH_POLY_SET ), m_polys( aOther.m_polys ) SHAPE( SH_POLY_SET ), m_polys( aOther.m_polys )
{ {
if( aOther.IsTriangulationUpToDate() )
{
for( unsigned i = 0; i < aOther.TriangulatedPolyCount(); i++ )
m_triangulatedPolys.push_back(
std::make_unique<TRIANGULATED_POLYGON>( *aOther.TriangulatedPolygon( i ) ) );
m_hash = aOther.GetHash();
m_triangulationValid = true;
}
} }

View File

@ -151,7 +151,6 @@ target_link_libraries( cvpcb_kiface
gal gal
${wxWidgets_LIBRARIES} ${wxWidgets_LIBRARIES}
${GDI_PLUS_LIBRARIES} ${GDI_PLUS_LIBRARIES}
${OPENMP_LIBRARIES} # used by 3d viewer
) )
if( BUILD_GITHUB_PLUGIN ) if( BUILD_GITHUB_PLUGIN )

View File

@ -424,8 +424,9 @@ class SHAPE_POLY_SET : public SHAPE
* Copy constructor SHAPE_POLY_SET * Copy constructor SHAPE_POLY_SET
* Performs a deep copy of \p aOther into \p this. * Performs a deep copy of \p aOther into \p this.
* @param aOther is the SHAPE_POLY_SET object that will be copied. * @param aOther is the SHAPE_POLY_SET object that will be copied.
* @param aDeepCopy if true, make new copies of the triangulated unique_ptr vector
*/ */
SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther ); SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther, bool aDeepCopy = false );
~SHAPE_POLY_SET(); ~SHAPE_POLY_SET();

View File

@ -652,12 +652,6 @@ if ( KICAD_BUILD_TESTS )
endif () endif ()
if( ${OPENMP_FOUND} )
set_target_properties( pcbnew_kiface PROPERTIES
COMPILE_FLAGS ${OpenMP_CXX_FLAGS}
)
endif()
set( PCBNEW_KIFACE_LIBRARIES set( PCBNEW_KIFACE_LIBRARIES
3d-viewer 3d-viewer
pcbcommon pcbcommon
@ -675,7 +669,6 @@ set( PCBNEW_KIFACE_LIBRARIES
${PYTHON_LIBRARIES} ${PYTHON_LIBRARIES}
${Boost_LIBRARIES} # must follow GITHUB ${Boost_LIBRARIES} # must follow GITHUB
${PCBNEW_EXTRA_LIBS} # -lrt must follow Boost ${PCBNEW_EXTRA_LIBS} # -lrt must follow Boost
${OPENMP_LIBRARIES}
) )

View File

@ -32,6 +32,7 @@
#include <class_zone.h> #include <class_zone.h>
#include <profile.h> #include <profile.h>
#include <atomic>
#include <thread> #include <thread>
#include <unordered_set> #include <unordered_set>
#include <utility> #include <utility>
@ -229,31 +230,50 @@ int main( int argc, char *argv[] )
PROF_COUNTER cnt( "allBoard" ); PROF_COUNTER cnt( "allBoard" );
#pragma omp parallel for schedule(dynamic) std::atomic<size_t> zonesToTriangulate( 0 );
for( int z = 0; z<brd->GetAreaCount(); z++ ) std::atomic<size_t> threadsFinished( 0 );
size_t parallelThreadCount = std::max<size_t>( std::thread::hardware_concurrency(), 2 );
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
{ {
auto zone = brd->GetArea( z ); std::thread t = std::thread( [brd, &zonesToTriangulate, &threadsFinished] ()
SHAPE_POLY_SET poly = zone->GetFilledPolysList();
poly.CacheTriangulation();
(void) poly;
printf("zone %d/%d\n", ( z+1 ), brd->GetAreaCount() );
#if 0
PROF_COUNTER unfrac("unfrac");
poly.Unfracture( SHAPE_POLY_SET::PM_FAST );
unfrac.Show();
PROF_COUNTER triangulate("triangulate");
for(int i =0; i< poly.OutlineCount(); i++)
{ {
poly.triangulatePoly( &poly.Polygon(i) ); for( size_t areaId = zonesToTriangulate.fetch_add( 1 );
} areaId < static_cast<size_t>( brd->GetAreaCount() );
triangulate.Show(); areaId = zonesToTriangulate.fetch_add( 1 ) )
#endif {
auto zone = brd->GetArea( areaId );
SHAPE_POLY_SET poly = zone->GetFilledPolysList();
poly.CacheTriangulation();
(void) poly;
printf("zone %zu/%d\n", ( areaId + 1 ), brd->GetAreaCount() );
#if 0
PROF_COUNTER unfrac("unfrac");
poly.Unfracture( SHAPE_POLY_SET::PM_FAST );
unfrac.Show();
PROF_COUNTER triangulate("triangulate");
for(int i =0; i< poly.OutlineCount(); i++)
{
poly.triangulatePoly( &poly.Polygon(i) );
}
triangulate.Show();
#endif
}
threadsFinished++;
} );
t.detach();
} }
while( threadsFinished < parallelThreadCount )
std::this_thread::sleep_for( std::chrono::milliseconds( 10 ) );
cnt.Show(); cnt.Show();
delete brd; delete brd;