|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <neural-graphics-primitives/common.h> |
|
#include <neural-graphics-primitives/thread_pool.h> |
|
|
|
#include <chrono> |
|
|
|
NGP_NAMESPACE_BEGIN |
|
|
|
using namespace std; |
|
|
|
ThreadPool::ThreadPool() |
|
: ThreadPool{thread::hardware_concurrency()} {} |
|
|
|
ThreadPool::ThreadPool(size_t maxNumThreads, bool force) { |
|
if (!force) { |
|
maxNumThreads = min((size_t)thread::hardware_concurrency(), maxNumThreads); |
|
} |
|
startThreads(maxNumThreads); |
|
} |
|
|
|
ThreadPool::~ThreadPool() { |
|
shutdownThreads(mThreads.size()); |
|
} |
|
|
|
void ThreadPool::startThreads(size_t num) { |
|
mNumThreads += num; |
|
for (size_t i = mThreads.size(); i < mNumThreads; ++i) { |
|
mThreads.emplace_back([this, i] { |
|
while (true) { |
|
unique_lock<mutex> lock{mTaskQueueMutex}; |
|
|
|
|
|
while (i < mNumThreads && mTaskQueue.empty()) { |
|
|
|
mWorkerCondition.wait(lock); |
|
} |
|
|
|
if (i >= mNumThreads) { |
|
break; |
|
} |
|
|
|
function<void()> task{move(mTaskQueue.front())}; |
|
mTaskQueue.pop_front(); |
|
|
|
|
|
lock.unlock(); |
|
|
|
task(); |
|
} |
|
}); |
|
} |
|
} |
|
|
|
void ThreadPool::shutdownThreads(size_t num) { |
|
auto numToClose = min(num, mNumThreads); |
|
|
|
{ |
|
lock_guard<mutex> lock{mTaskQueueMutex}; |
|
mNumThreads -= numToClose; |
|
} |
|
|
|
|
|
mWorkerCondition.notify_all(); |
|
for (auto i = 0u; i < numToClose; ++i) { |
|
mThreads.back().join(); |
|
mThreads.pop_back(); |
|
} |
|
} |
|
|
|
void ThreadPool::setNThreads(size_t num) { |
|
if (mNumThreads > num) { |
|
shutdownThreads(mNumThreads - num); |
|
} else if (mNumThreads < num) { |
|
startThreads(num - mNumThreads); |
|
} |
|
} |
|
|
|
void ThreadPool::flushQueue() { |
|
lock_guard<mutex> lock{mTaskQueueMutex}; |
|
mTaskQueue.clear(); |
|
} |
|
|
|
NGP_NAMESPACE_END |
|
|