summaryrefslogtreecommitdiff
path: root/aa.h
diff options
context:
space:
mode:
authorKeuin <[email protected]>2022-04-16 23:41:10 +0800
committerKeuin <[email protected]>2022-04-17 10:45:59 +0800
commit3e7ca8a48e9a788882fa201b14da2eb5b6cf8bf0 (patch)
treee877dd4786684d67c28b06144bc75be83fbbb155 /aa.h
parent9992f29a6222e1822f23329b2f49eef62dd949fe (diff)
New lock-free thread pool. Improve CPU utility with massive small tasks.
Diffstat (limited to 'aa.h')
-rw-r--r--aa.h74
1 files changed, 43 insertions, 31 deletions
diff --git a/aa.h b/aa.h
index 7e6e722..f2dfd69 100644
--- a/aa.h
+++ b/aa.h
@@ -8,8 +8,8 @@
#include "vec.h"
#include "viewport.h"
#include "hitlist.h"
+#include "threading.h"
#include <vector>
-#include <thread>
#include <algorithm>
#include <random>
@@ -30,38 +30,50 @@ public:
}
virtual bitmap<T> render(const hitlist &world, vec3d viewpoint, uint16_t image_width, uint16_t image_height) {
- const unsigned hwcc = std::thread::hardware_concurrency();
- std::cerr << "Rendering with " << hwcc << " thread(s)." << std::endl;
-
- const auto seed = 123456789012345678ULL;
- std::mt19937_64 seedgen{seed}; // generates seeds for workers
+ static constexpr auto seed = 123456789012345678ULL;
+ const unsigned thread_count = std::min(std::thread::hardware_concurrency(), samples);
+ std::cerr << "Preparing tasks..." << std::endl;
std::vector<bitmap<T>> images{samples, {1, 1}};
- std::thread t;
-
- std::vector<std::thread> workers;
- unsigned remaining = samples; // tasks remaining
- size_t base = 0;
- while (remaining > 0) {
- const unsigned n = std::min(hwcc, remaining); // threads in current batch
- remaining -= n;
- for (unsigned i = 0; i < n; ++i) {
- workers.emplace_back(std::thread{
- [&](int tid, uint64_t seed, uint64_t diffuse_seed, std::vector<basic_viewport<T>> *subs, vec3d viewpoint,
- uint16_t image_width, uint16_t image_height) {
- bias_ctx bc{seed};
- auto image = (*subs)[tid].render(
- world, viewpoint, image_width, image_height, bc, diffuse_seed);
- images[base + tid] = image;
- },
- i, seedgen(), seedgen(), subviews, viewpoint, image_width, image_height
- });
- }
- for (auto &th: workers) {
- th.join();
- }
- workers.clear();
- base += n;
+ std::mt19937_64 seedgen{seed}; // generates seeds for workers
+
+ const struct s_render_shared {
+ std::vector<basic_viewport<T>> &subs;
+ vec3d viewpoint;
+ uint16_t image_width;
+ uint16_t image_height;
+ const hitlist &world;
+ std::vector<bitmap<T>> &images;
+ } s_{.subs=*subviews, .viewpoint = viewpoint,
+ .image_width=image_width, .image_height=image_height,
+ .world=world, .images=images
+ };
+
+ struct s_render_task {
+ uint32_t task_id;
+ uint64_t seed;
+ uint64_t diffuse_seed;
+ const s_render_shared &shared;
+ };
+
+ thread_pool<s_render_task> pool{thread_count};
+
+
+ for (typeof(samples) i = 0; i < samples; ++i) {
+ pool.submit_task([](s_render_task &task) {
+ bias_ctx bc{seed};
+ auto image = task.shared.subs[task.task_id].render(
+ task.shared.world, task.shared.viewpoint,
+ task.shared.image_width, task.shared.image_height,
+ bc, task.diffuse_seed);
+ task.shared.images[task.task_id] = image;
+ }, s_render_task{
+ .task_id = i, .seed=seedgen(), .diffuse_seed=seedgen(), .shared=s_
+ });
}
+
+ std::cerr << "Rendering with " << thread_count << " thread(s)." << std::endl;
+ pool.start();
+ pool.wait();
return bitmap<T>::average(images);
}