mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-13 02:28:10 +08:00
Support for naming slicer own threads for debugging.
The following threads are named with this commit: slic3r_main, slic3r_BackgroundSlicingProcess, slic3r_tbbpool_xx_yy where xx is a one based index of the TTB thread and yy is the platform thread ID.
This commit is contained in:
parent
8d59abfdf8
commit
6531061d09
@ -46,6 +46,7 @@
|
|||||||
#include "libslic3r/Format/SL1.hpp"
|
#include "libslic3r/Format/SL1.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/AppConfig.hpp"
|
#include "libslic3r/AppConfig.hpp"
|
||||||
|
#include "libslic3r/Thread.hpp"
|
||||||
|
|
||||||
#include "PrusaSlicer.hpp"
|
#include "PrusaSlicer.hpp"
|
||||||
|
|
||||||
@ -62,6 +63,9 @@ using namespace Slic3r;
|
|||||||
|
|
||||||
int CLI::run(int argc, char **argv)
|
int CLI::run(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
// Mark the main thread for the debugger and for runtime checks.
|
||||||
|
set_current_thread_name("slic3r_main");
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
// On Linux, wxGTK has no support for Wayland, and the app crashes on
|
// On Linux, wxGTK has no support for Wayland, and the app crashes on
|
||||||
// startup if gtk3 is used. This env var has to be set explicitly to
|
// startup if gtk3 is used. This env var has to be set explicitly to
|
||||||
|
@ -201,6 +201,8 @@ add_library(libslic3r STATIC
|
|||||||
Utils.hpp
|
Utils.hpp
|
||||||
Time.cpp
|
Time.cpp
|
||||||
Time.hpp
|
Time.hpp
|
||||||
|
Thread.cpp
|
||||||
|
Thread.hpp
|
||||||
TriangleSelector.cpp
|
TriangleSelector.cpp
|
||||||
TriangleSelector.hpp
|
TriangleSelector.hpp
|
||||||
MTUtils.hpp
|
MTUtils.hpp
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "ShortestPath.hpp"
|
#include "ShortestPath.hpp"
|
||||||
#include "SupportMaterial.hpp"
|
#include "SupportMaterial.hpp"
|
||||||
|
#include "Thread.hpp"
|
||||||
#include "GCode.hpp"
|
#include "GCode.hpp"
|
||||||
#include "GCode/WipeTower.hpp"
|
#include "GCode/WipeTower.hpp"
|
||||||
#include "Utils.hpp"
|
#include "Utils.hpp"
|
||||||
@ -1604,6 +1605,8 @@ void Print::auto_assign_extruders(ModelObject* model_object) const
|
|||||||
// Slicing process, running at a background thread.
|
// Slicing process, running at a background thread.
|
||||||
void Print::process()
|
void Print::process()
|
||||||
{
|
{
|
||||||
|
name_tbb_thread_pool_threads();
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Starting the slicing process." << log_memory_info();
|
BOOST_LOG_TRIVIAL(info) << "Starting the slicing process." << log_memory_info();
|
||||||
for (PrintObject *obj : m_objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->make_perimeters();
|
obj->make_perimeters();
|
||||||
|
@ -1688,12 +1688,6 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||||||
|
|
||||||
m_typed_slices = false;
|
m_typed_slices = false;
|
||||||
|
|
||||||
#ifdef SLIC3R_PROFILE
|
|
||||||
// Disable parallelization so the Shiny profiler works
|
|
||||||
static tbb::task_scheduler_init *tbb_init = nullptr;
|
|
||||||
tbb_init = new tbb::task_scheduler_init(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// 1) Initialize layers and their slice heights.
|
// 1) Initialize layers and their slice heights.
|
||||||
std::vector<float> slice_zs;
|
std::vector<float> slice_zs;
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
#include "Geometry.hpp"
|
#include "Geometry.hpp"
|
||||||
#include "MTUtils.hpp"
|
#include "MTUtils.hpp"
|
||||||
|
#include "Thread.hpp"
|
||||||
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
@ -689,7 +690,10 @@ bool SLAPrint::invalidate_step(SLAPrintStep step)
|
|||||||
|
|
||||||
void SLAPrint::process()
|
void SLAPrint::process()
|
||||||
{
|
{
|
||||||
if(m_objects.empty()) return;
|
if (m_objects.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
name_tbb_thread_pool_threads();
|
||||||
|
|
||||||
// Assumption: at this point the print objects should be populated only with
|
// Assumption: at this point the print objects should be populated only with
|
||||||
// the model objects we have to process and the instances are also filtered
|
// the model objects we have to process and the instances are also filtered
|
||||||
|
158
src/libslic3r/Thread.cpp
Normal file
158
src/libslic3r/Thread.cpp
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include <processthreadsapi.h>
|
||||||
|
#include <boost/nowide/convert.hpp>
|
||||||
|
#else
|
||||||
|
// any posix system
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
#include <tbb/parallel_for.h>
|
||||||
|
#include <tbb/tbb_thread.h>
|
||||||
|
|
||||||
|
#define SLIC3R_THREAD_NAME_WIN32_MODERN
|
||||||
|
|
||||||
|
#include "Thread.hpp"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
#ifdef SLIC3R_THREAD_NAME_WIN32_MODERN
|
||||||
|
|
||||||
|
static void WindowsSetThreadName(HANDLE hThread, const char *thread_name)
|
||||||
|
{
|
||||||
|
size_t len = strlen(thread_name);
|
||||||
|
if (len < 1024) {
|
||||||
|
// Allocate the temp string on stack.
|
||||||
|
wchar_t buf[1024];
|
||||||
|
::SetThreadDescription(hThread, boost::nowide::widen(buf, 1024, thread_name));
|
||||||
|
} else {
|
||||||
|
// Allocate dynamically.
|
||||||
|
::SetThreadDescription(hThread, boost::nowide::widen(thread_name).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // SLIC3R_THREAD_NAME_WIN32_MODERN
|
||||||
|
// use the old way by throwing an exception
|
||||||
|
|
||||||
|
const DWORD MS_VC_EXCEPTION=0x406D1388;
|
||||||
|
|
||||||
|
#pragma pack(push,8)
|
||||||
|
typedef struct tagTHREADNAME_INFO
|
||||||
|
{
|
||||||
|
DWORD dwType; // Must be 0x1000.
|
||||||
|
LPCSTR szName; // Pointer to name (in user addr space).
|
||||||
|
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||||
|
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||||
|
} THREADNAME_INFO;
|
||||||
|
#pragma pack(pop)
|
||||||
|
static void WindowsSetThreadName(HANDLE hThread, const char *thread_name)
|
||||||
|
{
|
||||||
|
THREADNAME_INFO info;
|
||||||
|
info.dwType = 0x1000;
|
||||||
|
info.szName = threadName;
|
||||||
|
info.dwThreadID = ::GetThreadId(hThread);
|
||||||
|
info.dwFlags = 0;
|
||||||
|
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||||
|
}
|
||||||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SLIC3R_THREAD_NAME_WIN32_MODERN
|
||||||
|
|
||||||
|
// posix
|
||||||
|
void set_thread_name(std::thread &thread, const char *thread_name)
|
||||||
|
{
|
||||||
|
WindowsSetThreadName(static_cast<HANDLE>(thread.native_handle()), thread_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_thread_name(boost::thread &thread, const char *thread_name)
|
||||||
|
{
|
||||||
|
WindowsSetThreadName(static_cast<HANDLE>(thread.native_handle()), thread_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_current_thread_name(const char *thread_name)
|
||||||
|
{
|
||||||
|
WindowsSetThreadName(::GetCurrentThread(), thread_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // _WIN32
|
||||||
|
|
||||||
|
// posix
|
||||||
|
void set_thread_name(std::thread &thread, const char *thread_name)
|
||||||
|
{
|
||||||
|
pthread_setname_np(thread->native_handle(), thread_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_thread_name(boost::thread &thread, const char *thread_name)
|
||||||
|
{
|
||||||
|
pthread_setname_np(thread->native_handle(), thread_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_current_thread_name(const char *thread_name)
|
||||||
|
{
|
||||||
|
set_thread_name(pthread_self(), thread_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
// Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID.
|
||||||
|
void name_tbb_thread_pool_threads()
|
||||||
|
{
|
||||||
|
static bool initialized = false;
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
initialized = true;
|
||||||
|
|
||||||
|
const size_t nthreads_hw = std::thread::hardware_concurrency();
|
||||||
|
size_t nthreads = nthreads_hw;
|
||||||
|
|
||||||
|
#ifdef SLIC3R_PROFILE
|
||||||
|
// Shiny profiler is not thread safe, thus disable parallelization.
|
||||||
|
nthreads = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (nthreads != nthreads_hw) {
|
||||||
|
static tbb::task_scheduler_init *tbb_init = nullptr;
|
||||||
|
tbb_init = new tbb::task_scheduler_init(nthreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::atomic<size_t> nthreads_running(0);
|
||||||
|
std::condition_variable cv;
|
||||||
|
std::mutex cv_m;
|
||||||
|
auto master_thread_id = tbb::this_tbb_thread::get_id();
|
||||||
|
tbb::parallel_for(
|
||||||
|
tbb::blocked_range<size_t>(0, nthreads, 1),
|
||||||
|
[&nthreads_running, nthreads, &master_thread_id, &cv, &cv_m](const tbb::blocked_range<size_t> &range) {
|
||||||
|
assert(range.begin() + 1 == range.end());
|
||||||
|
if (nthreads_running.fetch_add(1) + 1 == nthreads) {
|
||||||
|
// All threads are spinning.
|
||||||
|
// Wake them up.
|
||||||
|
cv.notify_all();
|
||||||
|
} else {
|
||||||
|
// Wait for the last thread to wake the others.
|
||||||
|
std::unique_lock<std::mutex> lk(cv_m);
|
||||||
|
cv.wait(lk, [&nthreads_running, nthreads]{return nthreads_running == nthreads;});
|
||||||
|
}
|
||||||
|
auto thread_id = tbb::this_tbb_thread::get_id();
|
||||||
|
if (thread_id == master_thread_id) {
|
||||||
|
// The calling thread runs the 0'th task.
|
||||||
|
assert(range.begin() == 0);
|
||||||
|
} else {
|
||||||
|
assert(range.begin() > 0);
|
||||||
|
std::ostringstream name;
|
||||||
|
name << "slic3r_tbbpool_" << range.begin() << "_" << thread_id;
|
||||||
|
set_current_thread_name(name.str());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
src/libslic3r/Thread.hpp
Normal file
40
src/libslic3r/Thread.hpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef GUI_THREAD_HPP
|
||||||
|
#define GUI_THREAD_HPP
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <thread>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
void set_thread_name(std::thread &thread, const char *thread_name);
|
||||||
|
inline void set_thread_name(std::thread &thread, const std::string &thread_name) { set_thread_name(thread, thread_name.c_str()); }
|
||||||
|
void set_thread_name(boost::thread &thread, const char *thread_name);
|
||||||
|
inline void set_thread_name(boost::thread &thread, const std::string &thread_name) { set_thread_name(thread, thread_name.c_str()); }
|
||||||
|
void set_current_thread_name(const char *thread_name);
|
||||||
|
inline void set_current_thread_name(const std::string &thread_name) { set_current_thread_name(thread_name.c_str()); }
|
||||||
|
|
||||||
|
// To be called somewhere before the TBB threads are spinned for the first time, to
|
||||||
|
// give them names recognizible in the debugger.
|
||||||
|
void name_tbb_thread_pool_threads();
|
||||||
|
|
||||||
|
template<class Fn>
|
||||||
|
inline boost::thread create_thread(boost::thread::attributes &attrs, Fn &&fn)
|
||||||
|
{
|
||||||
|
// Duplicating the stack allocation size of Thread Building Block worker
|
||||||
|
// threads of the thread pool: allocate 4MB on a 64bit system, allocate 2MB
|
||||||
|
// on a 32bit system by default.
|
||||||
|
|
||||||
|
attrs.set_stack_size((sizeof(void*) == 4) ? (2048 * 1024) : (4096 * 1024));
|
||||||
|
return boost::thread{attrs, std::forward<Fn>(fn)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Fn> inline boost::thread create_thread(Fn &&fn)
|
||||||
|
{
|
||||||
|
boost::thread::attributes attrs;
|
||||||
|
return create_thread(attrs, std::forward<Fn>(fn));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GUI_THREAD_HPP
|
@ -204,7 +204,6 @@ set(SLIC3R_GUI_SOURCES
|
|||||||
Utils/UndoRedo.hpp
|
Utils/UndoRedo.hpp
|
||||||
Utils/HexFile.cpp
|
Utils/HexFile.cpp
|
||||||
Utils/HexFile.hpp
|
Utils/HexFile.hpp
|
||||||
Utils/Thread.hpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "libslic3r/GCode/PreviewData.hpp"
|
#include "libslic3r/GCode/PreviewData.hpp"
|
||||||
#endif // !ENABLE_GCODE_VIEWER
|
#endif // !ENABLE_GCODE_VIEWER
|
||||||
#include "libslic3r/Format/SL1.hpp"
|
#include "libslic3r/Format/SL1.hpp"
|
||||||
|
#include "libslic3r/Thread.hpp"
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -36,7 +37,6 @@
|
|||||||
#include "I18N.hpp"
|
#include "I18N.hpp"
|
||||||
#include "RemovableDriveManager.hpp"
|
#include "RemovableDriveManager.hpp"
|
||||||
|
|
||||||
#include "slic3r/Utils/Thread.hpp"
|
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
@ -224,6 +224,9 @@ void BackgroundSlicingProcess::process_sla()
|
|||||||
|
|
||||||
void BackgroundSlicingProcess::thread_proc()
|
void BackgroundSlicingProcess::thread_proc()
|
||||||
{
|
{
|
||||||
|
set_current_thread_name("slic3r_BackgroundSlicingProcess");
|
||||||
|
name_tbb_thread_pool_threads();
|
||||||
|
|
||||||
assert(m_print != nullptr);
|
assert(m_print != nullptr);
|
||||||
assert(m_print == m_fff_print || m_print == m_sla_print);
|
assert(m_print == m_fff_print || m_print == m_sla_print);
|
||||||
std::unique_lock<std::mutex> lck(m_mutex);
|
std::unique_lock<std::mutex> lck(m_mutex);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Job.hpp"
|
#include "Job.hpp"
|
||||||
|
#include <libslic3r/Thread.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
#include <slic3r/Utils/Thread.hpp>
|
#include "libslic3r/libslic3r.h"
|
||||||
|
|
||||||
#include <slic3r/GUI/I18N.hpp>
|
#include <slic3r/GUI/I18N.hpp>
|
||||||
|
|
||||||
#include "ProgressIndicator.hpp"
|
#include "ProgressIndicator.hpp"
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
#ifndef GUI_THREAD_HPP
|
|
||||||
#define GUI_THREAD_HPP
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
namespace Slic3r {
|
|
||||||
|
|
||||||
template<class Fn>
|
|
||||||
inline boost::thread create_thread(boost::thread::attributes &attrs, Fn &&fn)
|
|
||||||
{
|
|
||||||
// Duplicating the stack allocation size of Thread Building Block worker
|
|
||||||
// threads of the thread pool: allocate 4MB on a 64bit system, allocate 2MB
|
|
||||||
// on a 32bit system by default.
|
|
||||||
|
|
||||||
attrs.set_stack_size((sizeof(void*) == 4) ? (2048 * 1024) : (4096 * 1024));
|
|
||||||
return boost::thread{attrs, std::forward<Fn>(fn)};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Fn> inline boost::thread create_thread(Fn &&fn)
|
|
||||||
{
|
|
||||||
boost::thread::attributes attrs;
|
|
||||||
return create_thread(attrs, std::forward<Fn>(fn));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // GUI_THREAD_HPP
|
|
Loading…
x
Reference in New Issue
Block a user