Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
epoch_queue.hpp
Go to the documentation of this file.
1
3
4#pragma once
5
6#include "epoch_context.hpp"
7#include <atomic>
8#include <deque>
9#include <memory>
10#include <mutex>
12#include <utility>
13
14namespace uni20::async
15{
16
23 public:
25 EpochQueue() : current_(std::make_shared<EpochContext>()) { TRACE_MODULE(ASYNC, "EpochQueue Constructor", this); }
26
28 EpochQueue(EpochQueue const&) = delete;
30 EpochQueue& operator=(EpochQueue const&) = delete;
35
37 ~EpochQueue() { TRACE_MODULE(ASYNC, "EpochQueue Destructor", this); }
38
43 template <typename T> [[nodiscard]] EpochContextReader<T> create_read_context(shared_storage<T> storage) const
44 {
45 TRACE_MODULE(ASYNC, "EpochQueue::create_read_context", this);
46 // if (!current_->has_writer() && storage.constructed()) current_->start();
47 return EpochContextReader<T>(storage, current_);
48 }
49
55 {
56 TRACE_MODULE(ASYNC, "EpochQueue::create_write_context", this);
57 if (current_->has_writer())
58 {
59 std::shared_ptr<EpochContext> next = std::make_shared<EpochContext>();
60 current_->set_next_epoch(next);
61 current_ = next;
62 }
63 return EpochContextWriter<T>(storage, current_);
64 }
65
68 [[nodiscard]] std::shared_ptr<EpochContext> latest() const noexcept { return current_; }
69
72 [[nodiscard]] bool has_pending_writers() const noexcept { return current_ && current_->has_writer(); }
73
74#if UNI20_DEBUG_DAG
78 template <typename T> void initialize_node(shared_storage<T> const& storage)
79 {
80 if (current_) current_->set_node(NodeInfo::create(storage));
81 }
82
85 [[nodiscard]] NodeInfo const* debug_node() const { return current_ ? current_->node() : nullptr; }
86#endif
87
88 private:
89 std::shared_ptr<EpochContext> current_;
90};
91
92// FIXME: we can probably fix the oddities with the ordering of getting the buffers by
93// pre-constructing the WriteBuffer.
94// If the first epoch goes away then we cancel() it
97 public:
99 ReverseEpochQueue() : first_(std::make_shared<EpochContext>())
100 {
101 TRACE("Constructing ReverseEpochQueue EpochContext", first_.get());
102 }
103
108
113
116
118 explicit ReverseEpochQueue(std::shared_ptr<EpochContext> first) : first_(std::move(first))
119 {
120 TRACE_MODULE(ASYNC, "ReverseEpochQueue Constructor", this);
121 DEBUG_CHECK(!first_->has_writer());
122 }
123
128 template <typename T> [[nodiscard]] EpochContextReader<T> create_read_context(shared_storage<T> storage)
129 {
130 TRACE_MODULE(ASYNC, "ReverseEpochQueue::create_read_context", this);
131 DEBUG_CHECK(first_);
132 if (first_->has_writer()) first_ = EpochContext::make_previous(first_);
133 return EpochContextReader<T>(storage, first_);
134 }
135
141 {
142 TRACE_MODULE(ASYNC, "ReverseEpochQueue::create_write_context", this);
143 DEBUG_CHECK(first_);
144 if (first_->has_writer()) first_ = EpochContext::make_previous(first_);
145 // CHECK(!first_->has_writer());
146 return EpochContextWriter<T>(storage, first_);
147 }
148
151 void start()
152 {
153 DEBUG_CHECK(first_);
154 // CHECK(first_->has_writer());
155
156 // FIXME: we need to start() here in such a way that if we don't have an initial writer then
157 // we set an error state (which will generally be absorbed by the backprop accumulation knowing
158 // how to handle missing data)
159 first_->writer_acquire();
160 first_->writer_cancel();
161 first_->start();
162 first_.reset();
163 }
164
167 [[nodiscard]] bool is_started() const { return !first_; }
168
169 private:
170 std::shared_ptr<EpochContext> first_;
171};
172
173} // namespace uni20::async
RAII handle representing the writer of a value in an EpochContext.
Definition epoch_context.hpp:874
RAII-scoped representation of a writer’s participation in an epoch.
Definition epoch_context.hpp:1048
Definition epoch_context.hpp:169
static std::shared_ptr< EpochContext > make_previous(std::shared_ptr< EpochContext > next)
Helper factory to construct the previous epoch in a reverse-mode chain.
Definition epoch_context.hpp:214
Coordinates multiple epochs of read/write gates.
Definition epoch_queue.hpp:22
bool has_pending_writers() const noexcept
Reports whether the latest epoch already has a writer.
Definition epoch_queue.hpp:72
std::shared_ptr< EpochContext > latest() const noexcept
Returns the latest epoch context.
Definition epoch_queue.hpp:68
EpochQueue & operator=(EpochQueue &&)=delete
Queue identity is stable and is not move-assigned by value.
EpochContextWriter< T > create_write_context(shared_storage< T > storage)
Create a write context, advancing to a new epoch when needed.
Definition epoch_queue.hpp:54
EpochQueue & operator=(EpochQueue const &)=delete
Queue identity is shared by handle, never copy-assigned.
EpochQueue(EpochQueue &&)=delete
Queue identity is stable and is not transferred by value.
EpochContextReader< T > create_read_context(shared_storage< T > storage) const
Create a read context bound to the current epoch.
Definition epoch_queue.hpp:43
~EpochQueue()
Destroy the epoch queue.
Definition epoch_queue.hpp:37
EpochQueue()
Construct a queue with one initial epoch.
Definition epoch_queue.hpp:25
EpochQueue(EpochQueue const &)=delete
Queue identity is shared by handle, never copied.
static NodeInfo const * create(T const *value)
Returns the stacktrace of where the node was created.
Definition async_node.hpp:263
Reverse-order epoch queue used by reverse-mode gradient accumulation.
Definition epoch_queue.hpp:96
void start()
Start running the reverse queue.
Definition epoch_queue.hpp:151
EpochContextReader< T > create_read_context(shared_storage< T > storage)
Create a read context from the earliest active reverse epoch.
Definition epoch_queue.hpp:128
ReverseEpochQueue & operator=(ReverseEpochQueue &&)=default
Move assignment.
ReverseEpochQueue & operator=(ReverseEpochQueue &)=delete
Non-copyable.
ReverseEpochQueue(ReverseEpochQueue &&)=default
Move constructor.
ReverseEpochQueue()
Construct a reverse queue with one initial epoch.
Definition epoch_queue.hpp:99
ReverseEpochQueue(ReverseEpochQueue &)=delete
Non-copyable.
ReverseEpochQueue(std::shared_ptr< EpochContext > first)
Construct a ReverseEpochQueue from a given EpochContext.
Definition epoch_queue.hpp:118
EpochContextWriter< T > create_write_context(shared_storage< T > storage)
Create a write context from the earliest active reverse epoch.
Definition epoch_queue.hpp:140
~ReverseEpochQueue()=default
Destructor.
bool is_started() const
Reports whether the reverse queue has already started.
Definition epoch_queue.hpp:167
A lightweight, thread-safe, reference-counted storage for a single object.
Definition shared_storage.hpp:94
Manages one “generation” of write/read ordering in an Async<T>
Definition qnum.hpp:403
This represents the reverse-mode adjoint for functions of complex variables, assuming a real-valued s...
Definition async/async.hpp:26
#define DEBUG_CHECK(cond,...)
Definition trace.hpp:608
#define TRACE_MODULE(m,...)
Definition trace.hpp:149
#define TRACE(...)
Definition trace.hpp:89