More efficient threadpool
This commit is contained in:
+17
-4
@@ -1,9 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <coroutine>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#define DEFINE_REF(x) \
|
#define DEFINE_REF(x) typedef ::std::unique_ptr<x> P##x;
|
||||||
typedef ::std::unique_ptr<x> P##x; \
|
|
||||||
|
|
||||||
#define DECLARE_REF(x) \
|
#define DECLARE_REF(x) \
|
||||||
class x; \
|
class x; \
|
||||||
typedef ::std::unique_ptr<x> P##x; \
|
typedef ::std::unique_ptr<x> P##x;
|
||||||
|
|
||||||
|
struct Task
|
||||||
|
{
|
||||||
|
struct promise_type
|
||||||
|
{
|
||||||
|
Task get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
|
||||||
|
std::suspend_always initial_suspend() noexcept { return {}; }
|
||||||
|
std::suspend_never final_suspend() noexcept { return {}; }
|
||||||
|
void return_void() {}
|
||||||
|
void unhandled_exception() {}
|
||||||
|
};
|
||||||
|
std::coroutine_handle<promise_type> handle;
|
||||||
|
};
|
||||||
|
|||||||
+48
-46
@@ -3,64 +3,66 @@
|
|||||||
|
|
||||||
ThreadPool::ThreadPool(uint32_t numThreads)
|
ThreadPool::ThreadPool(uint32_t numThreads)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < numThreads; ++i)
|
for (uint32_t i = 0; i < numThreads; ++i)
|
||||||
{
|
{
|
||||||
workers.push_back(std::thread(&ThreadPool::work, this));
|
workers.push_back(std::thread(&ThreadPool::work, this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadPool::~ThreadPool()
|
ThreadPool::~ThreadPool()
|
||||||
{
|
{
|
||||||
running.store(false);
|
running.store(false);
|
||||||
{
|
{
|
||||||
std::unique_lock l(queueLock);
|
std::unique_lock l(queueLock);
|
||||||
queueCV.notify_all();
|
queueCV.notify_all();
|
||||||
}
|
}
|
||||||
for (auto& worker : workers)
|
for (auto& worker : workers)
|
||||||
{
|
{
|
||||||
worker.join();
|
worker.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadPool::runBatch(Batch&& batch)
|
void ThreadPool::runBatch(Batch&& batch)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::unique_lock l(queueLock);
|
std::unique_lock l(queueLock);
|
||||||
taskQueue.push_back(batch);
|
numRemaining = batch.jobs.size();
|
||||||
queueCV.notify_one();
|
taskQueue.push_back(batch);
|
||||||
}
|
queueCV.notify_all();
|
||||||
while (true)
|
}
|
||||||
{
|
while (true)
|
||||||
std::unique_lock l(queueLock);
|
{
|
||||||
if (taskQueue.empty())
|
std::unique_lock l(queueLock);
|
||||||
return;
|
if (taskQueue.empty())
|
||||||
completedCV.wait(l);
|
return;
|
||||||
}
|
completedCV.wait(l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadPool::work()
|
void ThreadPool::work()
|
||||||
{
|
{
|
||||||
while (running)
|
while (running)
|
||||||
|
{
|
||||||
|
Task job;
|
||||||
{
|
{
|
||||||
std::function<void()> job;
|
std::unique_lock l(queueLock);
|
||||||
{
|
if (taskQueue.empty() || taskQueue.front().jobs.empty())
|
||||||
std::unique_lock l(queueLock);
|
{
|
||||||
if (taskQueue.empty() || taskQueue.front().jobs.empty())
|
queueCV.wait(l);
|
||||||
{
|
continue;
|
||||||
queueCV.wait(l);
|
}
|
||||||
continue;
|
job = taskQueue.front().jobs.front();
|
||||||
}
|
taskQueue.front().jobs.pop_front();
|
||||||
job = taskQueue.front().jobs.front();
|
|
||||||
taskQueue.front().jobs.pop_front();
|
|
||||||
}
|
|
||||||
job();
|
|
||||||
{
|
|
||||||
std::unique_lock l(queueLock);
|
|
||||||
if (taskQueue.front().jobs.empty())
|
|
||||||
{
|
|
||||||
taskQueue.pop_front();
|
|
||||||
completedCV.notify_one();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
job.handle();
|
||||||
|
{
|
||||||
|
std::unique_lock l(queueLock);
|
||||||
|
numRemaining--;
|
||||||
|
if (numRemaining == 0)
|
||||||
|
{
|
||||||
|
taskQueue.pop_front();
|
||||||
|
completedCV.notify_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -3,10 +3,11 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include "Minimal.h"
|
||||||
|
|
||||||
struct Batch
|
struct Batch
|
||||||
{
|
{
|
||||||
std::list<std::function<void()>> jobs;
|
std::list<Task> jobs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadPool
|
class ThreadPool
|
||||||
@@ -21,6 +22,7 @@ private:
|
|||||||
std::mutex queueLock;
|
std::mutex queueLock;
|
||||||
std::condition_variable queueCV;
|
std::condition_variable queueCV;
|
||||||
std::condition_variable completedCV;
|
std::condition_variable completedCV;
|
||||||
|
uint32_t numRemaining;
|
||||||
std::list<Batch> taskQueue;
|
std::list<Batch> taskQueue;
|
||||||
std::vector<std::thread> workers;
|
std::vector<std::thread> workers;
|
||||||
};
|
};
|
||||||
+6
-4
@@ -5,8 +5,9 @@
|
|||||||
|
|
||||||
Scene::Scene()
|
Scene::Scene()
|
||||||
{
|
{
|
||||||
bvh.addModels(ModelLoader::loadModel("../res/models/cube.fbx"), glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f),
|
bvh.addModels(ModelLoader::loadModel("../res/models/cube.fbx"),
|
||||||
glm::vec4(0.0f, 0.0f, 1.0f, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)));
|
glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), glm::vec4(0.0f, 0.0f, 1.0f, 0.0f),
|
||||||
|
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)));
|
||||||
bvh.generate();
|
bvh.generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ void Scene::render(Camera cam, RenderParameter params)
|
|||||||
for (int w = 0; w < params.width; ++w)
|
for (int w = 0; w < params.width; ++w)
|
||||||
{
|
{
|
||||||
batch.jobs.push_back(
|
batch.jobs.push_back(
|
||||||
[&, w]()
|
[&](int w) -> Task
|
||||||
{
|
{
|
||||||
for (int h = 0; h < params.height; ++h)
|
for (int h = 0; h < params.height; ++h)
|
||||||
{
|
{
|
||||||
@@ -51,7 +52,8 @@ void Scene::render(Camera cam, RenderParameter params)
|
|||||||
accumulator[w + h * params.width] +=
|
accumulator[w + h * params.width] +=
|
||||||
glm::vec3(w / float(params.width * params.numSamples), h / float(params.height * params.numSamples), 0);
|
glm::vec3(w / float(params.width * params.numSamples), h / float(params.height * params.numSamples), 0);
|
||||||
}
|
}
|
||||||
});
|
co_return;
|
||||||
|
}(w));
|
||||||
}
|
}
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
threadPool.runBatch(std::move(batch));
|
threadPool.runBatch(std::move(batch));
|
||||||
|
|||||||
Reference in New Issue
Block a user