Added dependencies on the Intel Thread Building Blocks.
Changed the C++ parallelization code to Intel Thread Building Blocks.
This commit is contained in:
parent
8a42c0ad9f
commit
cb1a6eae1e
6 changed files with 158 additions and 96 deletions
140
xs/Build.PL
140
xs/Build.PL
|
@ -8,8 +8,18 @@ use ExtUtils::CppGuess;
|
||||||
use Module::Build::WithXSpp;
|
use Module::Build::WithXSpp;
|
||||||
|
|
||||||
my $cpp_guess = ExtUtils::CppGuess->new;
|
my $cpp_guess = ExtUtils::CppGuess->new;
|
||||||
|
my $lib_ext = ${$cpp_guess}{config}{lib_ext};
|
||||||
my $mswin = $^O eq 'MSWin32';
|
my $mswin = $^O eq 'MSWin32';
|
||||||
|
|
||||||
|
# Library paths to search for boost, thread building blocks and such.
|
||||||
|
# On Windows, there is really no standard. On Unices, this is a bit better.
|
||||||
|
my @library_path_prefixes = ();
|
||||||
|
if ($mswin) {
|
||||||
|
@library_path_prefixes = ("C:\\", "C:\\dev\\", "C:\\local\\", "D:\\", "D:\\dev\\", "D:\\local\\");
|
||||||
|
} else {
|
||||||
|
@library_path_prefixes = qw(/opt/local/ /usr/local/ /opt/ /usr/);
|
||||||
|
}
|
||||||
|
|
||||||
# _GLIBCXX_USE_C99 : to get the long long type for g++
|
# _GLIBCXX_USE_C99 : to get the long long type for g++
|
||||||
# HAS_BOOL : stops Perl/lib/CORE/handy.h from doing "# define bool char" for MSVC
|
# HAS_BOOL : stops Perl/lib/CORE/handy.h from doing "# define bool char" for MSVC
|
||||||
# NOGDI : prevents inclusion of wingdi.h which defines functions Polygon() and Polyline() in global namespace
|
# NOGDI : prevents inclusion of wingdi.h which defines functions Polygon() and Polyline() in global namespace
|
||||||
|
@ -76,24 +86,23 @@ if (defined $ENV{BOOST_INCLUDEDIR}) {
|
||||||
# Boost library was not defined by the environment.
|
# Boost library was not defined by the environment.
|
||||||
# Try to guess at some default paths.
|
# Try to guess at some default paths.
|
||||||
if ($mswin) {
|
if ($mswin) {
|
||||||
for my $path (glob('C:\dev\boost*\include'), glob ('C:\boost*\include')) {
|
for my $path (map glob($_ . 'boost*\include'), @library_path_prefixes) {
|
||||||
push @boost_include, $path;
|
push @boost_include, $path;
|
||||||
}
|
}
|
||||||
if (! @boost_include) {
|
if (! @boost_include) {
|
||||||
# No boost\include. Try to include the boost root.
|
# No boost\include. Try to include the boost root.
|
||||||
for my $path (glob('C:\dev\boost*'), glob ('C:\boost*')) {
|
for my $path (map glob($_ . 'boost*'), @library_path_prefixes) {
|
||||||
push @boost_include, $path;
|
push @boost_include, $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
push @boost_include, grep { -d $_ }
|
@boost_include = grep { -d $_ . '/boost' } map { $_ . 'include' } @library_path_prefixes;
|
||||||
qw(/opt/local/include /usr/local/include /opt/include /usr/include);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
my @boost_libs = ();
|
my @boost_libs = ();
|
||||||
if (defined $ENV{BOOST_LIBRARYDIR}) {
|
if (defined $ENV{BOOST_LIBRARYDIR}) {
|
||||||
push @boost_libs, $ENV{BOOST_LIBRARYDIR}
|
push @boost_libs, $ENV{BOOST_LIBRARYDIR};
|
||||||
} elsif (defined $ENV{BOOST_DIR}) {
|
} elsif (defined $ENV{BOOST_DIR}) {
|
||||||
my $subdir = $ENV{BOOST_DIR} . ($mswin ? '\stage\lib' : '/stage/lib');
|
my $subdir = $ENV{BOOST_DIR} . ($mswin ? '\stage\lib' : '/stage/lib');
|
||||||
if (-d $subdir) {
|
if (-d $subdir) {
|
||||||
|
@ -105,14 +114,11 @@ if (defined $ENV{BOOST_LIBRARYDIR}) {
|
||||||
# Boost library was not defined by the environment.
|
# Boost library was not defined by the environment.
|
||||||
# Try to guess at some default paths.
|
# Try to guess at some default paths.
|
||||||
if ($mswin) {
|
if ($mswin) {
|
||||||
for my $path (
|
for my $path (map (glob($_ . 'boost*\lib'), glob($_ . 'boost*\stage\lib')), @library_path_prefixes) {
|
||||||
glob('C:\dev\boost*\lib'), glob ('C:\boost*\lib'),
|
|
||||||
glob('C:\dev\boost*\stage\lib'), glob ('C:\boost*\stage\lib')) {
|
|
||||||
push @boost_libs, $path;
|
push @boost_libs, $path;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
push @boost_libs, grep { -d $_ }
|
push @boost_libs, grep { -d $_ } map $_ . 'lib', @library_path_prefixes;
|
||||||
qw(/opt/local/lib /usr/local/lib /opt/lib /usr/lib /lib);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +144,6 @@ if ($have_boost) {
|
||||||
} else {
|
} else {
|
||||||
# Either static linking, or check_lib could not be used to find the boost libraries.
|
# Either static linking, or check_lib could not be used to find the boost libraries.
|
||||||
my $lib_prefix = 'libboost_';
|
my $lib_prefix = 'libboost_';
|
||||||
my $lib_ext = ${$cpp_guess}{config}{lib_ext};
|
|
||||||
PATH: foreach my $path (@boost_libs) {
|
PATH: foreach my $path (@boost_libs) {
|
||||||
# Try to find the boost system library.
|
# Try to find the boost system library.
|
||||||
my @files = glob "$path/${lib_prefix}system*$lib_ext";
|
my @files = glob "$path/${lib_prefix}system*$lib_ext";
|
||||||
|
@ -185,6 +190,110 @@ is handy, if you have built Boost libraries with mutliple settings.
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# Search for the Intel Thread Building Blocks.
|
||||||
|
my @tbb_include = ();
|
||||||
|
if (defined $ENV{TBB_INCLUDEDIR}) {
|
||||||
|
push @tbb_include, $ENV{TBB_INCLUDEDIR}
|
||||||
|
} elsif (defined $ENV{TBB_DIR}) {
|
||||||
|
my $subdir = $ENV{TBB_DIR} . (($mswin == 1) ? '\include' : '/include');
|
||||||
|
push @tbb_include, $subdir if (-d $subdir);
|
||||||
|
} else {
|
||||||
|
# Thread Building Blocks library was not defined by the environment.
|
||||||
|
# Try to guess at some default paths.
|
||||||
|
if ($mswin) {
|
||||||
|
for my $path (map glob($_ . 'tbb*\include'), @library_path_prefixes) {
|
||||||
|
push @tbb_include, $path;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@tbb_include = grep { -d $_ . '/tbb' } map { $_ . 'include' } @library_path_prefixes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my @tbb_libs = ();
|
||||||
|
if (defined $ENV{TBB_LIBRARYDIR}) {
|
||||||
|
push @tbb_libs, $ENV{TBB_LIBRARYDIR}
|
||||||
|
} elsif (defined $ENV{TBB_DIR}) {
|
||||||
|
my $subdir = $ENV{TBB_DIR} . ($mswin ? '\lib' : '/lib');
|
||||||
|
push @tbb_libs, $subdir if (-d $subdir);
|
||||||
|
} else {
|
||||||
|
# Thread Building Blocks library was not defined by the environment.
|
||||||
|
# Try to guess at some default paths.
|
||||||
|
if ($mswin) {
|
||||||
|
for my $path (map { glob($_ . 'tbb*\lib') } @library_path_prefixes) {
|
||||||
|
push @tbb_libs, $path;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@tbb_libs = grep { -d $_ } map { $_ . 'lib' } @library_path_prefixes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# In order to generate the -l switches we need to know how Thread Building Blocks libraries are named
|
||||||
|
my $have_tbb = 0;
|
||||||
|
#my @tbb_libraries = qw(tbb tbbmalloc tbbmalloc_proxy); # we need these
|
||||||
|
my @tbb_libraries = qw(tbb); # we need these
|
||||||
|
|
||||||
|
if (!$ENV{SLIC3R_STATIC}) {
|
||||||
|
# Dynamic linking of Thread Building Blocks libraries.
|
||||||
|
if (! $mswin) {
|
||||||
|
# Check without explicit lib path (works on Linux and OSX).
|
||||||
|
$have_tbb = 1
|
||||||
|
if check_lib(
|
||||||
|
lib => [ @tbb_libraries ],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($have_tbb) {
|
||||||
|
# The Thread Building Blocks library was detected by check_lib on Linux.
|
||||||
|
push @LIBS, map "-l${_}", @tbb_libraries;
|
||||||
|
} else {
|
||||||
|
# Either static linking, or check_lib could not be used to find the Thread Building Blocks libraries.
|
||||||
|
my $lib_prefix = $cpp_guess->is_msvc ? '' : 'lib';
|
||||||
|
PATH: foreach my $path (@tbb_libs) {
|
||||||
|
# Try to find the Thread Building Blocks system library.
|
||||||
|
my @files = glob "$path/${lib_prefix}tbb*$lib_ext";
|
||||||
|
next if !@files;
|
||||||
|
if ($files[0] =~ /\Q${lib_prefix}tbb\E([^.]*)\Q$lib_ext\E$/) {
|
||||||
|
# Suffix contains the version number, the build type etc.
|
||||||
|
my $suffix = $1;
|
||||||
|
# Verify existence of all required TBB libraries at $path.
|
||||||
|
for my $lib (map "${lib_prefix}${_}${suffix}${lib_ext}", @tbb_libraries) {
|
||||||
|
# If the library file does not exist, try next library path.
|
||||||
|
-f "$path/$lib" or next PATH;
|
||||||
|
}
|
||||||
|
if (! $cpp_guess->is_msvc) {
|
||||||
|
# Test the correctness of TBB libraries by linking them to a minimal C program.
|
||||||
|
check_lib(
|
||||||
|
lib => [ map "${_}${suffix}", @tbb_libraries ],
|
||||||
|
INC => join(' ', map "-I$_", @INC, @tbb_include),
|
||||||
|
LIBS => "-L$path",
|
||||||
|
) or next;
|
||||||
|
}
|
||||||
|
push @INC, (map " -I$_", @tbb_include); # TODO: only use the one related to the chosen lib path
|
||||||
|
if ($ENV{SLIC3R_STATIC} || $cpp_guess->is_msvc) {
|
||||||
|
push @LIBS, map "${path}/${_}_static.lib", @tbb_libraries;
|
||||||
|
} else {
|
||||||
|
push @LIBS, " -L$path", (map " -l$_$suffix", @tbb_libraries);
|
||||||
|
}
|
||||||
|
$have_tbb = 1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
die <<'EOF' if !$have_tbb;
|
||||||
|
Slic3r requires the Intel Thread Building Blocks libraries. Please make sure the library is installed.
|
||||||
|
|
||||||
|
If the Intel Thread Building Blocks library is installed, this script should be able to locate them in several
|
||||||
|
standard locations. If this is not the case, you might want to supply a path to the library
|
||||||
|
through the TBB_DIR environment variable:
|
||||||
|
|
||||||
|
TBB_DIR=/path/to/TBB perl Build.PL
|
||||||
|
|
||||||
|
Or you may specify TBB_INCLUDEPATH and TBB_LIBRARYPATH separatly, which
|
||||||
|
is handy, if you have built the Thread Building Blocks libraries with mutliple settings.
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
# Add the OpenGL and GLU libraries.
|
# Add the OpenGL and GLU libraries.
|
||||||
if ($ENV{SLIC3R_GUI}) {
|
if ($ENV{SLIC3R_GUI}) {
|
||||||
if ($mswin) {
|
if ($mswin) {
|
||||||
|
@ -206,15 +315,6 @@ if ($ENV{SLIC3R_DEBUG}) {
|
||||||
# Disable asserts in the release builds.
|
# Disable asserts in the release builds.
|
||||||
push @cflags, '-DNDEBUG';
|
push @cflags, '-DNDEBUG';
|
||||||
}
|
}
|
||||||
if ($cpp_guess->is_gcc) {
|
|
||||||
# check whether we're dealing with a buggy GCC version
|
|
||||||
# see https://github.com/alexrj/Slic3r/issues/1965
|
|
||||||
if (`cc --version` =~ m/ 4\.7\.[012]/) {
|
|
||||||
# Workaround suggested by Boost devs:
|
|
||||||
# https://svn.boost.org/trac/boost/ticket/8695
|
|
||||||
push @cflags, qw(-fno-inline-small-functions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print "\n";
|
print "\n";
|
||||||
print 'With @cflags: ', join(', ', map "\"$_\"", @cflags), "\n";
|
print 'With @cflags: ', join(', ', map "\"$_\"", @cflags), "\n";
|
||||||
|
|
|
@ -1029,6 +1029,7 @@ GCode::needs_retraction(const Polyline &travel, ExtrusionRole role)
|
||||||
|
|
||||||
if (role == erSupportMaterial) {
|
if (role == erSupportMaterial) {
|
||||||
const SupportLayer* support_layer = dynamic_cast<const SupportLayer*>(this->layer);
|
const SupportLayer* support_layer = dynamic_cast<const SupportLayer*>(this->layer);
|
||||||
|
//FIXME support_layer->support_islands.contains should use some search structure!
|
||||||
if (support_layer != NULL && support_layer->support_islands.contains(travel)) {
|
if (support_layer != NULL && support_layer->support_islands.contains(travel)) {
|
||||||
// skip retraction if this is a travel move inside a support material island
|
// skip retraction if this is a travel move inside a support material island
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_for.h>
|
||||||
|
#include <tbb/atomic.h>
|
||||||
|
|
||||||
#include <Shiny/Shiny.h>
|
#include <Shiny/Shiny.h>
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
|
@ -632,7 +635,7 @@ PrintObject::discover_vertical_shells()
|
||||||
LayerRegion &neighbor_region = *neighbor_layer.get_region(int(idx_region));
|
LayerRegion &neighbor_region = *neighbor_layer.get_region(int(idx_region));
|
||||||
Polygons newholes;
|
Polygons newholes;
|
||||||
for (size_t idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region)
|
for (size_t idx_region = 0; idx_region < this->_print->regions.size(); ++ idx_region)
|
||||||
polygons_append(newholes, to_polygons(neighbor_layer.get_region(idx_region)->fill_expolygons));
|
polygons_append(newholes, to_polygons(neighbor_layer.regions[idx_region]->fill_expolygons));
|
||||||
if (hole_first) {
|
if (hole_first) {
|
||||||
hole_first = false;
|
hole_first = false;
|
||||||
polygons_append(holes, STDMOVE(newholes));
|
polygons_append(holes, STDMOVE(newholes));
|
||||||
|
@ -1267,12 +1270,15 @@ PrintObject::_make_perimeters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel";
|
BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - start";
|
||||||
parallelize<Layer*>(
|
tbb::parallel_for(
|
||||||
std::queue<Layer*>(std::deque<Layer*>(this->layers.begin(), this->layers.end())), // cast LayerPtrs to std::queue<Layer*>
|
tbb::blocked_range<size_t>(0, this->layers.size()),
|
||||||
boost::bind(&Slic3r::Layer::make_perimeters, _1),
|
[this](const tbb::blocked_range<size_t>& range) {
|
||||||
this->_print->config.threads.value
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
|
||||||
|
this->layers[layer_idx]->make_perimeters();
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - end";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
simplify slices (both layer and region slices),
|
simplify slices (both layer and region slices),
|
||||||
|
@ -1290,12 +1296,15 @@ PrintObject::_infill()
|
||||||
if (this->state.is_done(posInfill)) return;
|
if (this->state.is_done(posInfill)) return;
|
||||||
this->state.set_started(posInfill);
|
this->state.set_started(posInfill);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel";
|
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
|
||||||
parallelize<Layer*>(
|
tbb::parallel_for(
|
||||||
std::queue<Layer*>(std::deque<Layer*>(this->layers.begin(), this->layers.end())), // cast LayerPtrs to std::queue<Layer*>
|
tbb::blocked_range<size_t>(0, this->layers.size()),
|
||||||
boost::bind(&Slic3r::Layer::make_fills, _1),
|
[this](const tbb::blocked_range<size_t>& range) {
|
||||||
this->_print->config.threads.value
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
|
||||||
|
this->layers[layer_idx]->make_fills();
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - end";
|
||||||
|
|
||||||
/* we could free memory now, but this would make this step not idempotent
|
/* we could free memory now, but this would make this step not idempotent
|
||||||
### $_->fill_surfaces->clear for map @{$_->regions}, @{$object->layers};
|
### $_->fill_surfaces->clear for map @{$_->regions}, @{$object->layers};
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
|
#include <tbb/parallel_for.h>
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
#define _DEBUG
|
#define _DEBUG
|
||||||
|
@ -672,10 +674,12 @@ TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons>* la
|
||||||
std::vector<IntersectionLines> lines(z.size());
|
std::vector<IntersectionLines> lines(z.size());
|
||||||
{
|
{
|
||||||
boost::mutex lines_mutex;
|
boost::mutex lines_mutex;
|
||||||
parallelize<int>(
|
tbb::parallel_for(
|
||||||
0,
|
tbb::blocked_range<int>(0,this->mesh->stl.stats.number_of_facets),
|
||||||
this->mesh->stl.stats.number_of_facets-1,
|
[&lines, &lines_mutex, &z, this](const tbb::blocked_range<int>& range) {
|
||||||
boost::bind(&TriangleMeshSlicer::_slice_do, this, _1, &lines, &lines_mutex, z)
|
for (int facet_idx = range.begin(); facet_idx < range.end(); ++ facet_idx)
|
||||||
|
this->_slice_do(facet_idx, &lines, &lines_mutex, z);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,10 +688,12 @@ TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons>* la
|
||||||
// build loops
|
// build loops
|
||||||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::_make_loops_do";
|
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::_make_loops_do";
|
||||||
layers->resize(z.size());
|
layers->resize(z.size());
|
||||||
parallelize<size_t>(
|
tbb::parallel_for(
|
||||||
0,
|
tbb::blocked_range<size_t>(0, lines.size()),
|
||||||
lines.size()-1,
|
[&lines, &layers, this](const tbb::blocked_range<size_t>& range) {
|
||||||
boost::bind(&TriangleMeshSlicer::_make_loops_do, this, _1, &lines, layers)
|
for (size_t line_idx = range.begin(); line_idx < range.end(); ++ line_idx)
|
||||||
|
this->make_loops(lines[line_idx], &(*layers)[line_idx]);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::slice finished";
|
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::slice finished";
|
||||||
}
|
}
|
||||||
|
@ -873,12 +879,6 @@ bool TriangleMeshSlicer::slice_facet(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
TriangleMeshSlicer::_make_loops_do(size_t i, std::vector<IntersectionLines>* lines, std::vector<Polygons>* layers) const
|
|
||||||
{
|
|
||||||
this->make_loops((*lines)[i], &(*layers)[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TriangleMeshSlicer::make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const
|
void TriangleMeshSlicer::make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const
|
||||||
{
|
{
|
||||||
// Remove tangent edges.
|
// Remove tangent edges.
|
||||||
|
|
|
@ -132,7 +132,6 @@ private:
|
||||||
std::vector<stl_vertex> v_scaled_shared;
|
std::vector<stl_vertex> v_scaled_shared;
|
||||||
|
|
||||||
void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const;
|
void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const;
|
||||||
void _make_loops_do(size_t i, std::vector<IntersectionLines>* lines, std::vector<Polygons>* layers) const;
|
|
||||||
void make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const;
|
void make_loops(std::vector<IntersectionLine> &lines, Polygons* loops) const;
|
||||||
void make_expolygons(const Polygons &loops, ExPolygons* slices) const;
|
void make_expolygons(const Polygons &loops, ExPolygons* slices) const;
|
||||||
void make_expolygons_simple(std::vector<IntersectionLine> &lines, ExPolygons* slices) const;
|
void make_expolygons_simple(std::vector<IntersectionLine> &lines, ExPolygons* slices) const;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
|
#define SLIC3R_FORK_NAME "Slic3r Prusa Edition"
|
||||||
#define SLIC3R_VERSION "1.31.6"
|
#define SLIC3R_VERSION "1.33.8.devel"
|
||||||
#define SLIC3R_BUILD "UNKNOWN"
|
#define SLIC3R_BUILD "UNKNOWN"
|
||||||
|
|
||||||
//FIXME This epsilon value is used for many non-related purposes:
|
//FIXME This epsilon value is used for many non-related purposes:
|
||||||
|
@ -99,53 +99,6 @@ inline void append_to(std::vector<T> &dst, const std::vector<T> &src)
|
||||||
dst.insert(dst.end(), src.begin(), src.end());
|
dst.insert(dst.end(), src.begin(), src.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> void
|
|
||||||
_parallelize_do(std::queue<T>* queue, boost::mutex* queue_mutex, boost::function<void(T)> func)
|
|
||||||
{
|
|
||||||
//std::cout << "THREAD STARTED: " << boost::this_thread::get_id() << std::endl;
|
|
||||||
while (true) {
|
|
||||||
T i;
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(*queue_mutex);
|
|
||||||
if (queue->empty()) return;
|
|
||||||
i = queue->front();
|
|
||||||
queue->pop();
|
|
||||||
}
|
|
||||||
//std::cout << " Thread " << boost::this_thread::get_id() << " processing item " << i << std::endl;
|
|
||||||
func(i);
|
|
||||||
boost::this_thread::interruption_point();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> void
|
|
||||||
parallelize(std::queue<T> queue, boost::function<void(T)> func,
|
|
||||||
int threads_count = boost::thread::hardware_concurrency())
|
|
||||||
{
|
|
||||||
#ifdef SLIC3R_PROFILE
|
|
||||||
while (! queue.empty()) {
|
|
||||||
func(queue.front());
|
|
||||||
queue.pop();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (threads_count == 0)
|
|
||||||
threads_count = 2;
|
|
||||||
boost::mutex queue_mutex;
|
|
||||||
boost::thread_group workers;
|
|
||||||
for (int i = 0; i < std::min(threads_count, int(queue.size())); ++ i)
|
|
||||||
workers.add_thread(new boost::thread(&_parallelize_do<T>, &queue, &queue_mutex, func));
|
|
||||||
workers.join_all();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> void
|
|
||||||
parallelize(T start, T end, boost::function<void(T)> func,
|
|
||||||
int threads_count = boost::thread::hardware_concurrency())
|
|
||||||
{
|
|
||||||
std::queue<T> queue;
|
|
||||||
for (T i = start; i <= end; ++i) queue.push(i);
|
|
||||||
parallelize(queue, func, threads_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void append(std::vector<T>& dest, const std::vector<T>& src)
|
void append(std::vector<T>& dest, const std::vector<T>& src)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue