Refactored parallelization code, cherry picked from @alexrj 36789774471a0bf9a66bb33cc3ab6984f8ede8c6
This commit is contained in:
parent
9fbd135f14
commit
73ddd3b438
@ -2,7 +2,6 @@
|
|||||||
#define slic3r_Print_hpp_
|
#define slic3r_Print_hpp_
|
||||||
|
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
#include <queue>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -156,8 +155,6 @@ private:
|
|||||||
// parameter
|
// parameter
|
||||||
PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox);
|
PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox);
|
||||||
~PrintObject();
|
~PrintObject();
|
||||||
void _make_perimeters_do(std::queue<size_t>* queue, boost::mutex* queue_mutex);
|
|
||||||
void _infill_do(std::queue<size_t>* queue, boost::mutex* queue_mutex);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<PrintObject*> PrintObjectPtrs;
|
typedef std::vector<PrintObject*> PrintObjectPtrs;
|
||||||
|
@ -1292,7 +1292,7 @@ PrintConfigDef::PrintConfigDef()
|
|||||||
def->readonly = true;
|
def->readonly = true;
|
||||||
def->min = 1;
|
def->min = 1;
|
||||||
def->max = 16;
|
def->max = 16;
|
||||||
def->default_value = new ConfigOptionInt(boost::thread::hardware_concurrency());
|
def->default_value = new ConfigOptionInt((boost::thread::hardware_concurrency() == 0) ? 2 : boost::thread::hardware_concurrency());
|
||||||
|
|
||||||
def = this->add("toolchange_gcode", coString);
|
def = this->add("toolchange_gcode", coString);
|
||||||
def->label = "Tool change G-code";
|
def->label = "Tool change G-code";
|
||||||
|
@ -1009,18 +1009,11 @@ PrintObject::_make_perimeters()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
parallelize<Layer*>(
|
||||||
// queue all the layer numbers
|
std::queue<Layer*>(std::deque<Layer*>(this->layers.begin(), this->layers.end())), // cast LayerPtrs to std::queue<Layer*>
|
||||||
std::queue<size_t> queue;
|
boost::bind(&Slic3r::Layer::make_perimeters, _1),
|
||||||
boost::mutex queue_mutex;
|
this->_print->config.threads.value
|
||||||
for (size_t i = 0; i < this->layer_count(); ++i)
|
);
|
||||||
queue.push(i);
|
|
||||||
|
|
||||||
boost::thread_group workers;
|
|
||||||
for (int i = 0; i < this->_print->config.threads; i++)
|
|
||||||
workers.add_thread(new boost::thread(&Slic3r::PrintObject::_make_perimeters_do, this, &queue, &queue_mutex));
|
|
||||||
workers.join_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
simplify slices (both layer and region slices),
|
simplify slices (both layer and region slices),
|
||||||
@ -1032,43 +1025,17 @@ PrintObject::_make_perimeters()
|
|||||||
this->state.set_done(posPerimeters);
|
this->state.set_done(posPerimeters);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PrintObject::_make_perimeters_do(std::queue<size_t>* queue, boost::mutex* queue_mutex)
|
|
||||||
{
|
|
||||||
//std::cout << "THREAD STARTED: " << boost::this_thread::get_id() << std::endl;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
size_t layer_id;
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(*queue_mutex);
|
|
||||||
if (queue->empty()) return;
|
|
||||||
layer_id = queue->front();
|
|
||||||
queue->pop();
|
|
||||||
}
|
|
||||||
//std::cout << " Layer " << layer_id << " (" << boost::this_thread::get_id() << ")" << std::endl;
|
|
||||||
this->get_layer(layer_id)->make_perimeters();
|
|
||||||
boost::this_thread::interruption_point();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PrintObject::_infill()
|
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);
|
||||||
|
|
||||||
{
|
parallelize<Layer*>(
|
||||||
// queue all the layer numbers
|
std::queue<Layer*>(std::deque<Layer*>(this->layers.begin(), this->layers.end())), // cast LayerPtrs to std::queue<Layer*>
|
||||||
std::queue<size_t> queue;
|
boost::bind(&Slic3r::Layer::make_fills, _1),
|
||||||
boost::mutex queue_mutex;
|
this->_print->config.threads.value
|
||||||
for (size_t i = 0; i < this->layer_count(); ++i)
|
);
|
||||||
queue.push(i);
|
|
||||||
|
|
||||||
boost::thread_group workers;
|
|
||||||
for (int i = 0; i < this->_print->config.threads; i++)
|
|
||||||
workers.add_thread(new boost::thread(&Slic3r::PrintObject::_infill_do, this, &queue, &queue_mutex));
|
|
||||||
workers.join_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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};
|
||||||
@ -1077,23 +1044,4 @@ PrintObject::_infill()
|
|||||||
this->state.set_done(posInfill);
|
this->state.set_done(posInfill);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
PrintObject::_infill_do(std::queue<size_t>* queue, boost::mutex* queue_mutex)
|
|
||||||
{
|
|
||||||
//std::cout << "THREAD STARTED: " << boost::this_thread::get_id() << std::endl;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
size_t layer_id;
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(*queue_mutex);
|
|
||||||
if (queue->empty()) return;
|
|
||||||
layer_id = queue->front();
|
|
||||||
queue->pop();
|
|
||||||
}
|
|
||||||
//std::cout << " Layer " << layer_id << " (" << boost::this_thread::get_id() << ")" << std::endl;
|
|
||||||
this->get_layer(layer_id)->make_fills();
|
|
||||||
boost::this_thread::interruption_point();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <queue>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -432,83 +433,55 @@ TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons>* la
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
std::vector<IntersectionLines> lines(z.size());
|
std::vector<IntersectionLines> lines(z.size());
|
||||||
|
|
||||||
{
|
{
|
||||||
// queue all the facet indices
|
boost::mutex lines_mutex;
|
||||||
std::queue<size_t> queue;
|
parallelize<int>(
|
||||||
boost::mutex queue_mutex, lines_mutex;
|
0,
|
||||||
for (size_t i = 0; i < this->mesh->stl.stats.number_of_facets; ++i) queue.push(i);
|
this->mesh->stl.stats.number_of_facets-1,
|
||||||
|
boost::bind(&TriangleMeshSlicer::_slice_do, this, _1, &lines, &lines_mutex, z)
|
||||||
boost::thread_group workers;
|
);
|
||||||
for (int i = 0; i < boost::thread::hardware_concurrency(); i++)
|
|
||||||
workers.add_thread(new boost::thread(&TriangleMeshSlicer::_slice_do, this,
|
|
||||||
&queue, &queue_mutex, &lines, &lines_mutex, z));
|
|
||||||
workers.join_all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// v_scaled_shared could be freed here
|
// v_scaled_shared could be freed here
|
||||||
|
|
||||||
// build loops
|
// build loops
|
||||||
layers->resize(z.size());
|
layers->resize(z.size());
|
||||||
{
|
parallelize<size_t>(
|
||||||
// queue all the layer numbers
|
0,
|
||||||
std::queue<size_t> queue;
|
lines.size()-1,
|
||||||
boost::mutex queue_mutex;
|
boost::bind(&TriangleMeshSlicer::_make_loops_do, this, _1, &lines, layers)
|
||||||
for (size_t i = 0; i < lines.size(); ++i) queue.push(i);
|
);
|
||||||
|
|
||||||
// We don't use a mutex for lines because workers are only writing the skip property
|
|
||||||
// and no workers work on the same layer (i.e. item of 'lines').
|
|
||||||
boost::thread_group workers;
|
|
||||||
for (int i = 0; i < boost::thread::hardware_concurrency(); i++)
|
|
||||||
workers.add_thread(new boost::thread(&TriangleMeshSlicer::_make_loops_do, this,
|
|
||||||
&queue, &queue_mutex, &lines, layers));
|
|
||||||
workers.join_all();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TriangleMeshSlicer::_slice_do(std::queue<size_t>* queue, boost::mutex* queue_mutex,
|
TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex,
|
||||||
std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const
|
const std::vector<float> &z) const
|
||||||
{
|
{
|
||||||
//std::cout << "THREAD STARTED: " << boost::this_thread::get_id() << std::endl;
|
const stl_facet &facet = this->mesh->stl.facet_start[facet_idx];
|
||||||
|
|
||||||
while (true) {
|
// find facet extents
|
||||||
int facet_idx;
|
const float min_z = fminf(facet.vertex[0].z, fminf(facet.vertex[1].z, facet.vertex[2].z));
|
||||||
{
|
const float max_z = fmaxf(facet.vertex[0].z, fmaxf(facet.vertex[1].z, facet.vertex[2].z));
|
||||||
boost::lock_guard<boost::mutex> l(*queue_mutex);
|
|
||||||
if (queue->empty()) return;
|
|
||||||
facet_idx = queue->front();
|
|
||||||
queue->pop();
|
|
||||||
}
|
|
||||||
//std::cout << " Facet " << facet_idx << " (" << boost::this_thread::get_id() << ")" << std::endl;
|
|
||||||
|
|
||||||
const stl_facet &facet = this->mesh->stl.facet_start[facet_idx];
|
#ifdef SLIC3R_DEBUG
|
||||||
|
printf("\n==> FACET %d (%f,%f,%f - %f,%f,%f - %f,%f,%f):\n", facet_idx,
|
||||||
|
facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0].z,
|
||||||
|
facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1].z,
|
||||||
|
facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2].z);
|
||||||
|
printf("z: min = %.2f, max = %.2f\n", min_z, max_z);
|
||||||
|
#endif
|
||||||
|
|
||||||
// find facet extents
|
// find layer extents
|
||||||
const float min_z = fminf(facet.vertex[0].z, fminf(facet.vertex[1].z, facet.vertex[2].z));
|
std::vector<float>::const_iterator min_layer, max_layer;
|
||||||
const float max_z = fmaxf(facet.vertex[0].z, fmaxf(facet.vertex[1].z, facet.vertex[2].z));
|
min_layer = std::lower_bound(z.begin(), z.end(), min_z); // first layer whose slice_z is >= min_z
|
||||||
|
max_layer = std::upper_bound(z.begin() + (min_layer - z.begin()), z.end(), max_z) - 1; // last layer whose slice_z is <= max_z
|
||||||
|
#ifdef SLIC3R_DEBUG
|
||||||
|
printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin()));
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SLIC3R_TRIANGLEMESH_DEBUG
|
for (std::vector<float>::const_iterator it = min_layer; it != max_layer + 1; ++it) {
|
||||||
printf("\n==> FACET %d (%f,%f,%f - %f,%f,%f - %f,%f,%f):\n", facet_idx,
|
std::vector<float>::size_type layer_idx = it - z.begin();
|
||||||
facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0].z,
|
this->slice_facet(*it / SCALING_FACTOR, facet, facet_idx, min_z, max_z, &(*lines)[layer_idx], lines_mutex);
|
||||||
facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1].z,
|
|
||||||
facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2].z);
|
|
||||||
printf("z: min = %.2f, max = %.2f\n", min_z, max_z);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// find layer extents
|
|
||||||
std::vector<float>::const_iterator min_layer, max_layer;
|
|
||||||
min_layer = std::lower_bound(z.begin(), z.end(), min_z); // first layer whose slice_z is >= min_z
|
|
||||||
max_layer = std::upper_bound(z.begin() + (min_layer - z.begin()), z.end(), max_z) - 1; // last layer whose slice_z is <= max_z
|
|
||||||
#ifdef SLIC3R_TRIANGLEMESH_DEBUG
|
|
||||||
printf("layers: min = %d, max = %d\n", (int)(min_layer - z.begin()), (int)(max_layer - z.begin()));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (std::vector<float>::const_iterator it = min_layer; it != max_layer + 1; ++it) {
|
|
||||||
std::vector<float>::size_type layer_idx = it - z.begin();
|
|
||||||
this->slice_facet(*it / SCALING_FACTOR, facet, facet_idx, min_z, max_z, &(*lines)[layer_idx], lines_mutex);
|
|
||||||
}
|
|
||||||
boost::this_thread::interruption_point();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,23 +626,9 @@ TriangleMeshSlicer::slice_facet(float slice_z, const stl_facet &facet, const int
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TriangleMeshSlicer::_make_loops_do(std::queue<size_t>* queue, boost::mutex* queue_mutex,
|
TriangleMeshSlicer::_make_loops_do(size_t i, std::vector<IntersectionLines>* lines, std::vector<Polygons>* layers) const
|
||||||
std::vector<IntersectionLines>* lines, std::vector<Polygons>* layers) const
|
|
||||||
{
|
{
|
||||||
//std::cout << "THREAD STARTED: " << boost::this_thread::get_id() << std::endl;
|
this->make_loops((*lines)[i], &(*layers)[i]);
|
||||||
|
|
||||||
while (true) {
|
|
||||||
size_t layer_id;
|
|
||||||
{
|
|
||||||
boost::lock_guard<boost::mutex> l(*queue_mutex);
|
|
||||||
if (queue->empty()) return;
|
|
||||||
layer_id = queue->front();
|
|
||||||
queue->pop();
|
|
||||||
}
|
|
||||||
//std::cout << " Layer " << layer_id << " (" << boost::this_thread::get_id() << ")" << std::endl;
|
|
||||||
this->make_loops((*lines)[layer_id], &(*layers)[layer_id]);
|
|
||||||
boost::this_thread::interruption_point();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "libslic3r.h"
|
#include "libslic3r.h"
|
||||||
#include <admesh/stl.h>
|
#include <admesh/stl.h>
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include "BoundingBox.hpp"
|
#include "BoundingBox.hpp"
|
||||||
@ -101,10 +100,8 @@ class TriangleMeshSlicer
|
|||||||
typedef std::vector< std::vector<int> > t_facets_edges;
|
typedef std::vector< std::vector<int> > t_facets_edges;
|
||||||
t_facets_edges facets_edges;
|
t_facets_edges facets_edges;
|
||||||
stl_vertex* v_scaled_shared;
|
stl_vertex* v_scaled_shared;
|
||||||
void _slice_do(std::queue<size_t>* queue, boost::mutex* queue_mutex,
|
void _slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex, const std::vector<float> &z) const;
|
||||||
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_do(std::queue<size_t>* queue, boost::mutex* queue_mutex,
|
|
||||||
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;
|
||||||
|
@ -4,10 +4,13 @@
|
|||||||
// this needs to be included early for MSVC (listing it in Build.PL is not enough)
|
// this needs to be included early for MSVC (listing it in Build.PL is not enough)
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <queue>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <vector>
|
||||||
|
#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.31.6"
|
||||||
@ -40,13 +43,6 @@
|
|||||||
typedef long coord_t;
|
typedef long coord_t;
|
||||||
typedef double coordf_t;
|
typedef double coordf_t;
|
||||||
|
|
||||||
namespace Slic3r {
|
|
||||||
|
|
||||||
enum Axis { X=0, Y, Z };
|
|
||||||
|
|
||||||
}
|
|
||||||
using namespace Slic3r;
|
|
||||||
|
|
||||||
/* Implementation of CONFESS("foo"): */
|
/* Implementation of CONFESS("foo"): */
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define CONFESS(...) confess_at(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
|
#define CONFESS(...) confess_at(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
|
||||||
@ -91,4 +87,54 @@ inline std::string debug_out_path(const char *name, ...)
|
|||||||
// Write slices as SVG images into out directory during the 2D processing of the slices.
|
// Write slices as SVG images into out directory during the 2D processing of the slices.
|
||||||
// #define SLIC3R_DEBUG_SLICE_PROCESSING
|
// #define SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
enum Axis { X=0, Y, Z };
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline void append_to(std::vector<T> &dst, const std::vector<T> &src)
|
||||||
|
{
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
boost::mutex queue_mutex;
|
||||||
|
boost::thread_group workers;
|
||||||
|
for (int i = 0; i < threads_count; i++)
|
||||||
|
workers.add_thread(new boost::thread(&_parallelize_do<T>, &queue, &queue_mutex, func));
|
||||||
|
workers.join_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user