Orrery
A GPU-accelerated N-body gravitational simulator
Loading...
Searching...
No Matches
work_stealing_executor.hpp
Go to the documentation of this file.
1#pragma once
2
57
58#include <cstdint>
59#include <mutex>
60#include <string_view>
61#include <vector>
62
69#include "orrery/core/types.hpp"
70
71namespace orrery::backend {
72
75class WorkStealingExecutor final : public Executor {
76public:
92 static constexpr core::Index kChunksPerWorker = 16;
93
94 explicit WorkStealingExecutor(unsigned worker_count = 0,
96
97 void run(core::Index count, RangeTask task) override;
98
99 [[nodiscard]] std::string_view name() const noexcept override { return "work-stealing"; }
100
101 [[nodiscard]] unsigned worker_count() const noexcept override { return pool_.worker_count(); }
102
103 [[nodiscard]] CoreClass worker_core_class(unsigned worker) const noexcept override {
104 return pool_.core_class(worker);
105 }
106
107 [[nodiscard]] ExecutorStatistics statistics() const override;
108
109 void reset_statistics() noexcept override;
110
111private:
117 struct alignas(core::kCacheLineBytes) WorkRange {
118 std::mutex mutex;
119
121 core::Index next{};
122
125 core::Index end{};
126 };
127
129 void drain(unsigned worker) noexcept;
130
132 [[nodiscard]] bool claim_front(unsigned worker, IndexRange& chunk) noexcept;
133
135 [[nodiscard]] bool claim_back(unsigned victim, IndexRange& chunk) noexcept;
136
138 [[nodiscard]] bool steal(unsigned thief, IndexRange& chunk) noexcept;
139
140 ThreadPool pool_;
141
142 std::vector<PaddedWorkerStatistics> workers_;
143 std::vector<Duration> busy_at_region_start_;
144
147 std::vector<WorkRange> ranges_;
148
150 const RangeTask* task_{nullptr};
151
153 core::Index grain_{kPartitionGrain};
154
155 Duration elapsed_{};
156 std::uint64_t regions_{};
157};
158
159} // namespace orrery::backend
An allocator that starts every allocation on a cache line.
Worker threads and a way to run something on all of them at once.
Definition thread_pool.hpp:41
Affinity
Whether workers are tied to a particular logical processor.
Definition thread_pool.hpp:44
@ kUnpinned
Let the operating system place the threads.
Definition thread_pool.hpp:51
CoreClass worker_core_class(unsigned worker) const noexcept override
What kind of core a worker runs on, where that is known.
Definition work_stealing_executor.hpp:103
void reset_statistics() noexcept override
Set every counter back to zero.
std::string_view name() const noexcept override
The scheme's name, for benchmark tables and reports.
Definition work_stealing_executor.hpp:99
static constexpr core::Index kChunksPerWorker
How many chunks each worker's share is broken into.
Definition work_stealing_executor.hpp:92
ExecutorStatistics statistics() const override
The record of what the workers have done since the last reset.
void run(core::Index count, RangeTask task) override
Call task over pieces that together cover [0, count) exactly once each, and return when all of them h...
unsigned worker_count() const noexcept override
How many workers this executor divides work between.
Definition work_stealing_executor.hpp:101
Which logical processors this machine has, and which of them are fast.
CoreClass
What kind of core a logical processor belongs to.
Definition cpu_topology.hpp:47
How a kernel asks for a loop to be run in parallel.
core::FunctionRef< void(core::Index, core::Index)> RangeTask
A piece of a parallel loop: the half-open index range [begin, end).
Definition executor.hpp:49
How a range of indices is divided between workers.
The whole pool's record.
Definition worker_statistics.hpp:99
A half-open range of indices.
Definition partition.hpp:37
A fixed set of worker threads that run one body function on demand.
The scalar and index types that every layer of the project agrees on.
std::size_t Index
The type of a particle index and of any count of particles.
Definition types.hpp:45
What each worker thread did, and how long it spent doing nothing.