Import Geant4 11.1.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2022-07-01 10:44:02 +02:00
parent b3bf75a2a1
commit c07cea1fe0
2172 changed files with 183300 additions and 123938 deletions
+123
View File
@@ -0,0 +1,123 @@
# -------------------------------------------------------------------------------------- #
# General
# -------------------------------------------------------------------------------------- #
# Locate sources and headers for this project - headers are included so they will show up
# in IDEs
file(GLOB_RECURSE ptl_headers ${PROJECT_SOURCE_DIR}/include/PTL/*.hh
${PROJECT_SOURCE_DIR}/include/PTL/*.icc)
file(GLOB_RECURSE ptl_sources ${CMAKE_CURRENT_LIST_DIR}/*.cc)
# -------------------------------------------------------------------------------------- #
# Config, Version
# -------------------------------------------------------------------------------------- #
configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/Config.hh.in
${CMAKE_CURRENT_BINARY_DIR}/PTL/Config.hh @ONLY)
list(APPEND ptl_headers ${CMAKE_CURRENT_BINARY_DIR}/PTL/Config.hh)
configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/Version.hh.in
${CMAKE_CURRENT_BINARY_DIR}/PTL/Version.hh @ONLY)
list(APPEND ptl_headers ${CMAKE_CURRENT_BINARY_DIR}/PTL/Version.hh)
# -------------------------------------------------------------------------------------- #
# PTL Library
# -------------------------------------------------------------------------------------- #
if(BUILD_OBJECT_LIBS)
ptl_build_library(
TYPE OBJECT
TARGET_NAME ptl-object
OUTPUT_NAME G4ptl-object
SOURCES ${ptl_headers} ${ptl_sources})
target_link_libraries(ptl-object PUBLIC Threads::Threads)
if(PTL_USE_TBB)
target_link_libraries(ptl-object PUBLIC TBB::tbb)
endif()
target_include_directories(
ptl-object PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/source>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
endif()
if(BUILD_SHARED_LIBS)
ptl_build_library(
TYPE SHARED
TARGET_NAME ptl-shared
OUTPUT_NAME G4ptl
SOURCES ${ptl_headers} ${ptl_sources})
target_link_libraries(ptl-shared PUBLIC Threads::Threads)
if(PTL_USE_TBB)
target_link_libraries(ptl-shared PUBLIC TBB::tbb)
endif()
target_compile_definitions(ptl-shared PUBLIC PTL_BUILD_DLL)
target_include_directories(
ptl-shared
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
$<INSTALL_INTERFACE:${PTL_INSTALL_INCLUDEDIR}>)
if(PTL_USE_SANITIZER AND NOT ("${PTL_SANITIZER_TYPE}" STREQUAL "leak"))
string(REPLACE " " ";" _sanitize_args "${ptl_sanitize_args}")
set_target_properties(ptl-shared PROPERTIES INTERFACE_LINK_OPTIONS
"${_sanitize_args}")
endif()
export(
TARGETS ptl-shared
NAMESPACE PTL::
FILE ${PROJECT_BINARY_DIR}/ptl-shared.cmake)
endif()
if(BUILD_STATIC_LIBS)
ptl_build_library(
TYPE STATIC
TARGET_NAME ptl-static
OUTPUT_NAME $<IF:$<PLATFORM_ID:Windows>,G4ptl-static,G4ptl>
SOURCES ${ptl_headers} ${ptl_sources})
target_link_libraries(ptl-static PUBLIC Threads::Threads)
if(PTL_USE_TBB)
target_link_libraries(ptl-static PUBLIC TBB::tbb)
endif()
target_include_directories(
ptl-static
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
$<INSTALL_INTERFACE:${PTL_INSTALL_INCLUDEDIR}>)
export(
TARGETS ptl-static
NAMESPACE PTL::
FILE ${PROJECT_BINARY_DIR}/ptl-static.cmake)
endif()
# -------------------------------------------------------------------------------------- #
# Installation
# -------------------------------------------------------------------------------------- #
if(PTL_INSTALL_CONFIG)
# install export
install(
EXPORT ${PROJECT_NAME}Targets
NAMESPACE PTL::
DESTINATION ${PTL_INSTALL_CMAKEDIR}
COMPONENT Development)
endif()
if(PTL_INSTALL_HEADERS)
# headers
install(
FILES ${ptl_headers}
DESTINATION ${PTL_INSTALL_INCLUDEDIR}/PTL
COMPONENT Development)
endif()
+7 -2
View File
@@ -52,8 +52,13 @@ task_group_counter()
ThreadPool*
get_default_threadpool()
{
if(TaskRunManager::GetMasterRunManager())
return TaskRunManager::GetMasterRunManager()->GetThreadPool();
auto* mrm = TaskRunManager::GetMasterRunManager();
if(mrm)
{
if(!mrm->GetThreadPool())
mrm->Initialize();
return mrm->GetThreadPool();
}
return nullptr;
}
+27 -8
View File
@@ -36,11 +36,24 @@ using namespace PTL;
//======================================================================================//
TaskRunManager::pointer&
TaskRunManager::GetPrivateMasterRunManager()
{
static pointer _instance = nullptr;
return _instance;
}
//======================================================================================//
TaskRunManager::pointer&
TaskRunManager::GetPrivateMasterRunManager(bool init, bool useTBB)
{
static pointer _instance = (init) ? new TaskRunManager(useTBB) : nullptr;
return _instance;
auto& _v = GetPrivateMasterRunManager();
if(!init)
return _v;
if(!_v)
_v = new TaskRunManager(useTBB);
return _v;
}
//======================================================================================//
@@ -48,8 +61,8 @@ TaskRunManager::GetPrivateMasterRunManager(bool init, bool useTBB)
TaskRunManager*
TaskRunManager::GetMasterRunManager(bool useTBB)
{
static pointer& _instance = GetPrivateMasterRunManager(true, useTBB);
return _instance;
auto& _v = GetPrivateMasterRunManager(true, useTBB);
return _v;
}
//======================================================================================//
@@ -65,10 +78,8 @@ TaskRunManager::GetInstance(bool useTBB)
TaskRunManager::TaskRunManager(bool useTBB)
: m_workers(std::thread::hardware_concurrency())
{
if(!GetPrivateMasterRunManager(false))
{
GetPrivateMasterRunManager(false) = this;
}
if(!GetPrivateMasterRunManager())
GetPrivateMasterRunManager() = this;
#if defined(PTL_USE_TBB)
auto _useTBB = GetEnv<bool>("PTL_FORCE_TBB", GetEnv<bool>("FORCE_TBB", useTBB));
@@ -83,6 +94,14 @@ TaskRunManager::TaskRunManager(bool useTBB)
//======================================================================================//
TaskRunManager::~TaskRunManager()
{
if(GetPrivateMasterRunManager() == this)
GetPrivateMasterRunManager() = nullptr;
}
//======================================================================================//
void
TaskRunManager::Initialize(uint64_t n)
{
+282 -65
View File
@@ -31,27 +31,18 @@
#include "PTL/ThreadPool.hh"
#include "PTL/Globals.hh"
#include "PTL/ThreadData.hh"
#include "PTL/Threading.hh"
#include "PTL/UserTaskQueue.hh"
#include "PTL/Utility.hh"
#include "PTL/VUserTaskQueue.hh"
#include <cstdlib>
#include <thread>
using namespace PTL;
//======================================================================================//
inline intmax_t
ncores()
{
return static_cast<intmax_t>(Thread::hardware_concurrency());
}
//======================================================================================//
ThreadPool::thread_id_map_t ThreadPool::f_thread_ids;
//======================================================================================//
namespace
{
ThreadData*&
@@ -63,7 +54,58 @@ thread_data()
//======================================================================================//
bool ThreadPool::f_use_tbb = false;
ThreadPool::thread_id_map_t&
ThreadPool::f_thread_ids()
{
static auto _v = thread_id_map_t{};
return _v;
}
//======================================================================================//
bool&
ThreadPool::f_use_tbb()
{
static bool _v = GetEnv<bool>("PTL_USE_TBB", false);
return _v;
}
//======================================================================================//
bool&
ThreadPool::f_use_cpu_affinity()
{
static bool _v = GetEnv<bool>("PTL_CPU_AFFINITY", false);
return _v;
}
//======================================================================================//
int&
ThreadPool::f_thread_priority()
{
static int _v = GetEnv<int>("PTL_THREAD_PRIORITY", 0);
return _v;
}
//======================================================================================//
int&
ThreadPool::f_verbose()
{
static int _v = GetEnv<int>("PTL_VERBOSE", 0);
return _v;
}
//======================================================================================//
ThreadPool::size_type&
ThreadPool::f_default_pool_size()
{
static size_type _v =
GetEnv<size_type>("PTL_NUM_THREADS", Thread::hardware_concurrency());
return _v;
}
//======================================================================================//
// static member function that calls the member function we want the thread to
@@ -71,14 +113,20 @@ bool ThreadPool::f_use_tbb = false;
void
ThreadPool::start_thread(ThreadPool* tp, thread_data_t* _data, intmax_t _idx)
{
if(tp->get_verbose() > 0)
{
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] Starting thread " << _idx << "..." << std::endl;
}
auto _thr_data = std::make_shared<ThreadData>(tp);
{
AutoLock lock(TypeMutex<ThreadPool>(), std::defer_lock);
if(!lock.owns_lock())
lock.lock();
if(_idx < 0)
_idx = f_thread_ids.size();
f_thread_ids[std::this_thread::get_id()] = _idx;
_idx = f_thread_ids().size();
f_thread_ids()[std::this_thread::get_id()] = _idx;
Threading::SetThreadId(_idx);
_data->emplace_back(_thr_data);
}
@@ -86,6 +134,13 @@ ThreadPool::start_thread(ThreadPool* tp, thread_data_t* _data, intmax_t _idx)
tp->record_entry();
tp->execute_thread(thread_data()->current_queue);
tp->record_exit();
if(tp->get_verbose() > 0)
{
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] Thread " << _idx << " terminating..."
<< std::endl;
}
}
//======================================================================================//
@@ -93,7 +148,7 @@ ThreadPool::start_thread(ThreadPool* tp, thread_data_t* _data, intmax_t _idx)
bool
ThreadPool::using_tbb()
{
return f_use_tbb;
return f_use_tbb();
}
//======================================================================================//
@@ -102,7 +157,19 @@ void
ThreadPool::set_use_tbb(bool enable)
{
#if defined(PTL_USE_TBB)
f_use_tbb = enable;
f_use_tbb() = enable;
#else
ConsumeParameters<bool>(enable);
#endif
}
//======================================================================================//
// static member function that initialized tbb library
void
ThreadPool::set_default_use_cpu_affinity(bool enable)
{
#if defined(PTL_USE_TBB)
f_use_cpu_affinity() = enable;
#else
ConsumeParameters<bool>(enable);
#endif
@@ -113,7 +180,31 @@ ThreadPool::set_use_tbb(bool enable)
const ThreadPool::thread_id_map_t&
ThreadPool::get_thread_ids()
{
return f_thread_ids;
return f_thread_ids();
}
//======================================================================================//
uintmax_t
ThreadPool::get_thread_id(ThreadId _tid)
{
uintmax_t _idx = 0;
{
AutoLock lock(TypeMutex<ThreadPool>(), std::defer_lock);
if(!lock.owns_lock())
lock.lock();
auto itr = f_thread_ids().find(_tid);
if(itr == f_thread_ids().end())
{
_idx = f_thread_ids().size();
f_thread_ids()[_tid] = _idx;
}
else
{
_idx = itr->second;
}
}
return _idx;
}
//======================================================================================//
@@ -121,42 +212,90 @@ ThreadPool::get_thread_ids()
uintmax_t
ThreadPool::get_this_thread_id()
{
auto _tid = ThisThread::get_id();
{
AutoLock lock(TypeMutex<ThreadPool>(), std::defer_lock);
if(!lock.owns_lock())
lock.lock();
if(f_thread_ids.find(_tid) == f_thread_ids.end())
{
auto _idx = f_thread_ids.size();
f_thread_ids[_tid] = _idx;
}
}
return f_thread_ids[_tid];
return get_thread_id(ThisThread::get_id());
}
//======================================================================================//
ThreadPool::ThreadPool(const size_type& pool_size, VUserTaskQueue* task_queue,
bool _use_affinity, affinity_func_t _affinity_func)
: m_use_affinity(_use_affinity)
, m_pool_state(std::make_shared<std::atomic_short>(thread_pool::state::NONINIT))
, m_task_queue(task_queue)
, m_affinity_func(std::move(_affinity_func))
uintmax_t
ThreadPool::add_thread_id(ThreadId _tid)
{
AutoLock lock(TypeMutex<ThreadPool>(), std::defer_lock);
if(!lock.owns_lock())
lock.lock();
if(f_thread_ids().find(_tid) == f_thread_ids().end())
{
auto _idx = f_thread_ids().size();
f_thread_ids()[_tid] = _idx;
Threading::SetThreadId(_idx);
}
return f_thread_ids().at(_tid);
}
//======================================================================================//
ThreadPool::Config::Config(bool _init, bool _use_tbb, bool _use_affinity, int _verbose,
int _prio, size_type _size, VUserTaskQueue* _task_queue,
affinity_func_t _affinity_func, initialize_func_t _init_func,
finalize_func_t _fini_func)
: init{ _init }
, use_tbb{ _use_tbb }
, use_affinity{ _use_affinity }
, verbose{ _verbose }
, priority{ _prio }
, pool_size{ _size }
, task_queue{ _task_queue }
, set_affinity{ std::move(_affinity_func) }
, initializer{ std::move(_init_func) }
, finalizer{ std::move(_fini_func) }
{}
//======================================================================================//
ThreadPool::ThreadPool(const Config& _cfg)
: m_use_affinity{ _cfg.use_affinity }
, m_tbb_tp{ _cfg.use_tbb }
, m_verbose{ _cfg.verbose }
, m_priority{ _cfg.priority }
, m_pool_state{ std::make_shared<std::atomic_short>(thread_pool::state::NONINIT) }
, m_task_queue{ _cfg.task_queue }
, m_init_func{ _cfg.initializer }
, m_fini_func{ _cfg.finalizer }
, m_affinity_func{ _cfg.set_affinity }
{
auto master_id = get_this_thread_id();
if(master_id != 0 && m_verbose > 1)
std::cerr << "ThreadPool created on non-master slave" << std::endl;
{
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] ThreadPool created on worker thread" << std::endl;
}
thread_data() = new ThreadData(this);
// initialize after get_this_thread_id so master is zero
this->initialize_threadpool(pool_size);
if(!m_task_queue)
m_task_queue = new UserTaskQueue(m_pool_size);
if(_cfg.init)
this->initialize_threadpool(_cfg.pool_size);
}
ThreadPool::ThreadPool(const size_type& _pool_size, VUserTaskQueue* _task_queue,
bool _use_affinity, affinity_func_t _affinity_func,
initialize_func_t _init_func, finalize_func_t _fini_func)
: ThreadPool{ Config{ true, f_use_tbb(), _use_affinity, f_verbose(), f_thread_priority(),
_pool_size, _task_queue, std::move(_affinity_func),
std::move(_init_func), std::move(_fini_func) } }
{}
ThreadPool::ThreadPool(const size_type& pool_size, initialize_func_t _init_func,
finalize_func_t _fini_func, bool _use_affinity,
affinity_func_t _affinity_func, VUserTaskQueue* task_queue)
: ThreadPool{ pool_size,
task_queue,
_use_affinity,
std::move(_affinity_func),
std::move(_init_func),
std::move(_fini_func) }
{}
//======================================================================================//
ThreadPool::~ThreadPool()
@@ -188,7 +327,25 @@ ThreadPool::is_initialized() const
//======================================================================================//
void
ThreadPool::set_affinity(intmax_t i, Thread& _thread)
ThreadPool::record_entry()
{
if(m_thread_active)
++(*m_thread_active);
}
//======================================================================================//
void
ThreadPool::record_exit()
{
if(m_thread_active)
--(*m_thread_active);
}
//======================================================================================//
void
ThreadPool::set_affinity(intmax_t i, Thread& _thread) const
{
try
{
@@ -196,14 +353,39 @@ ThreadPool::set_affinity(intmax_t i, Thread& _thread)
intmax_t _pin = m_affinity_func(i);
if(m_verbose > 0)
{
std::cout << "Setting pin affinity for thread " << _thread.get_id() << " to "
<< _pin << std::endl;
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] Setting pin affinity for thread "
<< get_thread_id(_thread.get_id()) << " to " << _pin << std::endl;
}
Threading::SetPinAffinity(_pin, native_thread);
} catch(std::runtime_error& e)
{
std::cout << "Error setting pin affinity" << std::endl;
std::cerr << e.what() << std::endl; // issue assigning affinity
std::cerr << "[PTL::ThreadPool] Error setting pin affinity: " << e.what()
<< std::endl;
}
}
//======================================================================================//
void
ThreadPool::set_priority(int _prio, Thread& _thread) const
{
try
{
NativeThread native_thread = _thread.native_handle();
if(m_verbose > 0)
{
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] Setting thread "
<< get_thread_id(_thread.get_id()) << " priority to " << _prio
<< std::endl;
}
Threading::SetThreadPriority(_prio, native_thread);
} catch(std::runtime_error& e)
{
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] Error setting thread priority: " << e.what()
<< std::endl;
}
}
@@ -225,7 +407,7 @@ ThreadPool::initialize_threadpool(size_type proposed_size)
#if defined(PTL_USE_TBB)
//--------------------------------------------------------------------//
// handle tbb task scheduler
if(f_use_tbb || m_tbb_tp)
if(m_tbb_tp)
{
m_tbb_tp = true;
m_pool_size = proposed_size;
@@ -243,14 +425,19 @@ ThreadPool::initialize_threadpool(size_type proposed_size)
tbb::global_control::max_allowed_parallelism, proposed_size + 1);
if(m_verbose > 0)
{
std::cout << "ThreadPool [TBB] initialized with " << m_pool_size
<< " threads." << std::endl;
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] ThreadPool [TBB] initialized with "
<< m_pool_size << " threads." << std::endl;
}
}
// create task group (used for async)
if(!m_tbb_task_group)
m_tbb_task_group = new tbb_task_group_t();
{
m_tbb_task_group = new tbb_task_group_t{};
execute_on_all_threads([this]() { m_init_func(); });
}
return m_pool_size;
}
#endif
@@ -267,21 +454,27 @@ ThreadPool::initialize_threadpool(size_type proposed_size)
;
if(m_verbose > 0)
{
std::cout << "ThreadPool initialized with " << m_pool_size << " threads."
<< std::endl;
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] ThreadPool initialized with "
<< m_pool_size << " threads." << std::endl;
}
if(!m_task_queue)
{
m_delete_task_queue = true;
m_task_queue = new UserTaskQueue(m_pool_size);
}
else
{
m_task_queue->resize(m_pool_size);
}
return m_pool_size;
}
else if(m_pool_size == proposed_size) // NOLINT
{
if(m_verbose > 0)
{
std::cout << "ThreadPool initialized with " << m_pool_size << " threads."
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "ThreadPool initialized with " << m_pool_size << " threads."
<< std::endl;
}
if(!m_task_queue)
@@ -301,7 +494,10 @@ ThreadPool::initialize_threadpool(size_type proposed_size)
}
if(!m_task_queue)
m_task_queue = new UserTaskQueue(proposed_size);
{
m_delete_task_queue = true;
m_task_queue = new UserTaskQueue(proposed_size);
}
auto this_tid = get_this_thread_id();
for(size_type i = m_pool_size; i < proposed_size; ++i)
@@ -321,15 +517,19 @@ ThreadPool::initialize_threadpool(size_type proposed_size)
// set the affinity
if(m_use_affinity)
set_affinity(i, thr);
set_priority(m_priority, thr);
// store
m_threads.emplace_back(std::move(thr));
} catch(std::runtime_error& e)
{
std::cerr << e.what() << std::endl; // issue creating thread
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] " << e.what()
<< std::endl; // issue creating thread
continue;
} catch(std::bad_alloc& e)
{
std::cerr << e.what() << std::endl;
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] " << e.what() << std::endl;
continue;
}
}
@@ -351,8 +551,9 @@ ThreadPool::initialize_threadpool(size_type proposed_size)
if(m_verbose > 0)
{
std::cout << "ThreadPool initialized with " << m_pool_size << " threads."
<< std::endl;
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] ThreadPool initialized with " << m_pool_size
<< " threads." << std::endl;
}
return m_main_threads.size();
@@ -375,6 +576,7 @@ ThreadPool::destroy_threadpool()
#if defined(PTL_USE_TBB)
if(m_tbb_task_group)
{
execute_on_all_threads([this]() { m_fini_func(); });
auto _func = [&]() { m_tbb_task_group->wait(); };
if(m_tbb_task_arena)
m_tbb_task_arena->execute(_func);
@@ -394,7 +596,11 @@ ThreadPool::destroy_threadpool()
delete _global_control;
_global_control = nullptr;
m_tbb_tp = false;
std::cout << "ThreadPool [TBB] destroyed" << std::endl;
AutoLock lock(TypeMutex<decltype(std::cerr)>());
if(m_verbose > 0)
{
std::cerr << "[PTL::ThreadPool] ThreadPool [TBB] destroyed" << std::endl;
}
}
#endif
@@ -441,8 +647,8 @@ ThreadPool::destroy_threadpool()
//--------------------------------------------------------------------//
// erase thread from thread ID list
if(f_thread_ids.find(_tid) != f_thread_ids.end())
f_thread_ids.erase(f_thread_ids.find(_tid));
if(f_thread_ids().find(_tid) != f_thread_ids().end())
f_thread_ids().erase(f_thread_ids().find(_tid));
//--------------------------------------------------------------------//
// it's joined
@@ -453,6 +659,7 @@ ThreadPool::destroy_threadpool()
m_threads.clear();
m_main_threads.clear();
m_is_joined.clear();
m_alive_flag->store(false);
auto start = std::chrono::steady_clock::now();
@@ -466,15 +673,17 @@ ThreadPool::destroy_threadpool()
auto _active = m_thread_active->load();
if(get_verbose() >= 0)
if(get_verbose() > 0)
{
if(_active == 0)
{
std::cout << "ThreadPool destroyed" << std::endl;
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] ThreadPool destroyed" << std::endl;
}
else
{
std::cout << "ThreadPool destroyed but " << _active
AutoLock lock(TypeMutex<decltype(std::cerr)>());
std::cerr << "[PTL::ThreadPool] ThreadPool destroyed but " << _active
<< " threads might still be active (and cause a termination error)"
<< std::endl;
}
@@ -497,6 +706,8 @@ ThreadPool::stop_thread()
if(!m_alive_flag->load() || m_pool_size == 0)
return 0;
m_pool_state->store(thread_pool::state::PARTIAL);
//------------------------------------------------------------------------//
// notify all threads we are shutting down
m_task_lock->lock();
@@ -505,6 +716,9 @@ ThreadPool::stop_thread()
m_task_lock->unlock();
//------------------------------------------------------------------------//
while(!m_is_stopped.empty() && m_stop_threads.empty())
;
// lock up the task queue
AutoLock _task_lock(*m_task_lock);
@@ -526,6 +740,8 @@ ThreadPool::stop_thread()
m_is_joined.pop_back();
}
m_pool_state->store(thread_pool::state::STARTED);
m_pool_size = m_main_threads.size();
return m_main_threads.size();
}
@@ -539,7 +755,6 @@ ThreadPool::get_valid_queue(task_queue_t*& _queue) const
_queue = new UserTaskQueue{ static_cast<intmax_t>(m_pool_size) };
return _queue;
}
//======================================================================================//
void
@@ -552,6 +767,8 @@ ThreadPool::execute_thread(VUserTaskQueue* _task_queue)
// initialization function
m_init_func();
// finalization function (executed when scope is destroyed)
ScopeDestructor _fini{ [this]() { m_fini_func(); } };
ThreadId tid = ThisThread::get_id();
ThreadData* data = thread_data();
+106 -9
View File
@@ -25,15 +25,24 @@
#include "PTL/Threading.hh"
#include "PTL/AutoLock.hh"
#include "PTL/Globals.hh"
#include "PTL/Types.hh"
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
#if defined(PTL_WINDOWS)
# include <Windows.h>
#else
#elif defined(PTL_UNIX)
# include <sys/syscall.h>
# include <sys/types.h>
# include <unistd.h>
#endif
#if defined(PTL_MACOS)
# include <sys/sysctl.h>
#endif
#if defined(PTL_LINUX)
# include <fstream>
#endif
#include <atomic>
using namespace PTL;
@@ -43,6 +52,7 @@ using namespace PTL;
namespace
{
thread_local int ThreadID = Threading::MASTER_ID;
} // namespace
//======================================================================================//
@@ -64,6 +74,50 @@ Threading::GetNumberOfCores()
//======================================================================================//
unsigned
Threading::GetNumberOfPhysicalCpus()
{
#if defined(PTL_MACOS)
int count;
size_t count_len = sizeof(count);
sysctlbyname("hw.physicalcpu", &count, &count_len, nullptr, 0);
return static_cast<unsigned>(count);
#elif defined(PTL_LINUX)
unsigned core_id_count = 0;
std::ifstream ifs("/proc/cpuinfo");
if(ifs)
{
std::set<std::string> core_ids;
while(true)
{
std::string line = {};
getline(ifs, line);
if(!ifs.good())
break;
if(line.find("core id") != std::string::npos)
{
for(std::string itr : { "core id", ":", " ", "\t" })
{
static auto _npos = std::string::npos;
auto _pos = _npos;
while((_pos = line.find(itr)) != _npos)
line = line.replace(_pos, itr.length(), "");
}
core_ids.insert(line);
}
}
core_id_count = static_cast<unsigned>(core_ids.size());
if(core_id_count > 0)
return core_id_count;
}
return GetNumberOfCores();
#else
return GetNumberOfCores();
#endif
}
//======================================================================================//
void
Threading::SetThreadId(int value)
{
@@ -79,16 +133,59 @@ Threading::GetThreadId()
//======================================================================================//
bool
Threading::SetPinAffinity(int cpu, NativeThread& aT)
Threading::SetPinAffinity(int _cpu)
{
#if defined(__linux__) || defined(_AIX)
cpu_set_t* aset = new cpu_set_t;
CPU_ZERO(aset);
CPU_SET(cpu, aset);
pthread_t& _aT = static_cast<pthread_t&>(aT);
return (pthread_setaffinity_np(_aT, sizeof(cpu_set_t), aset) == 0);
cpu_set_t _cpu_set{};
CPU_ZERO(&_cpu_set);
if(_cpu >= 0)
CPU_SET(_cpu, &_cpu_set);
return (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &_cpu_set) == 0);
#else // Not available for Mac, WIN,...
ConsumeParameters(cpu, aT);
ConsumeParameters(_cpu);
return true;
#endif
}
//======================================================================================//
bool
Threading::SetThreadPriority(int _prio)
{
#if defined(__linux__) || defined(_AIX)
return (pthread_setschedprio(pthread_self(), _prio) == 0);
#else // Not available for Mac, WIN,...
ConsumeParameters(_prio);
return true;
#endif
}
//======================================================================================//
bool
Threading::SetPinAffinity(int _cpu, NativeThread& _t)
{
#if defined(__linux__) || defined(_AIX)
cpu_set_t _cpu_set{};
CPU_ZERO(&_cpu_set);
CPU_SET(_cpu, &_cpu_set);
return (pthread_setaffinity_np(static_cast<pthread_t>(_t), sizeof(cpu_set_t),
&_cpu_set) == 0);
#else // Not available for Mac, WIN,...
ConsumeParameters(_cpu, _t);
return true;
#endif
}
//======================================================================================//
bool
Threading::SetThreadPriority(int _prio, NativeThread& _t)
{
#if defined(__linux__) || defined(_AIX)
return (pthread_setschedprio(static_cast<pthread_t>(_t), _prio) == 0);
#else
ConsumeParameters(_prio, _t);
return true;
#endif
}
+137
View File
@@ -0,0 +1,137 @@
//
// MIT License
// Copyright (c) 2019 Jonathan R. Madsen
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED
// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// ----------------------------------------------------------------------
// class Timer
//
// Implementation
// 29.04.97 G.Cosmo Added timings for Windows systems
#include "PTL/Timer.hh"
#include <iomanip>
#include <sstream>
#include <stdexcept>
#include <string>
using namespace PTL;
#if defined(IRIX6_2)
# if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE_EXTENDED == 1)
# define __vfork vfork
# endif
#endif
#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
# include <sys/types.h>
# include <windows.h>
//======================================================================================//
// extract milliseconds time unit
int
sysconf(int a)
{
if(a == _SC_CLK_TCK)
return 1000;
else
return 0;
}
//======================================================================================//
static clock_t
filetime2msec(FILETIME* t)
{
return (clock_t)((((float) t->dwHighDateTime) * 429496.7296) +
(((float) t->dwLowDateTime) * .0001));
}
//======================================================================================//
clock_t
times(struct tms* t)
{
FILETIME ct = { 0, 0 }, et = { 0, 0 }, st = { 0, 0 }, ut = { 0, 0 }, rt = { 0, 0 };
SYSTEMTIME realtime;
GetSystemTime(&realtime);
SystemTimeToFileTime(&realtime, &rt); // get real time in 10^-9 sec
if(t != 0)
{
GetProcessTimes(GetCurrentProcess(), &ct, &et, &st,
&ut); // get process time in 10^-9 sec
t->tms_utime = t->tms_cutime = filetime2msec(&ut);
t->tms_stime = t->tms_cstime = filetime2msec(&st);
}
return filetime2msec(&rt);
}
//======================================================================================//
#endif /* WIN32 */
//======================================================================================//
Timer::Timer()
: fValidTimes(false)
{}
//======================================================================================//
double
Timer::GetRealElapsed() const
{
if(!fValidTimes)
{
throw std::runtime_error("Timer::GetRealElapsed() - "
"Timer not stopped or times not recorded!");
}
std::chrono::duration<double> diff = fEndRealTime - fStartRealTime;
return diff.count();
}
//======================================================================================//
double
Timer::GetSystemElapsed() const
{
if(!fValidTimes)
{
throw std::runtime_error("Timer::GetSystemElapsed() - "
"Timer not stopped or times not recorded!");
}
double diff = fEndTimes.tms_stime - fStartTimes.tms_stime;
return diff / sysconf(_SC_CLK_TCK);
}
//======================================================================================//
double
Timer::GetUserElapsed() const
{
if(!fValidTimes)
{
throw std::runtime_error("Timer::GetUserElapsed() - "
"Timer not stopped or times not recorded!");
}
double diff = fEndTimes.tms_utime - fStartTimes.tms_utime;
return diff / sysconf(_SC_CLK_TCK);
}
//======================================================================================//
+7 -1
View File
@@ -27,8 +27,10 @@
#include "PTL/Task.hh"
#include "PTL/TaskGroup.hh"
#include "PTL/ThreadPool.hh"
#include "PTL/Utility.hh"
#include <cassert>
#include <stdexcept>
using namespace PTL;
@@ -41,6 +43,7 @@ UserTaskQueue::UserTaskQueue(intmax_t nworkers, UserTaskQueue* parent)
, m_insert_bin((parent) ? (ThreadPool::get_this_thread_id() % (nworkers + 1)) : 0)
, m_hold((parent) ? parent->m_hold : new std::atomic_bool(false))
, m_ntasks((parent) ? parent->m_ntasks : new std::atomic_uintmax_t(0))
, m_mutex((parent) ? parent->m_mutex : new Mutex{})
, m_subqueues((parent) ? parent->m_subqueues : new TaskSubQueueContainer())
{
// create nthreads + 1 subqueues so there is always a subqueue available
@@ -85,6 +88,7 @@ UserTaskQueue::~UserTaskQueue()
m_subqueues->clear();
delete m_hold;
delete m_ntasks;
delete m_mutex;
delete m_subqueues;
}
}
@@ -94,7 +98,9 @@ UserTaskQueue::~UserTaskQueue()
void
UserTaskQueue::resize(intmax_t n)
{
AutoLock l(m_mutex);
if(!m_mutex)
throw std::runtime_error("nullptr to mutex");
AutoLock lk(m_mutex);
if(m_workers < n)
{
while(m_workers < n)