From fa0abac9522f0a3efbb628ad34467b994fbfc409 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 21 Jun 2023 17:31:02 +0200 Subject: [PATCH 1/3] Optimization: measurement tries to save some reallocations --- src/libslic3r/Measure.cpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index 08c17df47b..6e04acb967 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -190,6 +190,7 @@ void MeasuringImpl::update_planes() //const Halfedge_index he_orig = he; m_planes[plane_id].borders.emplace_back(); std::vector& last_border = m_planes[plane_id].borders.back(); + last_border.reserve(4); last_border.emplace_back(sm.point(sm.source(he)).cast()); //Vertex_index target = sm.target(he); const Halfedge_index he_start = he; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index c2ab108667..53cc85a4e3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -96,6 +96,8 @@ static GLModel::Geometry init_plane_data(const indexed_triangle_set& its, const { GLModel::Geometry init_data; init_data.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3N3 }; + init_data.reserve_indices(3 * triangle_indices.size()); + init_data.reserve_vertices(3 * triangle_indices.size()); unsigned int i = 0; for (int idx : triangle_indices) { const Vec3f& v0 = its.vertices[its.indices[idx][0]]; @@ -1036,10 +1038,10 @@ void GLGizmoMeasure::update_if_needed() { auto update_plane_models_cache = [this](const indexed_triangle_set& its) { m_plane_models_cache.clear(); + m_plane_models_cache.resize(m_measuring->get_num_of_planes(), GLModel()); for (int idx = 0; idx < m_measuring->get_num_of_planes(); ++idx) { - m_plane_models_cache.emplace_back(GLModel()); GLModel::Geometry init_data = init_plane_data(its, m_measuring->get_plane_triangle_indices(idx)); - m_plane_models_cache.back().init_from(std::move(init_data)); + m_plane_models_cache[idx].init_from(std::move(init_data)); } }; From 3277bba8c1bf9ac14b7459693dedadd7f654acf1 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 22 Jun 2023 15:33:48 +0200 Subject: [PATCH 2/3] Optimization: further improvements in measurement initialization --- src/libslic3r/Measure.cpp | 62 +++++++++++++----------- src/libslic3r/Measure.hpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 24 ++++++--- 3 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index 6e04acb967..5593362949 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -72,7 +72,7 @@ public: int get_num_of_planes() const; const std::vector& get_plane_triangle_indices(int idx) const; const std::vector& get_plane_features(unsigned int plane_id); - const TriangleMesh& get_mesh() const; + const indexed_triangle_set& get_its() const; private: void update_planes(); @@ -80,7 +80,7 @@ private: std::vector m_planes; std::vector m_face_to_plane; - TriangleMesh m_mesh; + indexed_triangle_set m_its; }; @@ -89,7 +89,7 @@ private: MeasuringImpl::MeasuringImpl(const indexed_triangle_set& its) -: m_mesh(its) +: m_its(its) { update_planes(); @@ -104,14 +104,12 @@ MeasuringImpl::MeasuringImpl(const indexed_triangle_set& its) void MeasuringImpl::update_planes() { - m_planes.clear(); - // Now we'll go through all the facets and append Points of facets sharing the same normal. // This part is still performed in mesh coordinate system. - const size_t num_of_facets = m_mesh.its.indices.size(); + const size_t num_of_facets = m_its.indices.size(); m_face_to_plane.resize(num_of_facets, size_t(-1)); - const std::vector face_normals = its_face_normals(m_mesh.its); - const std::vector face_neighbors = its_face_neighbors(m_mesh.its); + const std::vector face_normals = its_face_normals(m_its); + const std::vector face_neighbors = its_face_neighbors(m_its); std::vector facet_queue(num_of_facets, 0); int facet_queue_cnt = 0; const stl_normal* normal_ptr = nullptr; @@ -121,6 +119,10 @@ void MeasuringImpl::update_planes() return (std::abs(a(0) - b(0)) < 0.001 && std::abs(a(1) - b(1)) < 0.001 && std::abs(a(2) - b(2)) < 0.001); }; + m_planes.clear(); + m_planes.reserve(num_of_facets / 5); // empty plane data object is quite lightweight, let's save the initial reallocations + + // First go through all the triangles and fill in m_planes vector. For each "plane" // detected on the model, it will contain list of facets that are part of it. // We will also fill in m_face_to_plane, which contains index into m_planes @@ -132,7 +134,7 @@ void MeasuringImpl::update_planes() facet_queue[facet_queue_cnt ++] = seed_facet_idx; normal_ptr = &face_normals[seed_facet_idx]; m_face_to_plane[seed_facet_idx] = m_planes.size(); - m_planes.emplace_back(); + m_planes.emplace_back(); break; } if (seed_facet_idx == num_of_facets) @@ -160,16 +162,21 @@ void MeasuringImpl::update_planes() assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); })); // Now we will walk around each of the planes and save vertices which form the border. - SurfaceMesh sm(m_mesh.its); - for (int plane_id=0; plane_id < int(m_planes.size()); ++plane_id) { - const auto& facets = m_planes[plane_id].facets; - m_planes[plane_id].borders.clear(); + const SurfaceMesh sm(m_its); + + const auto& face_to_plane = m_face_to_plane; + auto& planes = m_planes; + + tbb::parallel_for(tbb::blocked_range(0, m_planes.size()), + [&planes, &face_to_plane, &face_neighbors, &sm](const tbb::blocked_range& range) { + for (size_t plane_id = range.begin(); plane_id != range.end(); ++plane_id) { + + const auto& facets = planes[plane_id].facets; + planes[plane_id].borders.clear(); std::vector> visited(facets.size(), {false, false, false}); - - for (int face_id=0; face_id& last_border = m_planes[plane_id].borders.back(); + planes[plane_id].borders.emplace_back(); + std::vector& last_border = planes[plane_id].borders.back(); last_border.reserve(4); last_border.emplace_back(sm.point(sm.source(he)).cast()); //Vertex_index target = sm.target(he); @@ -211,7 +218,7 @@ void MeasuringImpl::update_planes() // Remember all halfedges we saw to break out of such infinite loops. boost::container::small_vector he_seen; - while ( (int)m_face_to_plane[sm.face(he)] == plane_id && he != he_orig) { + while ( (int)face_to_plane[sm.face(he)] == plane_id && he != he_orig) { he_seen.emplace_back(he); he = sm.next_around_target(he); if (he.is_invalid() || std::find(he_seen.begin(), he_seen.end(), he) != he_seen.end()) @@ -242,7 +249,7 @@ void MeasuringImpl::update_planes() } while (he != he_start); if (last_border.size() == 1) - m_planes[plane_id].borders.pop_back(); + planes[plane_id].borders.pop_back(); else { assert(last_border.front() == last_border.back()); last_border.pop_back(); @@ -252,8 +259,9 @@ void MeasuringImpl::update_planes() continue; // There was no failure. PLANE_FAILURE: - m_planes[plane_id].borders.clear(); - } + planes[plane_id].borders.clear(); + }}); + m_planes.shrink_to_fit(); } @@ -582,9 +590,9 @@ const std::vector& MeasuringImpl::get_plane_features(unsigned in return m_planes[plane_id].surface_features; } -const TriangleMesh& MeasuringImpl::get_mesh() const +const indexed_triangle_set& MeasuringImpl::get_its() const { - return this->m_mesh; + return this->m_its; } @@ -627,9 +635,9 @@ const std::vector& Measuring::get_plane_features(unsigned int pl return priv->get_plane_features(plane_id); } -const TriangleMesh& Measuring::get_mesh() const +const indexed_triangle_set& Measuring::get_its() const { - return priv->get_mesh(); + return priv->get_its(); } const AngleAndEdges AngleAndEdges::Dummy = { 0.0, Vec3d::Zero(), { Vec3d::Zero(), Vec3d::Zero() }, { Vec3d::Zero(), Vec3d::Zero() }, 0.0, true }; diff --git a/src/libslic3r/Measure.hpp b/src/libslic3r/Measure.hpp index a273135ca8..70f446afd9 100644 --- a/src/libslic3r/Measure.hpp +++ b/src/libslic3r/Measure.hpp @@ -109,7 +109,7 @@ public: const std::vector& get_plane_features(unsigned int plane_id) const; // Returns the mesh used for measuring - const TriangleMesh& get_mesh() const; + const indexed_triangle_set& get_its() const; private: std::unique_ptr priv; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 53cc85a4e3..4632f2490a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -14,6 +14,8 @@ #include +#include + #include namespace Slic3r { @@ -650,7 +652,7 @@ void GLGizmoMeasure::on_render() const auto [idx, normal, point] = m_curr_feature->get_plane(); if (m_last_plane_idx != idx) { m_last_plane_idx = idx; - const indexed_triangle_set& its = m_measuring->get_mesh().its; + const indexed_triangle_set& its = m_measuring->get_its(); const std::vector& plane_triangles = m_measuring->get_plane_triangle_indices(idx); GLModel::Geometry init_data = init_plane_data(its, plane_triangles); m_plane.reset(); @@ -1039,10 +1041,18 @@ void GLGizmoMeasure::update_if_needed() auto update_plane_models_cache = [this](const indexed_triangle_set& its) { m_plane_models_cache.clear(); m_plane_models_cache.resize(m_measuring->get_num_of_planes(), GLModel()); - for (int idx = 0; idx < m_measuring->get_num_of_planes(); ++idx) { - GLModel::Geometry init_data = init_plane_data(its, m_measuring->get_plane_triangle_indices(idx)); - m_plane_models_cache[idx].init_from(std::move(init_data)); - } + + auto& plane_models_cache = m_plane_models_cache; + const auto& measuring = m_measuring; + + //for (int idx = 0; idx < m_measuring->get_num_of_planes(); ++idx) { + tbb::parallel_for(tbb::blocked_range(0, m_measuring->get_num_of_planes()), + [&plane_models_cache, &measuring, &its](const tbb::blocked_range& range) { + for (size_t idx = range.begin(); idx != range.end(); ++idx) { + GLModel::Geometry init_data = init_plane_data(its, measuring->get_plane_triangle_indices(idx)); + plane_models_cache[idx].init_from(std::move(init_data)); + } + }); }; auto do_update = [this, update_plane_models_cache](const std::vector& volumes_cache, const Selection& selection) { @@ -1061,8 +1071,8 @@ void GLGizmoMeasure::update_if_needed() } m_measuring.reset(new Measure::Measuring(composite_mesh.its)); - update_plane_models_cache(m_measuring->get_mesh().its); - m_raycaster.reset(new MeshRaycaster(std::make_shared(m_measuring->get_mesh()))); + update_plane_models_cache(m_measuring->get_its()); + m_raycaster.reset(new MeshRaycaster(std::make_shared(composite_mesh))); m_volumes_cache = volumes_cache; }; From 37a088abacb1eeea89350e044840af109e782527 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 23 Jun 2023 12:46:30 +0200 Subject: [PATCH 3/3] Optimization: Parallelize the for loops over individual PrintObjects --- src/libslic3r/Print.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 9ed95dddf3..8f6c65f2f8 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -903,20 +903,29 @@ void Print::process() name_tbb_thread_pool_threads_set_locale(); BOOST_LOG_TRIVIAL(info) << "Starting the slicing process." << log_memory_info(); - for (PrintObject *obj : m_objects) - obj->make_perimeters(); - for (PrintObject *obj : m_objects) - obj->infill(); - for (PrintObject *obj : m_objects) - obj->ironing(); + + tbb::parallel_for(tbb::blocked_range(0, m_objects.size(), 1), [this](const tbb::blocked_range &range) { + for (size_t idx = range.begin(); idx < range.end(); ++idx) { + m_objects[idx]->make_perimeters(); + m_objects[idx]->infill(); + m_objects[idx]->ironing(); + } + }, tbb::simple_partitioner()); + + // The following step writes to m_shared_regions, it should not run in parallel. for (PrintObject *obj : m_objects) obj->generate_support_spots(); // check data from previous step, format the error message(s) and send alert to ui + // this also has to be done sequentially. alert_when_supports_needed(); - for (PrintObject *obj : m_objects) - obj->generate_support_material(); - for (PrintObject *obj : m_objects) - obj->estimate_curled_extrusions(); + + tbb::parallel_for(tbb::blocked_range(0, m_objects.size(), 1), [this](const tbb::blocked_range &range) { + for (size_t idx = range.begin(); idx < range.end(); ++idx) { + m_objects[idx]->generate_support_material(); + m_objects[idx]->estimate_curled_extrusions(); + } + }, tbb::simple_partitioner()); + if (this->set_started(psWipeTower)) { m_wipe_tower_data.clear(); m_tool_ordering.clear();