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
12 changed files with 219 additions and 38 deletions
|
@ -46,6 +46,7 @@
|
|||
#include "libslic3r/Format/SL1.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "libslic3r/Thread.hpp"
|
||||
|
||||
#include "PrusaSlicer.hpp"
|
||||
|
||||
|
@ -62,6 +63,9 @@ using namespace Slic3r;
|
|||
|
||||
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__
|
||||
// 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
|
||||
|
|
|
@ -201,6 +201,8 @@ add_library(libslic3r STATIC
|
|||
Utils.hpp
|
||||
Time.cpp
|
||||
Time.hpp
|
||||
Thread.cpp
|
||||
Thread.hpp
|
||||
TriangleSelector.cpp
|
||||
TriangleSelector.hpp
|
||||
MTUtils.hpp
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "I18N.hpp"
|
||||
#include "ShortestPath.hpp"
|
||||
#include "SupportMaterial.hpp"
|
||||
#include "Thread.hpp"
|
||||
#include "GCode.hpp"
|
||||
#include "GCode/WipeTower.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
@ -1604,6 +1605,8 @@ void Print::auto_assign_extruders(ModelObject* model_object) const
|
|||
// Slicing process, running at a background thread.
|
||||
void Print::process()
|
||||
{
|
||||
name_tbb_thread_pool_threads();
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Starting the slicing process." << log_memory_info();
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->make_perimeters();
|
||||
|
|
|
@ -1688,12 +1688,6 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
|
|||
|
||||
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.
|
||||
std::vector<float> slice_zs;
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "ClipperUtils.hpp"
|
||||
#include "Geometry.hpp"
|
||||
#include "MTUtils.hpp"
|
||||
#include "Thread.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
#include <numeric>
|
||||
|
@ -689,7 +690,10 @@ bool SLAPrint::invalidate_step(SLAPrintStep step)
|
|||
|
||||
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
|
||||
// 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/HexFile.cpp
|
||||
Utils/HexFile.hpp
|
||||
Utils/Thread.hpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libslic3r/GCode/PreviewData.hpp"
|
||||
#endif // !ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/Format/SL1.hpp"
|
||||
#include "libslic3r/Thread.hpp"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
#include <cassert>
|
||||
|
@ -36,7 +37,6 @@
|
|||
#include "I18N.hpp"
|
||||
#include "RemovableDriveManager.hpp"
|
||||
|
||||
#include "slic3r/Utils/Thread.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
@ -224,6 +224,9 @@ void BackgroundSlicingProcess::process_sla()
|
|||
|
||||
void BackgroundSlicingProcess::thread_proc()
|
||||
{
|
||||
set_current_thread_name("slic3r_BackgroundSlicingProcess");
|
||||
name_tbb_thread_pool_threads();
|
||||
|
||||
assert(m_print != nullptr);
|
||||
assert(m_print == m_fff_print || m_print == m_sla_print);
|
||||
std::unique_lock<std::mutex> lck(m_mutex);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "Job.hpp"
|
||||
#include <libslic3r/Thread.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
#include <atomic>
|
||||
|
||||
#include <slic3r/Utils/Thread.hpp>
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
#include <slic3r/GUI/I18N.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…
Reference in a new issue