From eff53d4dba01e62e35b09152fc3525c10e5d72f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C5=A0ach?= Date: Wed, 10 Jan 2024 13:44:51 +0100 Subject: [PATCH] Add option cmd option to limit the number of threads --- src/PrusaSlicer.cpp | 8 +++++++- src/libslic3r/PrintConfig.cpp | 5 +++++ src/libslic3r/Thread.cpp | 9 ++++----- src/libslic3r/Utils.hpp | 3 ++- src/libslic3r/utils.cpp | 6 +++--- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index a07256fd7b..04b481bc42 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -817,7 +817,13 @@ bool CLI::setup(int argc, char **argv) if (opt_loglevel != 0) set_logging_level(opt_loglevel->value); } - + + { + const ConfigOptionInt *opt_threads = m_config.opt("threads"); + if (opt_threads != nullptr) + thread_count = opt_threads->value; + } + //FIXME Validating at this stage most likely does not make sense, as the config is not fully initialized yet. std::string validity = m_config.validate(); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 88ba446eba..02e824efe6 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -5066,6 +5066,11 @@ CLIMiscConfigDef::CLIMiscConfigDef() def->label = L("Data directory"); def->tooltip = L("Load and store settings at the given directory. This is useful for maintaining different profiles or including configurations from a network storage."); + def = this->add("threads", coInt); + def->label = L("Maximum number of threads"); + def->tooltip = L("Sets the maximum number of threads the slicing process will use. If not defined, slic3r will decide."); + def->min = 1; + def = this->add("loglevel", coInt); def->label = L("Logging level"); def->tooltip = L("Sets logging sensitivity. 0:fatal, 1:error, 2:warning, 3:info, 4:debug, 5:trace\n" diff --git a/src/libslic3r/Thread.cpp b/src/libslic3r/Thread.cpp index 338182e026..789e51da6e 100644 --- a/src/libslic3r/Thread.cpp +++ b/src/libslic3r/Thread.cpp @@ -235,12 +235,11 @@ void name_tbb_thread_pool_threads_set_locale() // const size_t nthreads_hw = std::thread::hardware_concurrency(); const size_t nthreads_hw = tbb::this_task_arena::max_concurrency(); size_t nthreads = nthreads_hw; + if (thread_count) { + nthreads = std::min(nthreads_hw, *thread_count); + } -#if 0 - // Shiny profiler is not thread safe, thus disable parallelization. - disable_multi_threading(); - nthreads = 1; -#endif + enforce_thread_count(nthreads); size_t nthreads_running(0); std::condition_variable cv; diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 4b4be4c3ee..c9ee17235d 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -21,6 +21,7 @@ namespace boost { namespace filesystem { class directory_entry; }} namespace Slic3r { +inline std::optional thread_count; extern void set_logging_level(unsigned int level); extern unsigned get_logging_level(); // Format memory allocated, separate thousands by comma. @@ -29,7 +30,7 @@ extern std::string format_memsize_MB(size_t n); // The string is non-empty if the loglevel >= info (3) or ignore_loglevel==true. // Latter is used to get the memory info from SysInfoDialog. extern std::string log_memory_info(bool ignore_loglevel = false); -extern void disable_multi_threading(); +extern void enforce_thread_count(std::size_t count); // Returns the size of physical memory (RAM) in bytes. extern size_t total_physical_memory(); diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 7062c2b89d..08f9d430d8 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -123,15 +123,15 @@ unsigned get_logging_level() } } -void disable_multi_threading() +void enforce_thread_count(const std::size_t count) { // Disable parallelization to simplify debugging. #ifdef TBB_HAS_GLOBAL_CONTROL { - static tbb::global_control gc(tbb::global_control::max_allowed_parallelism, 1); + static tbb::global_control gc(tbb::global_control::max_allowed_parallelism, count); } #else // TBB_HAS_GLOBAL_CONTROL - static tbb::task_scheduler_init *tbb_init = new tbb::task_scheduler_init(1); + static tbb::task_scheduler_init *tbb_init = new tbb::task_scheduler_init(count); UNUSED(tbb_init); #endif // TBB_HAS_GLOBAL_CONTROL }