ZhengyangZhang commited on
Commit
a809a68
·
verified ·
1 Parent(s): a4472e7

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/all.h +23 -0
  2. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/arg.h +23 -0
  3. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/autograd.h +5 -0
  4. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/cuda.h +28 -0
  5. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data.h +13 -0
  6. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader.h +54 -0
  7. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/base.h +250 -0
  8. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/stateful.h +61 -0
  9. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/stateless.h +80 -0
  10. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader_options.h +63 -0
  11. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets.h +9 -0
  12. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/base.h +96 -0
  13. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/chunk.h +526 -0
  14. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/map.h +114 -0
  15. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/mnist.h +44 -0
  16. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/shared.h +79 -0
  17. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/stateful.h +64 -0
  18. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/tensor.h +34 -0
  19. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/data_shuttle.h +83 -0
  20. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/queue.h +80 -0
  21. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/sequencers.h +107 -0
  22. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/example.h +53 -0
  23. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/iterator.h +178 -0
  24. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers.h +9 -0
  25. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/base.h +41 -0
  26. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/custom_batch_request.h +17 -0
  27. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/distributed.h +133 -0
  28. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/random.h +48 -0
  29. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/sequential.h +44 -0
  30. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/serialize.h +24 -0
  31. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/stream.h +57 -0
  32. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms.h +7 -0
  33. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/base.h +49 -0
  34. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/collate.h +31 -0
  35. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/lambda.h +52 -0
  36. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/stack.h +45 -0
  37. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/tensor.h +73 -0
  38. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/worker_exception.h +37 -0
  39. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/detail/TensorDataContainer.h +351 -0
  40. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/detail/static.h +60 -0
  41. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/enum.h +210 -0
  42. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/expanding_array.h +182 -0
  43. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/fft.h +390 -0
  44. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/imethod.h +53 -0
  45. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/jit.h +34 -0
  46. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/mps.h +42 -0
  47. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nested.h +93 -0
  48. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nn.h +10 -0
  49. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nn/cloneable.h +94 -0
  50. lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nn/functional.h +17 -0
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/all.h ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #if !defined(_MSC_VER) && __cplusplus < 201703L
4
+ #error C++17 or later compatible compiler is required to use PyTorch.
5
+ #endif
6
+
7
+ #include <torch/autograd.h>
8
+ #include <torch/cuda.h>
9
+ #include <torch/data.h>
10
+ #include <torch/enum.h>
11
+ #include <torch/fft.h>
12
+ #include <torch/jit.h>
13
+ #include <torch/mps.h>
14
+ #include <torch/nested.h>
15
+ #include <torch/nn.h>
16
+ #include <torch/optim.h>
17
+ #include <torch/serialize.h>
18
+ #include <torch/sparse.h>
19
+ #include <torch/special.h>
20
+ #include <torch/types.h>
21
+ #include <torch/utils.h>
22
+ #include <torch/version.h>
23
+ #include <torch/xpu.h>
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/arg.h ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <utility>
4
+
5
+ #define TORCH_ARG(T, name) \
6
+ public: \
7
+ inline auto name(const T& new_##name) -> decltype(*this) { /* NOLINT */ \
8
+ this->name##_ = new_##name; \
9
+ return *this; \
10
+ } \
11
+ inline auto name(T&& new_##name) -> decltype(*this) { /* NOLINT */ \
12
+ this->name##_ = std::move(new_##name); \
13
+ return *this; \
14
+ } \
15
+ inline const T& name() const noexcept { /* NOLINT */ \
16
+ return this->name##_; \
17
+ } \
18
+ inline T& name() noexcept { /* NOLINT */ \
19
+ return this->name##_; \
20
+ } \
21
+ \
22
+ private: \
23
+ T name##_ /* NOLINT */
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/autograd.h ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/autograd/autograd.h>
4
+ #include <torch/csrc/autograd/autograd_not_implemented_fallback.h>
5
+ #include <torch/csrc/autograd/custom_function.h>
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/cuda.h ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+
5
+ #include <cstddef>
6
+ #include <cstdint>
7
+
8
+ namespace torch::cuda {
9
+
10
+ /// Returns the number of CUDA devices available.
11
+ size_t TORCH_API device_count();
12
+
13
+ /// Returns true if at least one CUDA device is available.
14
+ bool TORCH_API is_available();
15
+
16
+ /// Returns true if CUDA is available, and CuDNN is available.
17
+ bool TORCH_API cudnn_is_available();
18
+
19
+ /// Sets the seed for the current GPU.
20
+ void TORCH_API manual_seed(uint64_t seed);
21
+
22
+ /// Sets the seed for all available GPUs.
23
+ void TORCH_API manual_seed_all(uint64_t seed);
24
+
25
+ /// Waits for all kernels in all streams on a CUDA device to complete.
26
+ void TORCH_API synchronize(int64_t device_index = -1);
27
+
28
+ } // namespace torch::cuda
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data.h ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/dataloader.h>
4
+ #include <torch/data/datasets.h>
5
+ #include <torch/data/samplers.h>
6
+ #include <torch/data/transforms.h>
7
+
8
+ // Some "exports".
9
+
10
+ namespace torch::data {
11
+ using datasets::BatchDataset; // NOLINT
12
+ using datasets::Dataset; // NOLINT
13
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader.h ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/dataloader/stateful.h>
4
+ #include <torch/data/dataloader/stateless.h>
5
+
6
+ #include <torch/csrc/utils/variadic.h>
7
+
8
+ #include <c10/util/Exception.h>
9
+
10
+ #include <cstddef>
11
+ #include <memory>
12
+ #include <type_traits>
13
+ #include <utility>
14
+
15
+ namespace torch::data {
16
+
17
+ /// Creates a `DataLoader` instance for a stateless `dataset`, a `sampler` and
18
+ /// some `options`.
19
+ template <typename Dataset, typename Sampler>
20
+ std::enable_if_t<
21
+ !Dataset::is_stateful,
22
+ std::unique_ptr<StatelessDataLoader<Dataset, Sampler>>>
23
+ make_data_loader(Dataset dataset, Sampler sampler, DataLoaderOptions options) {
24
+ return std::make_unique<StatelessDataLoader<Dataset, Sampler>>(
25
+ std::move(dataset), std::move(sampler), options);
26
+ }
27
+
28
+ /// Creates a `DataLoader` instance for a stateless `dataset` and some
29
+ /// `options`. A sampler (by default a `RandomSampler`) will be constructed from
30
+ /// the size of the dataset.
31
+ template <typename Sampler = samplers::RandomSampler, typename Dataset>
32
+ std::enable_if_t<
33
+ !Dataset::is_stateful && std::is_constructible_v<Sampler, size_t>,
34
+ std::unique_ptr<StatelessDataLoader<Dataset, Sampler>>>
35
+ make_data_loader(
36
+ Dataset dataset,
37
+ DataLoaderOptions options = DataLoaderOptions()) {
38
+ const std::optional<size_t> size = dataset.size();
39
+ TORCH_CHECK(
40
+ size.has_value(),
41
+ "Expected the dataset to be sized in "
42
+ "order to construct the Sampler");
43
+ return make_data_loader(std::move(dataset), Sampler(*size), options);
44
+ }
45
+
46
+ /// Creates a `DataLoader` for a stateful `dataset` and some `options`.
47
+ template <typename Dataset, typename = std::enable_if_t<Dataset::is_stateful>>
48
+ std::unique_ptr<StatefulDataLoader<Dataset>> make_data_loader(
49
+ Dataset dataset,
50
+ DataLoaderOptions options = DataLoaderOptions()) {
51
+ return std::make_unique<StatefulDataLoader<Dataset>>(
52
+ std::move(dataset), options);
53
+ }
54
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/base.h ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/dataloader_options.h>
4
+ #include <torch/data/detail/data_shuttle.h>
5
+ #include <torch/data/detail/sequencers.h>
6
+ #include <torch/data/iterator.h>
7
+ #include <torch/data/samplers/random.h>
8
+ #include <torch/data/worker_exception.h>
9
+ #include <torch/types.h>
10
+
11
+ #include <torch/csrc/utils/variadic.h>
12
+
13
+ #include <c10/util/Exception.h>
14
+ #include <c10/util/irange.h>
15
+
16
+ #include <cstddef>
17
+ #include <exception>
18
+ #include <memory>
19
+ #include <thread>
20
+ #include <utility>
21
+ #include <vector>
22
+
23
+ namespace torch::data {
24
+ template <typename Dataset, typename Batch, typename BatchRequest>
25
+ class DataLoaderBase {
26
+ public:
27
+ using BatchType = Batch;
28
+ using BatchRequestType = BatchRequest;
29
+
30
+ /// Constructs a new DataLoader from a `dataset` to sample from, `options`
31
+ /// to configure the DataLoader with, and a `sampler` that specifies the
32
+ /// sampling strategy.
33
+ DataLoaderBase(
34
+ DataLoaderOptions options,
35
+ std::unique_ptr<Dataset> main_thread_dataset = nullptr)
36
+ : options_(options),
37
+ main_thread_dataset_(std::move(main_thread_dataset)),
38
+ sequencer_(new_sequencer()) {}
39
+
40
+ // NOLINTNEXTLINE(bugprone-exception-escape)
41
+ virtual ~DataLoaderBase() {
42
+ join();
43
+ }
44
+
45
+ /// Returns an iterator into the DataLoader. The lifetime of the iterator is
46
+ /// bound to the DataLoader. In C++ standards language, the category of the
47
+ /// iterator is `OutputIterator`. See
48
+ /// https://en.cppreference.com/w/cpp/named_req/OutputIterator for what this
49
+ /// means. In short: you may increment the iterator and dereference it, but
50
+ /// cannot go back, or step forward more than one position at a time. When the
51
+ /// DataLoader is exhausted, it will compare equal with the special
52
+ /// "sentinel" iterator returned by `DataLoader::end()`. Most of the time, you
53
+ /// should only use range-for loops to loop over the DataLoader, but
54
+ /// standard algorithms like `std::copy(dataloader.begin(), dataloader.end(),
55
+ /// output_iterator)` are supported too.
56
+ Iterator<Batch> begin() {
57
+ TORCH_CHECK(
58
+ shuttle_.in_flight_jobs() == 0,
59
+ "Attempted to get a new DataLoader iterator "
60
+ "while another iterator is not yet exhausted");
61
+ reset();
62
+ return Iterator<Batch>(std::make_unique<detail::ValidIterator<Batch>>(
63
+ [this] { return this->next(); }));
64
+ }
65
+
66
+ /// Returns a special "sentinel" iterator that compares equal with a
67
+ /// non-sentinel iterator once the DataLoader is exhausted.
68
+ Iterator<Batch> end() {
69
+ return Iterator<Batch>(std::make_unique<detail::SentinelIterator<Batch>>());
70
+ }
71
+
72
+ /// Joins the DataLoader's worker threads and drains internal queues.
73
+ /// This function may only be invoked from the main thread (in which the
74
+ /// DataLoader lives).
75
+ void join() {
76
+ if (joined_) {
77
+ return;
78
+ }
79
+ shuttle_.drain();
80
+ // Send one 'quit' message per worker. Since a worker dies (exits its
81
+ // thread) after receiving this message, each `QuitWorker()` message will be
82
+ // read by exactly one worker.
83
+ for ([[maybe_unused]] const auto w : c10::irange(options_.workers)) {
84
+ push_job(QuitWorker());
85
+ }
86
+ for (auto& worker : workers_) {
87
+ worker.join();
88
+ }
89
+ joined_ = true;
90
+ }
91
+
92
+ /// Returns the options with which the DataLoader was configured.
93
+ const FullDataLoaderOptions& options() const noexcept {
94
+ return options_;
95
+ }
96
+
97
+ protected:
98
+ /// Simple mix-in to give something a sequence number.
99
+ struct Sequenced {
100
+ Sequenced() = default;
101
+ Sequenced(size_t sqn) : sequence_number(sqn) {}
102
+ size_t sequence_number;
103
+ };
104
+
105
+ struct QuitWorker {};
106
+
107
+ /// A `Job` is either a `BatchRequest` (new indices to fetch data at) or a
108
+ /// `QuitWorker` object, to indicate the worker should shut down.
109
+ struct Job : Sequenced {
110
+ Job() = default;
111
+ Job(QuitWorker q, size_t sqn) : Sequenced(sqn), quit(q) {}
112
+ Job(BatchRequest&& i, size_t sqn)
113
+ : Sequenced(sqn), batch_request(std::move(i)) {}
114
+ std::optional<QuitWorker> quit;
115
+ std::optional<BatchRequest> batch_request;
116
+ };
117
+
118
+ /// The finished result of a job.
119
+ struct Result : Sequenced {
120
+ Result() = default;
121
+ Result(std::optional<Batch>&& b, size_t sqn)
122
+ : Sequenced(sqn), batch(std::move(b)) {}
123
+ Result(std::exception_ptr exception, size_t sqn)
124
+ : Sequenced(sqn), exception(std::move(exception)) {}
125
+ std::optional<Batch> batch;
126
+ std::exception_ptr exception;
127
+ };
128
+
129
+ /// Subclass hook for getting the next batch request. The stateless case will
130
+ /// ask the sampler for a new batch request (e.g. a vector of indices), while
131
+ /// the stateful one will simply return the batch size.
132
+ virtual std::optional<BatchRequestType> get_batch_request() = 0;
133
+
134
+ /// Resets the internal state of the DataLoader, optionally pre-fetching
135
+ /// new jobs.
136
+ virtual void reset() {
137
+ shuttle_.drain();
138
+ sequence_number_ = 0;
139
+ sequencer_ = new_sequencer();
140
+ prefetch();
141
+ }
142
+
143
+ /// Schedules `requested_jobs` many new batches to be fetched. The actual
144
+ /// number of jobs scheduled may be less if the DataLoader exhausts.
145
+ void prefetch(size_t requested_jobs) {
146
+ for ([[maybe_unused]] const auto r : c10::irange(requested_jobs)) {
147
+ if (auto batch_request = get_batch_request()) {
148
+ this->push_job(std::move(*batch_request));
149
+ } else {
150
+ break;
151
+ }
152
+ }
153
+ }
154
+
155
+ /// Schedules the maximum number of jobs (based on the `max_jobs` option).
156
+ void prefetch() {
157
+ prefetch(options_.max_jobs);
158
+ }
159
+
160
+ /// Returns the next batch of data, or an empty `optional` if the DataLoader
161
+ /// is exhausted. This operation will block until a batch is available if one
162
+ /// is still expected.
163
+ std::optional<BatchType> next() {
164
+ if (options_.workers > 0) {
165
+ while (std::optional<Result> result = this->pop_result()) {
166
+ if (result->exception) {
167
+ throw WorkerException(result->exception);
168
+ } else if (result->batch) {
169
+ prefetch(1);
170
+ return std::move(result->batch);
171
+ }
172
+ }
173
+ } else if (auto batch_request = get_batch_request()) {
174
+ return this->main_thread_dataset_->get_batch(std::move(*batch_request));
175
+ }
176
+ return std::nullopt;
177
+ }
178
+
179
+ /// The function that worker threads run.
180
+ void worker_thread(Dataset& dataset) {
181
+ while (true) {
182
+ auto job = shuttle_.pop_job();
183
+ if (job.quit) {
184
+ break;
185
+ }
186
+ try {
187
+ auto batch = dataset.get_batch(std::move(*job.batch_request));
188
+ shuttle_.push_result({std::move(batch), job.sequence_number});
189
+ } catch (...) {
190
+ shuttle_.push_result({std::current_exception(), job.sequence_number});
191
+ }
192
+ }
193
+ }
194
+
195
+ /// Convenience method that calls `shuttle_.push_job()` with the next sequence
196
+ /// number.
197
+ template <typename T>
198
+ void push_job(T value) {
199
+ shuttle_.push_job({std::move(value), sequence_number_++});
200
+ }
201
+
202
+ /// Convenience method that gets the next result from the sequencer.
203
+ std::optional<Result> pop_result() {
204
+ return sequencer_->next(
205
+ [this] { return this->shuttle_.pop_result(this->options_.timeout); });
206
+ }
207
+
208
+ /// Convenience method that creates a new sequencer based on the
209
+ /// `enforce_ordering` option.
210
+ std::unique_ptr<detail::sequencers::Sequencer<Result>> new_sequencer() {
211
+ if (options_.enforce_ordering) {
212
+ return std::make_unique<detail::sequencers::OrderedSequencer<Result>>(
213
+ options_.max_jobs);
214
+ }
215
+ return std::make_unique<detail::sequencers::NoSequencer<Result>>();
216
+ }
217
+
218
+ /// The options the DataLoader was configured with.
219
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
220
+ const FullDataLoaderOptions options_;
221
+
222
+ /// The dataset for the main thread, only has a value if the number of
223
+ /// worker threads was configured as zero, meaning the main thread has to do
224
+ /// all the work (synchronously). NOTE: Really want this to be on the heap
225
+ /// when empty, therefore `unique_ptr` and not `optional`.
226
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
227
+ std::unique_ptr<Dataset> main_thread_dataset_;
228
+
229
+ /// The sequence number for the *next* batch to be retrieved from the
230
+ /// dataset.
231
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
232
+ size_t sequence_number_ = 0;
233
+
234
+ /// The worker threads, running the `worker_thread()` method.
235
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
236
+ std::vector<std::thread> workers_;
237
+
238
+ /// The `DataShuttle` which takes care of the life cycle of a job.
239
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
240
+ detail::DataShuttle<Job, Result> shuttle_;
241
+
242
+ /// The `Sequencer`, which handles optional ordering of batches.
243
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
244
+ std::unique_ptr<detail::sequencers::Sequencer<Result>> sequencer_;
245
+
246
+ /// True if the DataLoader has joined its worker threads.
247
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
248
+ bool joined_ = false;
249
+ };
250
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/stateful.h ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <c10/util/irange.h>
4
+ #include <torch/data/dataloader/base.h>
5
+
6
+ #include <cstddef>
7
+ #include <thread>
8
+ #include <utility>
9
+
10
+ namespace torch::data {
11
+
12
+ /// A dataloader for stateful datasets.
13
+ ///
14
+ /// A dataloader for stateful datatasets differs from one for stateless
15
+ /// datasets one in that the dataset is shared among worker threads, and that
16
+ /// this dataset is itself responsible for producing batches rather than
17
+ /// depending on a sampler. The statefulness here actually refers to the
18
+ /// dataset. The StatefulDataLoader simply alters the data loading algorithm to
19
+ /// accommodate the stateful, shared nature of the dataset. Note that the
20
+ /// dataset must be thread safe if more than one worker thread is used.
21
+ ///
22
+ /// A stateful dataloader is created by calling `make_data_loader` with a
23
+ /// stateful dataset.
24
+ template <typename Dataset>
25
+ class StatefulDataLoader : public DataLoaderBase<
26
+ Dataset,
27
+ typename Dataset::BatchType::value_type,
28
+ typename Dataset::BatchRequestType> {
29
+ public:
30
+ using super = DataLoaderBase<
31
+ Dataset,
32
+ typename Dataset::BatchType::value_type,
33
+ typename Dataset::BatchRequestType>;
34
+ using typename super::BatchRequestType;
35
+
36
+ /// Constructs the `StatefulDataLoader` from a `dataset` and some `options`.
37
+ StatefulDataLoader(Dataset dataset, DataLoaderOptions options)
38
+ : super(options, std::make_unique<Dataset>(std::move(dataset))) {
39
+ for ([[maybe_unused]] const auto _ : c10::irange(this->options_.workers)) {
40
+ // As opposed to the stateless case, here all worker threads access the
41
+ // same underlying dataset.
42
+ this->workers_.emplace_back(
43
+ [this] { this->worker_thread(*this->main_thread_dataset_); });
44
+ }
45
+ }
46
+
47
+ private:
48
+ /// Resets the internal state of the dataloader and the dataset.
49
+ void reset() override {
50
+ this->main_thread_dataset_->reset();
51
+ // Call the base class method last because it calls `prefetch()`
52
+ super::reset();
53
+ }
54
+
55
+ /// For stateful datasets, the batch request is always the batch size. The
56
+ /// dataset is responsible for determining what goes into the batch next.
57
+ std::optional<BatchRequestType> get_batch_request() override {
58
+ return this->options_.batch_size;
59
+ }
60
+ };
61
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/stateless.h ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/dataloader/base.h>
4
+ #include <torch/data/worker_exception.h>
5
+
6
+ #include <c10/util/Exception.h>
7
+ #include <c10/util/irange.h>
8
+
9
+ #include <cstddef>
10
+ #include <thread>
11
+ #include <utility>
12
+
13
+ namespace torch::data {
14
+
15
+ /// A dataloader for stateless datasets.
16
+ ///
17
+ /// This dataloader follows the traditional PyTorch dataloader design, whereby a
18
+ /// (posssibly) stateful sampler produces *batch requests* for a stateless
19
+ /// dataset, which acts as a simple batch request to batch mapping. The batch
20
+ /// request will often be an array of indices, and if the dataset is a simple
21
+ /// image dataset, the dataset would produce the images at those indices.
22
+ template <typename Dataset, typename Sampler>
23
+ class StatelessDataLoader : public DataLoaderBase<
24
+ Dataset,
25
+ typename Dataset::BatchType,
26
+ typename Sampler::BatchRequestType> {
27
+ public:
28
+ using super = DataLoaderBase<
29
+ Dataset,
30
+ typename Dataset::BatchType,
31
+ typename Sampler::BatchRequestType>;
32
+ using typename super::BatchRequestType;
33
+
34
+ /// Constructs the `StatelessDataLoader` from a `dataset`, a `sampler` and
35
+ /// some `options`.
36
+ StatelessDataLoader(
37
+ Dataset dataset,
38
+ Sampler sampler,
39
+ DataLoaderOptions options)
40
+ : super(options), sampler_(std::move(sampler)) {
41
+ for (const auto w : c10::irange(this->options_.workers)) {
42
+ // Here we copy the dataset into the worker thread closure. Each worker
43
+ // has its own copy of the dataset. This means the dataset must be
44
+ // trivially copiable, or else we don't expect more than one worker to
45
+ // be in use.
46
+ (void)w; // Suppress unused variable warning
47
+ this->workers_.emplace_back(
48
+ [this, dataset]() mutable { this->worker_thread(dataset); });
49
+ }
50
+ if (this->options_.workers == 0) {
51
+ this->main_thread_dataset_ =
52
+ std::make_unique<Dataset>(std::move(dataset));
53
+ }
54
+ }
55
+
56
+ private:
57
+ /// Resets the internal state of the dataloader and the sampler.
58
+ void reset() override {
59
+ sampler_.reset();
60
+ // Call the base class method last because it calls `prefetch()`
61
+ super::reset();
62
+ }
63
+
64
+ /// Queries the sampler for the next batch request (possibly progressing its
65
+ /// internal state).
66
+ std::optional<BatchRequestType> get_batch_request() override {
67
+ auto indices = sampler_.next(this->options_.batch_size);
68
+ if (!indices ||
69
+ (indices->size() < this->options_.batch_size &&
70
+ this->options_.drop_last)) {
71
+ return std::nullopt;
72
+ }
73
+ AT_ASSERT(indices->size() > 0);
74
+ return indices;
75
+ }
76
+
77
+ /// The `Sampler` used to produce batch requests.
78
+ Sampler sampler_;
79
+ };
80
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader_options.h ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/arg.h>
4
+ #include <torch/types.h>
5
+
6
+ #include <chrono>
7
+ #include <cstddef>
8
+
9
+ namespace torch::data {
10
+
11
+ /// Options to configure a `DataLoader`.
12
+ struct DataLoaderOptions {
13
+ DataLoaderOptions() = default;
14
+ /* implicit */ DataLoaderOptions(size_t batch_size)
15
+ : batch_size_(batch_size) {}
16
+
17
+ /// The size of each batch to fetch.
18
+ TORCH_ARG(size_t, batch_size) = 1;
19
+
20
+ /// The number of worker threads to launch. If zero, the main thread will
21
+ /// synchronously perform the data loading.
22
+ TORCH_ARG(size_t, workers) = 0;
23
+
24
+ /// The maximum number of jobs to enqueue for fetching by worker threads.
25
+ /// Defaults to two times the number of worker threads.
26
+ TORCH_ARG(std::optional<size_t>, max_jobs);
27
+
28
+ /// An optional limit on the time to wait for the next batch.
29
+ TORCH_ARG(std::optional<std::chrono::milliseconds>, timeout);
30
+
31
+ /// Whether to enforce ordering of batches when multiple are loaded
32
+ /// asynchronously by worker threads. Set to `false` for better performance if
33
+ /// you do not care about determinism.
34
+ TORCH_ARG(bool, enforce_ordering) = true;
35
+
36
+ /// Whether to omit the last batch if it contains less than `batch_size`
37
+ /// examples.
38
+ TORCH_ARG(bool, drop_last) = false;
39
+ };
40
+
41
+ /// Like `DataLoaderOptions`, but without any unconfigured state.
42
+ /// `DataLoaderOptions` has some options that depend on other options
43
+ /// (`max_jobs` => `2 * workers`). In the spirit of properly using the C++ type
44
+ /// system, `DataLoaderOptions` allows only setting values. To access values,
45
+ /// you must create a `FullDataLoaderOptions` from a `DataLoaderOptions`
46
+ /// instance, which will do any necessary coalescing.
47
+ struct FullDataLoaderOptions {
48
+ explicit FullDataLoaderOptions(DataLoaderOptions options)
49
+ : batch_size(options.batch_size()),
50
+ workers(options.workers()),
51
+ max_jobs(options.max_jobs().value_or(2 * workers)),
52
+ timeout(options.timeout()),
53
+ enforce_ordering(options.enforce_ordering()),
54
+ drop_last(options.drop_last()) {}
55
+
56
+ size_t batch_size;
57
+ size_t workers;
58
+ size_t max_jobs;
59
+ std::optional<std::chrono::milliseconds> timeout;
60
+ bool enforce_ordering;
61
+ bool drop_last;
62
+ };
63
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/datasets/base.h>
4
+ #include <torch/data/datasets/chunk.h>
5
+ #include <torch/data/datasets/map.h>
6
+ #include <torch/data/datasets/mnist.h>
7
+ #include <torch/data/datasets/shared.h>
8
+ #include <torch/data/datasets/stateful.h>
9
+ #include <torch/data/datasets/tensor.h>
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/base.h ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/example.h>
4
+ #include <torch/types.h>
5
+
6
+ #include <c10/util/ArrayRef.h>
7
+
8
+ #include <cstddef>
9
+ #include <cstdint>
10
+ #include <type_traits>
11
+ #include <utility>
12
+ #include <vector>
13
+
14
+ namespace torch::data::datasets {
15
+ template <typename S, typename T>
16
+ class MapDataset;
17
+ template <typename D, typename T>
18
+ MapDataset<D, T> map(D, T); // NOLINT
19
+ } // namespace torch::data::datasets
20
+
21
+ namespace torch::data::datasets {
22
+ namespace detail {
23
+ template <typename T>
24
+ struct is_optional : std::false_type {};
25
+ template <typename T>
26
+ struct is_optional<std::optional<T>> : std::true_type {};
27
+ } // namespace detail
28
+
29
+ /// A dataset that can yield data only in batches.
30
+ template <
31
+ typename Self,
32
+ typename Batch = std::vector<Example<>>,
33
+ typename BatchRequest = ArrayRef<size_t>>
34
+ class BatchDataset {
35
+ public:
36
+ using SelfType = Self;
37
+ using BatchType = Batch;
38
+ using BatchRequestType = BatchRequest;
39
+ constexpr static bool is_stateful = detail::is_optional<BatchType>::value;
40
+
41
+ virtual ~BatchDataset() = default;
42
+
43
+ /// Returns a batch of data given an index.
44
+ virtual Batch get_batch(BatchRequest request) = 0;
45
+
46
+ /// Returns the size of the dataset, or an empty std::optional if it is
47
+ /// unsized.
48
+ virtual std::optional<size_t> size() const = 0;
49
+
50
+ /// Creates a `MapDataset` that applies the given `transform` to this dataset.
51
+ template <typename TransformType>
52
+ MapDataset<Self, TransformType> map(TransformType transform) & {
53
+ return datasets::map(static_cast<Self&>(*this), std::move(transform));
54
+ }
55
+
56
+ /// Creates a `MapDataset` that applies the given `transform` to this dataset.
57
+ template <typename TransformType>
58
+ MapDataset<Self, TransformType> map(TransformType transform) && {
59
+ return datasets::map(
60
+ std::move(static_cast<Self&>(*this)), std::move(transform));
61
+ }
62
+ };
63
+
64
+ /// A dataset that can yield data in batches, or as individual examples.
65
+ ///
66
+ /// A `Dataset` is a `BatchDataset`, because it supports random access and
67
+ /// therefore batched access is implemented (by default) by calling the random
68
+ /// access indexing function for each index in the requested batch of indices.
69
+ /// This can be customized.
70
+ template <typename Self, typename SingleExample = Example<>>
71
+ class Dataset : public BatchDataset<Self, std::vector<SingleExample>> {
72
+ public:
73
+ using ExampleType = SingleExample;
74
+
75
+ /// Returns the example at the given index.
76
+ virtual ExampleType get(size_t index) = 0;
77
+
78
+ /// Returns a batch of data.
79
+ /// The default implementation calls `get()` for every requested index
80
+ /// in the batch.
81
+ std::vector<ExampleType> get_batch(ArrayRef<size_t> indices) override {
82
+ std::vector<ExampleType> batch;
83
+ batch.reserve(indices.size());
84
+ for (const auto i : indices) {
85
+ batch.push_back(get(i));
86
+ }
87
+ return batch;
88
+ }
89
+ };
90
+
91
+ /// A `StreamDataset` represents a dataset that is a potentially infinite
92
+ /// stream. It takes as batch index only a number, which is the batch size, and
93
+ /// yields that many elements from the stream.
94
+ template <typename Self, typename Batch = std::vector<Example<>>>
95
+ using StreamDataset = BatchDataset<Self, Batch, /*BatchRequest=*/size_t>;
96
+ } // namespace torch::data::datasets
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/chunk.h ADDED
@@ -0,0 +1,526 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <c10/util/irange.h>
4
+ #include <torch/arg.h>
5
+ #include <torch/data/datasets/stateful.h>
6
+ #include <torch/data/samplers.h>
7
+ #include <queue>
8
+ #include <thread>
9
+ #include <utility>
10
+
11
+ #include <torch/serialize.h>
12
+
13
+ namespace torch::data::datasets {
14
+
15
+ /// Interface for chunk reader, which performs data chunking and reading of
16
+ /// entire chunks.
17
+ ///
18
+ /// A chunk could be an entire file, such as an audio data file or an image,
19
+ /// or part of a file in the case of a large text-file split based on seek
20
+ /// positions.
21
+ template <
22
+ typename ExampleType_,
23
+ typename ChunkType_ = std::vector<ExampleType_>>
24
+ class ChunkDataReader {
25
+ public:
26
+ virtual ~ChunkDataReader() = default;
27
+
28
+ using ChunkType = ChunkType_;
29
+ using ExampleType = ExampleType_;
30
+
31
+ /// Read an entire chunk.
32
+ virtual ChunkType read_chunk(size_t chunk_index) = 0;
33
+
34
+ /// Returns the number of chunks available in this reader.
35
+ virtual size_t chunk_count() = 0;
36
+
37
+ /// This will clear any internal state associate with this reader.
38
+ virtual void reset() = 0;
39
+ };
40
+
41
+ namespace detail {
42
+ /// BatchDataBuffer manages a queue of UnwrappedBatchData. After a new chunk is
43
+ /// loaded, BatchDataBuffer splits it into small batches and push them into the
44
+ /// queue. When get_batch is called from data loader, it pops cached batches and
45
+ /// return. If the cache is empty, it either waits to load more chunks or return
46
+ /// null if all chunks are loaded.
47
+ template <
48
+ typename UnwrappedBatch,
49
+ typename ExampleSampler = samplers::RandomSampler>
50
+ class BatchDataBuffer {
51
+ public:
52
+ using UnwrappedBatchType = UnwrappedBatch;
53
+ using BatchType = std::optional<UnwrappedBatchType>;
54
+ using BatchRequestType = typename ExampleSampler::BatchRequestType;
55
+
56
+ BatchDataBuffer(
57
+ size_t batch_size,
58
+ ExampleSampler& example_sampler,
59
+ size_t queue_capacity)
60
+ : batch_size_(batch_size),
61
+ example_sampler_(example_sampler),
62
+ queue_capacity_(queue_capacity) {}
63
+
64
+ /// Return batch data from the queue. Called from the ChunkDataset main
65
+ /// thread.
66
+ BatchType get_batch() {
67
+ std::unique_lock<std::mutex> lock(queue_mutex_);
68
+ cv_read_.wait(lock, [this] {
69
+ // wait till there is available data in the queue or if all chunks are
70
+ // loaded (i.e. the dataset is exhausted for this epoch)
71
+ return (
72
+ this->total_example_count_in_queue_ >= batch_size_ || this->stop_);
73
+ });
74
+ if (batch_queue_.empty()) {
75
+ AT_ASSERT(stop_);
76
+ // All batches have been retrieved. Return an empty batch.
77
+ return std::nullopt;
78
+ }
79
+
80
+ UnwrappedBatchData batch = std::move(batch_queue_.front());
81
+ batch_queue_.pop();
82
+ if (batch.exception) {
83
+ throw WorkerException(batch.exception);
84
+ }
85
+
86
+ total_example_count_in_queue_ -= batch.batch_data.size();
87
+ lock.unlock();
88
+ cv_write_.notify_all();
89
+
90
+ return batch.batch_data;
91
+ }
92
+
93
+ /// Push preloaded chunks to batch queue. Called from the ChunkDataset worker
94
+ /// threads.
95
+ void add_chunk_data(UnwrappedBatchType data) {
96
+ std::unique_lock<std::mutex> lock(queue_mutex_);
97
+ cv_write_.wait(lock, [this] {
98
+ // stop loading if we have preloaded enough data.
99
+ return this->total_example_count_in_queue_ < this->queue_capacity_ ||
100
+ this->stop_;
101
+ });
102
+ if (stop_) {
103
+ // When stop_ is true, it means no further chunk loading is necessary.
104
+ // Return without any further processing.
105
+ return;
106
+ }
107
+
108
+ auto data_size = data.size();
109
+ auto remaining_size = data_size;
110
+ example_sampler_.reset(data_size);
111
+
112
+ auto fill_batch = [&](size_t example_count, UnwrappedBatchType& batch) {
113
+ auto batch_example_indices = this->example_sampler_.next(example_count);
114
+ AT_ASSERT(
115
+ batch_example_indices &&
116
+ batch_example_indices.value().size() == example_count);
117
+ BatchRequestType& indices = batch_example_indices.value();
118
+ for (size_t i : indices) {
119
+ TORCH_CHECK(i < data_size, "Index out of range");
120
+ batch.emplace_back(std::move(data[i]));
121
+ }
122
+ remaining_size -= example_count;
123
+ };
124
+
125
+ if (!batch_queue_.empty()) {
126
+ // if the queue has existing data, and the last batch doesn't have enough
127
+ // examples to fill a batch_size batch, add more example to this batch
128
+ // first.
129
+ auto& batch = batch_queue_.back();
130
+ size_t current_count = batch.batch_data.size();
131
+ if (current_count < batch_size_) {
132
+ auto example_count =
133
+ std::min(remaining_size, batch_size_ - current_count);
134
+ fill_batch(example_count, batch.batch_data);
135
+ }
136
+ }
137
+
138
+ // If we still have data remaining after filling the last pushed batch, add
139
+ // them to the queue too.
140
+ while (remaining_size > 0) {
141
+ UnwrappedBatchType current_batch;
142
+
143
+ // Allocate the batch memory ahead of time.
144
+ current_batch.reserve(batch_size_);
145
+
146
+ auto example_count = std::min(remaining_size, batch_size_);
147
+ fill_batch(example_count, current_batch);
148
+ batch_queue_.emplace(std::move(current_batch));
149
+ }
150
+ total_example_count_in_queue_ += data_size;
151
+ lock.unlock();
152
+ cv_read_.notify_all();
153
+ }
154
+
155
+ /// Push exceptions thrown during preloading into batch queue. Called from
156
+ /// the ChunkDataset worker threads.
157
+ void add_chunk_data(std::exception_ptr e_ptr) {
158
+ std::unique_lock<std::mutex> lock(queue_mutex_);
159
+ cv_write_.wait(lock, [this] {
160
+ // stop loading if we have preloaded enough data.
161
+ return (
162
+ this->total_example_count_in_queue_ < this->queue_capacity_ ||
163
+ this->stop_);
164
+ });
165
+ if (stop_) {
166
+ // When stop_ is true, it means this current thread needs to be tore down,
167
+ // the batch buffer will be discarded, so no need to enqueue any new
168
+ // exceptions.
169
+ return;
170
+ }
171
+
172
+ batch_queue_.emplace(e_ptr);
173
+ lock.unlock();
174
+ cv_read_.notify_all();
175
+ }
176
+
177
+ void stop() {
178
+ {
179
+ // Hold the lock before changing stop_ to prevent a race condition which
180
+ // can cause a deadlock. To be more specific, conditional variable
181
+ // cv_write_ waits on predicate stop_ in add_chunk_data(). The wait
182
+ // happens in two steps: 1) while still holding the lock, check if
183
+ // predicate is true; 2) if it is true, proceeds, otherwise, release the
184
+ // lock and wait until notified. Without holding a lock, cv_write_'s
185
+ // notification can happen in between step 1) and 2). In that case, as
186
+ // cv_write_ is not in waiting status yet, so the notification is lost and
187
+ // cv_write_ will sleep forever. By taking a lock before changing
188
+ // predicate stop_, it is ensured updating and evaluating stop_ always
189
+ // happen in a synchronized way
190
+ std::lock_guard<std::mutex> lock(queue_mutex_);
191
+ stop_ = true;
192
+ }
193
+
194
+ // notify all writers, wake them from wait to exit current method.
195
+ cv_write_.notify_all();
196
+ // notify all readers too.
197
+ cv_read_.notify_all();
198
+ }
199
+ /// The batch size is needed to create batches from the chunk data. Similar to
200
+ /// regular dataloader where the batches are created with prefetches,
201
+ /// BatchDataBuffer perform the batch creation using the provided batch size.
202
+ size_t batch_size_ = 0;
203
+
204
+ /// count of total example stored in the queue
205
+ size_t total_example_count_in_queue_ = 0;
206
+
207
+ /// struct that contains a raw unwrapped batch unit. An unwrapped batch unit
208
+ /// is the raw data without 'optional' wrapper. It can be a collection of
209
+ /// images, utterances, e.t.c.
210
+ struct UnwrappedBatchData {
211
+ explicit UnwrappedBatchData(UnwrappedBatchType data)
212
+ : batch_data(std::move(data)) {}
213
+
214
+ explicit UnwrappedBatchData(std::exception_ptr e)
215
+ : exception(std::move(e)) {}
216
+
217
+ /// batch data to return
218
+ UnwrappedBatchType batch_data;
219
+
220
+ /// exception pointer which captures any abnormal exceptions while creating
221
+ /// the batch.
222
+ std::exception_ptr exception;
223
+ };
224
+
225
+ /// local cache to store example batches from loaded chunk
226
+ std::queue<UnwrappedBatchData> batch_queue_;
227
+
228
+ // sync batch_queue_ update.
229
+ std::mutex queue_mutex_;
230
+
231
+ std::condition_variable cv_read_;
232
+ std::condition_variable cv_write_;
233
+
234
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
235
+ ExampleSampler& example_sampler_;
236
+
237
+ // configurable maximun number of elements the queue can hold at one time.
238
+ size_t queue_capacity_;
239
+
240
+ // When set to true, it wakes the writer threads from the wait and exit
241
+ // current function call. This is needed when ChunkDataSet.Reset is called
242
+ // while the previous epoch is not exhausted yet. When ChunkDataset is waiting
243
+ // its preloader to finish previous work before tearing down the thread, the
244
+ // preloader could be still waiting for the conditional variable, thus cause
245
+ // the program to hang. This boolean is used to break this waiting condition.
246
+ bool stop_ = false;
247
+ };
248
+ } // namespace detail
249
+
250
+ /// Options to configure a `ChunkDataset`.
251
+ struct ChunkDatasetOptions {
252
+ ChunkDatasetOptions() = delete;
253
+ ChunkDatasetOptions(
254
+ size_t preloader_count,
255
+ size_t batch_size,
256
+ size_t cache_size = 2048,
257
+ size_t cross_chunk_shuffle_count = 1)
258
+ : preloader_count_(preloader_count),
259
+ batch_size_(batch_size),
260
+ cache_size_(cache_size),
261
+ cross_chunk_shuffle_count_(cross_chunk_shuffle_count) {
262
+ TORCH_CHECK(
263
+ preloader_count_ > 0,
264
+ "Preloader count is 0. At least one preloader needs to be specified.");
265
+ TORCH_CHECK(
266
+ batch_size_ > 0,
267
+ "Batch size is 0. A positive batch size needs to be specified.");
268
+ TORCH_CHECK(
269
+ cache_size_ > 0,
270
+ "Cache size is 0. A positive cache size needs to be specified.");
271
+ TORCH_CHECK(
272
+ cache_size_ >= batch_size_,
273
+ "Cache size is less than batch size. Cache needs to be large enough to "
274
+ "hold at least one batch.");
275
+ TORCH_CHECK(
276
+ cross_chunk_shuffle_count_ > 0,
277
+ "cross_chunk_shuffle_count needs to be greater than 0.");
278
+ }
279
+
280
+ /// The number of worker thread to preload chunk data.
281
+ TORCH_ARG(size_t, preloader_count);
282
+
283
+ /// The size of each batch.
284
+ TORCH_ARG(size_t, batch_size);
285
+
286
+ /// The capacity of the queue for batch caching.
287
+ TORCH_ARG(size_t, cache_size) = 2048;
288
+
289
+ // The number of chunks to perfrom cross-chunk shuffling. Default to 1 meaning
290
+ // no cross-chunk shuffling. When it is equal to n (n > 1), n random
291
+ // chunks will be loaded at once and example shuffling will be performed
292
+ // across all those n chunks.
293
+ // Note: Usually the default config (1 chunk shuffle + example shuffle) is
294
+ // good enough to generate random distributed data. Use this parameter only if
295
+ // you know cross-shuffle is needed in your case. Also there is a performance
296
+ // penalty when this value is greater than 1, as we need to do extra merge
297
+ // between multiple chunks before performing example sampling.
298
+ TORCH_ARG(size_t, cross_chunk_shuffle_count) = 1;
299
+ };
300
+
301
+ /// A stateful dataset that support hierarchical sampling and prefetching of
302
+ /// entre chunks.
303
+ ///
304
+ /// Unlike regular dataset, chunk dataset require two samplers to operate and
305
+ /// keeps an internal state. `ChunkSampler` selects, which chunk to load next,
306
+ /// while the `ExampleSampler` determins the order of Examples that are returned
307
+ /// in each `get_batch` call. The hierarchical sampling approach used here is
308
+ /// inspired by this paper http://martin.zinkevich.org/publications/nips2010.pdf
309
+ template <
310
+ typename ChunkReader,
311
+ typename ChunkSampler = samplers::RandomSampler,
312
+ typename ExampleSampler = samplers::RandomSampler>
313
+ class ChunkDataset final
314
+ : public StatefulDataset<
315
+ ChunkDataset<ChunkReader, ChunkSampler, ExampleSampler>,
316
+ typename ChunkReader::BatchType,
317
+ size_t> {
318
+ public:
319
+ using BatchType = std::optional<typename ChunkReader::BatchType>;
320
+ using UnwrappedBatchType = typename ChunkReader::BatchType;
321
+ using BatchRequestType = size_t;
322
+ using ChunkSamplerType = ChunkSampler;
323
+ using ExampleSamplerType = ExampleSampler;
324
+
325
+ ChunkDataset(
326
+ ChunkReader chunk_reader,
327
+ ChunkSampler chunk_sampler,
328
+ ExampleSampler example_sampler,
329
+ ChunkDatasetOptions options,
330
+ std::function<void(UnwrappedBatchType&)> preprocessing_policy =
331
+ std::function<void(UnwrappedBatchType&)>())
332
+ : chunk_reader_(std::move(chunk_reader)),
333
+ chunk_sampler_(std::move(chunk_sampler)),
334
+ example_sampler_(std::move(example_sampler)),
335
+ options_(options),
336
+ preprocessing_policy_(std::move(preprocessing_policy)),
337
+ quit_worker_(false),
338
+ running_preloaders_(0) {}
339
+
340
+ ~ChunkDataset() override {
341
+ // stop batch buffer first.
342
+ if (batch_buffer_) {
343
+ batch_buffer_->stop();
344
+ }
345
+ free_workers();
346
+ }
347
+
348
+ /// Default get_batch method of BatchDataset. This method returns
349
+ /// Example batches created from the preloaded chunks. The implemenation
350
+ /// is dataset agnostic and does not need overriding in different chunk
351
+ /// datasets.
352
+ BatchType get_batch(size_t batch_size) override {
353
+ TORCH_CHECK(
354
+ batch_buffer_ != nullptr,
355
+ "Dataset needs to call reset() before calling get_batch().");
356
+
357
+ TORCH_CHECK(
358
+ batch_size == options_.batch_size(),
359
+ "The requested batch size does not match with the initialized batch size.\n"
360
+ " The requested batch size is ",
361
+ batch_size,
362
+ ", while the dataset is created with batch size equal to ",
363
+ options_.batch_size());
364
+ return batch_buffer_->get_batch();
365
+ }
366
+
367
+ /// Helper method around get_batch as `batch_size` is not strictly necessary
368
+ BatchType get_batch() {
369
+ return get_batch(options_.batch_size());
370
+ }
371
+
372
+ /// This will clear any internal state and starts the internal prefetching
373
+ /// mechanism for the chunk dataset.
374
+ void reset() override {
375
+ // We need this to support partial data reads via dataloader iterator.
376
+ if (batch_buffer_) {
377
+ batch_buffer_->stop();
378
+ }
379
+ // free workers from previous reset if there is any.
380
+ free_workers();
381
+ preload_threads_.clear();
382
+
383
+ if (!load_checkpoint_) {
384
+ chunk_reader_.reset();
385
+ chunk_sampler_.reset(chunk_reader_.chunk_count());
386
+ load_checkpoint_ = false;
387
+ }
388
+
389
+ // Throw out any existing cached batch in the buffer and re-creates a new
390
+ // chunk buffer.
391
+ batch_buffer_ = std::make_unique<
392
+ detail::BatchDataBuffer<UnwrappedBatchType, ExampleSamplerType>>(
393
+ options_.batch_size(), example_sampler_, options_.cache_size());
394
+
395
+ // create new workers for this new epoch.
396
+ quit_worker_ = false;
397
+
398
+ AT_ASSERT(running_preloaders_ == 0);
399
+ running_preloaders_ = options_.preloader_count();
400
+ for (const auto i : c10::irange(options_.preloader_count())) {
401
+ preload_threads_.emplace_back([this, i]() { this->preloader(i); });
402
+ }
403
+ }
404
+
405
+ /// size is not used for chunk dataset.
406
+ std::optional<size_t> size() const override {
407
+ return std::nullopt;
408
+ }
409
+
410
+ // provide a references to chunk sampler. Used mainly in distributed data
411
+ // loading to set the epoch number for the sampler.
412
+ ChunkSamplerType& chunk_sampler() {
413
+ return chunk_sampler_;
414
+ }
415
+
416
+ void save(serialize::OutputArchive& archive) const override {
417
+ std::lock_guard<std::mutex> lock(chunk_index_guard_);
418
+ chunk_sampler_.save(archive);
419
+ }
420
+
421
+ void load(serialize::InputArchive& archive) override {
422
+ std::lock_guard<std::mutex> lock(chunk_index_guard_);
423
+ chunk_sampler_.load(archive);
424
+ load_checkpoint_ = true;
425
+ }
426
+
427
+ private:
428
+ /// running on worker thread to preload chunk data.
429
+ void preloader(size_t id) {
430
+ while (!quit_worker_.load()) {
431
+ try {
432
+ std::vector<size_t> chunk_idx;
433
+ {
434
+ std::lock_guard<std::mutex> lock(chunk_index_guard_);
435
+ if (auto chunk_sampler_result = chunk_sampler_.next(
436
+ this->options_.cross_chunk_shuffle_count())) {
437
+ chunk_idx = chunk_sampler_result.value();
438
+ } else {
439
+ break;
440
+ }
441
+ }
442
+ UnwrappedBatchType data = chunk_reader_.read_chunk(chunk_idx[0]);
443
+ for (const auto i : c10::irange(1, chunk_idx.size())) {
444
+ auto chunk_data = chunk_reader_.read_chunk(chunk_idx[i]);
445
+ std::move(
446
+ chunk_data.begin(), chunk_data.end(), std::back_inserter(data));
447
+ }
448
+ if (preprocessing_policy_) {
449
+ preprocessing_policy_(data);
450
+ }
451
+ if (!data.empty()) { // skip empty chunks.
452
+ batch_buffer_->add_chunk_data(std::move(data));
453
+ }
454
+ } catch (...) {
455
+ batch_buffer_->add_chunk_data(std::current_exception());
456
+ }
457
+ }
458
+ AT_ASSERT(running_preloaders_.load() > 0);
459
+ --running_preloaders_;
460
+ if (running_preloaders_.load() == 0) {
461
+ // all preloaders are completed, so we can notify the batch_buffer.
462
+ batch_buffer_->stop();
463
+ }
464
+ }
465
+
466
+ /// Block the current thread until the workers finish execution and exit.
467
+ void free_workers() {
468
+ if (!quit_worker_.load()) {
469
+ quit_worker_ = true;
470
+ for (auto& worker_thread : preload_threads_) {
471
+ worker_thread.join();
472
+ }
473
+ }
474
+ }
475
+
476
+ private:
477
+ // Templated class that defines what is a chunk and how to read chunk data.
478
+ // When a chunk is returned by chunk_reader_, ChunkDataset split it into
479
+ // batches and caches them in batch_buffer_.
480
+ ChunkReader chunk_reader_;
481
+
482
+ // chunk sampler to shuffle different chunks
483
+ ChunkSamplerType chunk_sampler_;
484
+
485
+ // example sampler to shuffle examples in a specific chunk
486
+ ExampleSamplerType example_sampler_;
487
+
488
+ // batch data buffer which holds chunk data from preloading thread.
489
+ std::shared_ptr<
490
+ detail::BatchDataBuffer<UnwrappedBatchType, ExampleSamplerType>>
491
+ batch_buffer_;
492
+
493
+ // worker thread pool
494
+ std::vector<std::thread> preload_threads_;
495
+
496
+ /// The options the Dataset was configured with.
497
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-const-or-ref-data-members)
498
+ const ChunkDatasetOptions options_;
499
+
500
+ // function pointer wrapper to apply custom processing over chunk data. This
501
+ // is considered an advanced parameter for developers who want to apply a
502
+ // pre-process to the chunk data before sampling into minibatch.
503
+ // Different than the collate function, this policy is applied on the chunk
504
+ // level, instead of minibatch level. When a chunk of data is loaded (multiple
505
+ // chunks if cross_chunk_shuffle_count_ is greater than 1), this policy is
506
+ // applied to the full loaded data. It is useful if developers want to
507
+ // perform pre-processing (like bucketing) to the chunk data before
508
+ // example sampler samples the data. By default it's an empty pointer and no
509
+ // action will be taken.
510
+ std::function<void(UnwrappedBatchType&)> preprocessing_policy_;
511
+
512
+ // indicate whether the worker thread can be teared down
513
+ std::atomic<bool> quit_worker_;
514
+
515
+ // keep track of running preloaders to notify batch buffer. A value 0
516
+ // indicates that the chunk loading is completed.
517
+ std::atomic<size_t> running_preloaders_;
518
+
519
+ // mutex to synchronize chunk sampler next() call.
520
+ mutable std::mutex chunk_index_guard_;
521
+
522
+ // boolean value to indicate whether we need to load the checkpoint for
523
+ // chunk_sampler_.
524
+ bool load_checkpoint_{false};
525
+ };
526
+ } // namespace torch::data::datasets
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/map.h ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/datasets/base.h>
4
+ #include <torch/types.h>
5
+
6
+ #include <c10/util/ArrayRef.h>
7
+
8
+ #include <cstddef>
9
+ #include <type_traits>
10
+ #include <utility>
11
+
12
+ namespace torch::data::datasets {
13
+ namespace detail {
14
+ template <bool C, typename T>
15
+ using optional_if_t = std::conditional_t<C, std::optional<T>, T>;
16
+ } // namespace detail
17
+
18
+ /// A `MapDataset` is a dataset that applies a transform to a source dataset.
19
+ template <typename SourceDataset, typename AppliedTransform>
20
+ class MapDataset : public BatchDataset<
21
+ MapDataset<SourceDataset, AppliedTransform>,
22
+ detail::optional_if_t<
23
+ SourceDataset::is_stateful,
24
+ typename AppliedTransform::OutputBatchType>,
25
+ typename SourceDataset::BatchRequestType> {
26
+ public:
27
+ using DatasetType = SourceDataset;
28
+ using TransformType = AppliedTransform;
29
+ using BatchRequestType = typename SourceDataset::BatchRequestType;
30
+ using OutputBatchType = detail::optional_if_t<
31
+ SourceDataset::is_stateful,
32
+ typename AppliedTransform::OutputBatchType>;
33
+
34
+ MapDataset(DatasetType dataset, TransformType transform)
35
+ : dataset_(std::move(dataset)), transform_(std::move(transform)) {}
36
+
37
+ /// Gets a batch from the source dataset and applies the transform to it,
38
+ /// returning the result.
39
+ OutputBatchType get_batch(BatchRequestType indices) override {
40
+ return get_batch_impl(std::move(indices));
41
+ }
42
+
43
+ /// Returns the size of the source dataset.
44
+ // NOLINTNEXTLINE(bugprone-exception-escape)
45
+ std::optional<size_t> size() const noexcept override {
46
+ return dataset_.size();
47
+ }
48
+
49
+ /// Calls `reset()` on the underlying dataset.
50
+ /// NOTE: Stateless datasets do not have a reset() method, so a call to this
51
+ /// method will only compile for stateful datasets (which have a reset()
52
+ /// method).
53
+ void reset() {
54
+ dataset_.reset();
55
+ }
56
+
57
+ /// Returns the underlying dataset.
58
+ const SourceDataset& dataset() noexcept {
59
+ return dataset_;
60
+ }
61
+
62
+ /// Returns the transform being applied.
63
+ const AppliedTransform& transform() noexcept {
64
+ return transform_;
65
+ }
66
+
67
+ private:
68
+ /// The implementation of `get_batch()` for the stateless case, which simply
69
+ /// applies the transform to the output of `get_batch()` from the dataset.
70
+ template <
71
+ typename D = SourceDataset,
72
+ typename = std::enable_if_t<!D::is_stateful>>
73
+ OutputBatchType get_batch_impl(BatchRequestType indices) {
74
+ return transform_.apply_batch(dataset_.get_batch(std::move(indices)));
75
+ }
76
+
77
+ /// The implementation of `get_batch()` for the stateful case. Here, we follow
78
+ /// the semantics of `Optional.map()` in many functional languages, which
79
+ /// applies a transformation to the optional's content when the optional
80
+ /// contains a value, and returns a new optional (of a different type) if the
81
+ /// original optional returned by `get_batch()` was empty.
82
+ template <typename D = SourceDataset>
83
+ std::enable_if_t<D::is_stateful, OutputBatchType> get_batch_impl(
84
+ BatchRequestType indices) {
85
+ if (auto batch = dataset_.get_batch(std::move(indices))) {
86
+ return transform_.apply_batch(std::move(*batch));
87
+ }
88
+ return std::nullopt;
89
+ }
90
+
91
+ /// The underlying dataset being transformed.
92
+ SourceDataset dataset_;
93
+
94
+ // The transformation that is applied to batches received from the dataset.
95
+ AppliedTransform transform_;
96
+ };
97
+
98
+ /// Creates a `MapDataset` with the given dataset and transform.
99
+ template <typename DatasetType, typename TransformType>
100
+ MapDataset<DatasetType, TransformType> map(
101
+ DatasetType dataset,
102
+ TransformType transform) {
103
+ static_assert(
104
+ std::is_same_v<
105
+ std::conditional_t<
106
+ DatasetType::is_stateful,
107
+ typename DatasetType::BatchType::value_type,
108
+ typename DatasetType::BatchType>,
109
+ typename TransformType::InputBatchType>,
110
+ "BatchType type of dataset does not match input type of transform");
111
+ return {std::move(dataset), std::move(transform)};
112
+ }
113
+
114
+ } // namespace torch::data::datasets
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/mnist.h ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/datasets/base.h>
4
+ #include <torch/data/example.h>
5
+ #include <torch/types.h>
6
+
7
+ #include <torch/csrc/Export.h>
8
+
9
+ #include <cstddef>
10
+ #include <string>
11
+
12
+ namespace torch::data::datasets {
13
+ /// The MNIST dataset.
14
+ class TORCH_API MNIST : public Dataset<MNIST> {
15
+ public:
16
+ /// The mode in which the dataset is loaded.
17
+ enum class Mode { kTrain, kTest };
18
+
19
+ /// Loads the MNIST dataset from the `root` path.
20
+ ///
21
+ /// The supplied `root` path should contain the *content* of the unzipped
22
+ /// MNIST dataset, available from http://yann.lecun.com/exdb/mnist.
23
+ explicit MNIST(const std::string& root, Mode mode = Mode::kTrain);
24
+
25
+ /// Returns the `Example` at the given `index`.
26
+ Example<> get(size_t index) override;
27
+
28
+ /// Returns the size of the dataset.
29
+ std::optional<size_t> size() const override;
30
+
31
+ /// Returns true if this is the training subset of MNIST.
32
+ // NOLINTNEXTLINE(bugprone-exception-escape)
33
+ bool is_train() const noexcept;
34
+
35
+ /// Returns all images stacked into a single tensor.
36
+ const Tensor& images() const;
37
+
38
+ /// Returns all targets stacked into a single tensor.
39
+ const Tensor& targets() const;
40
+
41
+ private:
42
+ Tensor images_, targets_;
43
+ };
44
+ } // namespace torch::data::datasets
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/shared.h ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/datasets/base.h>
4
+
5
+ #include <memory>
6
+ #include <utility>
7
+
8
+ namespace torch::data::datasets {
9
+
10
+ /// A dataset that wraps another dataset in a shared pointer and implements the
11
+ /// `BatchDataset` API, delegating all calls to the shared instance. This is
12
+ /// useful when you want all worker threads in the dataloader to access the same
13
+ /// dataset instance. The dataset must take care of synchronization and
14
+ /// thread-safe access itself.
15
+ ///
16
+ /// Use `torch::data::datasets::make_shared_dataset()` to create a new
17
+ /// `SharedBatchDataset` like you would a `std::shared_ptr`.
18
+ template <typename UnderlyingDataset>
19
+ class SharedBatchDataset : public BatchDataset<
20
+ SharedBatchDataset<UnderlyingDataset>,
21
+ typename UnderlyingDataset::BatchType,
22
+ typename UnderlyingDataset::BatchRequestType> {
23
+ public:
24
+ using BatchType = typename UnderlyingDataset::BatchType;
25
+ using BatchRequestType = typename UnderlyingDataset::BatchRequestType;
26
+
27
+ /// Constructs a new `SharedBatchDataset` from a `shared_ptr` to the
28
+ /// `UnderlyingDataset`.
29
+ /* implicit */ SharedBatchDataset(
30
+ std::shared_ptr<UnderlyingDataset> shared_dataset)
31
+ : dataset_(std::move(shared_dataset)) {}
32
+
33
+ /// Calls `get_batch` on the underlying dataset.
34
+ BatchType get_batch(BatchRequestType request) override {
35
+ return dataset_->get_batch(std::move(request));
36
+ }
37
+
38
+ /// Returns the `size` from the underlying dataset.
39
+ std::optional<size_t> size() const override {
40
+ return dataset_->size();
41
+ }
42
+
43
+ /// Accesses the underlying dataset.
44
+ UnderlyingDataset& operator*() {
45
+ return *dataset_;
46
+ }
47
+
48
+ /// Accesses the underlying dataset.
49
+ const UnderlyingDataset& operator*() const {
50
+ return *dataset_;
51
+ }
52
+
53
+ /// Accesses the underlying dataset.
54
+ UnderlyingDataset* operator->() {
55
+ return dataset_.get();
56
+ }
57
+
58
+ /// Accesses the underlying dataset.
59
+ const UnderlyingDataset* operator->() const {
60
+ return dataset_.get();
61
+ }
62
+
63
+ /// Calls `reset()` on the underlying dataset.
64
+ void reset() {
65
+ dataset_->reset();
66
+ }
67
+
68
+ private:
69
+ std::shared_ptr<UnderlyingDataset> dataset_;
70
+ };
71
+
72
+ /// Constructs a new `SharedBatchDataset` by creating a
73
+ /// `shared_ptr<UnderlyingDatase>`. All arguments are forwarded to
74
+ /// `make_shared<UnderlyingDataset>`.
75
+ template <typename UnderlyingDataset, typename... Args>
76
+ SharedBatchDataset<UnderlyingDataset> make_shared_dataset(Args&&... args) {
77
+ return std::make_shared<UnderlyingDataset>(std::forward<Args>(args)...);
78
+ }
79
+ } // namespace torch::data::datasets
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/stateful.h ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/datasets/base.h>
4
+ #include <torch/data/example.h>
5
+
6
+ #include <cstddef>
7
+ #include <vector>
8
+
9
+ namespace torch::serialize {
10
+ class OutputArchive;
11
+ class InputArchive;
12
+ } // namespace torch::serialize
13
+
14
+ namespace torch::data::datasets {
15
+
16
+ /// A stateful dataset is a dataset that maintains some internal state, which
17
+ /// will be `reset()` at the beginning of each epoch. Subclasses can override
18
+ /// the `reset()` method to configure this behavior. Further, the return type of
19
+ /// a stateful dataset's `get_batch()` method is always an `optional`. When the
20
+ /// stateful dataset wants to indicate to the dataloader that its epoch has
21
+ /// ended, it should return an empty optional. The dataloader knows to modify
22
+ /// its implementation based on whether the dataset is stateless or stateful.
23
+ ///
24
+ /// Note that when subclassing a from `StatefulDataset<Self, T>`, the return
25
+ /// type of `get_batch()`, which the subclass must override, will be
26
+ /// `optional<T>` (i.e. the type specified in the `StatefulDataset`
27
+ /// specialization is automatically boxed into an `optional` for the dataset's
28
+ /// `BatchType`).
29
+ template <
30
+ typename Self,
31
+ typename Batch = std::vector<Example<>>,
32
+ typename BatchRequest = size_t>
33
+ class StatefulDataset
34
+ : public BatchDataset<Self, std::optional<Batch>, BatchRequest> {
35
+ public:
36
+ /// Resets internal state of the dataset.
37
+ virtual void reset() = 0;
38
+
39
+ /// Saves the statefulDataset's state to OutputArchive.
40
+ virtual void save(serialize::OutputArchive& archive) const = 0;
41
+
42
+ /// Deserializes the statefulDataset's state from the `archive`.
43
+ virtual void load(serialize::InputArchive& archive) = 0;
44
+ };
45
+
46
+ /// Serializes a statefulDataset to `OutputArchive`.
47
+ template <typename... Args>
48
+ serialize::OutputArchive& operator<<(
49
+ serialize::OutputArchive& archive,
50
+ const StatefulDataset<Args...>& statefulDataset) {
51
+ statefulDataset.save(archive);
52
+ return archive;
53
+ }
54
+
55
+ /// Deserializes a statefulDataset from an `InputArchive`.
56
+ template <typename... Args>
57
+ serialize::InputArchive& operator>>(
58
+ serialize::InputArchive& archive,
59
+ StatefulDataset<Args...>& statefulDataset) {
60
+ statefulDataset.load(archive);
61
+ return archive;
62
+ }
63
+
64
+ } // namespace torch::data::datasets
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/tensor.h ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/datasets/base.h>
4
+ #include <torch/data/example.h>
5
+ #include <torch/types.h>
6
+
7
+ #include <cstddef>
8
+ #include <vector>
9
+
10
+ namespace torch::data::datasets {
11
+
12
+ /// A dataset of tensors.
13
+ /// Stores a single tensor internally, which is then indexed inside `get()`.
14
+ struct TensorDataset : public Dataset<TensorDataset, TensorExample> {
15
+ /// Creates a `TensorDataset` from a vector of tensors.
16
+ explicit TensorDataset(const std::vector<Tensor>& tensors)
17
+ : TensorDataset(torch::stack(tensors)) {}
18
+
19
+ explicit TensorDataset(torch::Tensor tensor) : tensor(std::move(tensor)) {}
20
+
21
+ /// Returns a single `TensorExample`.
22
+ TensorExample get(size_t index) override {
23
+ return tensor[static_cast<int64_t>(index)];
24
+ }
25
+
26
+ /// Returns the number of tensors in the dataset.
27
+ std::optional<size_t> size() const override {
28
+ return tensor.size(0);
29
+ }
30
+
31
+ Tensor tensor;
32
+ };
33
+
34
+ } // namespace torch::data::datasets
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/data_shuttle.h ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/detail/queue.h>
4
+ #include <torch/types.h>
5
+
6
+ #include <c10/util/Exception.h>
7
+ #include <optional>
8
+
9
+ #include <chrono>
10
+ #include <utility>
11
+
12
+ namespace torch::data::detail {
13
+
14
+ /// Encapsulates the full life cycle of DataLoader jobs.
15
+ ///
16
+ /// When a new job is enqueued to the `DataShuttle`, a counter for in-flight
17
+ /// jobs is bumped. This job is said to be "in-flight" until its result is
18
+ /// popped. Worker threads dequeue jobs as soon as they are available. When a
19
+ /// worker finishes a job, it enqueues the result. Only when the main thread
20
+ /// dequeues a result is the count of in-flight jobs decremented. When the main
21
+ /// thread attempts to dequeue a job but no jobs are in-flight, that means the
22
+ /// epoch is complete and `pop_result` returns an empty optional.
23
+ template <typename Job, typename Result>
24
+ class DataShuttle {
25
+ public:
26
+ /// Pushes a new job. Called by the main thread.
27
+ void push_job(Job job) {
28
+ new_jobs_.push(std::move(job));
29
+ ++in_flight_jobs_;
30
+ }
31
+
32
+ /// Pushes the result of a job. Called by worker threads.
33
+ void push_result(Result result) {
34
+ results_.push(std::move(result));
35
+ }
36
+
37
+ /// Returns the next job, blocking until there is one available. Called by
38
+ /// worker threads.
39
+ Job pop_job() {
40
+ return new_jobs_.pop();
41
+ }
42
+
43
+ /// Returns the result of a job, or nullopt if all jobs were exhausted. Called
44
+ /// by the main thread.
45
+ std::optional<Result> pop_result(
46
+ std::optional<std::chrono::milliseconds> timeout = std::nullopt) {
47
+ if (in_flight_jobs_ > 0) {
48
+ auto result = results_.pop(timeout);
49
+ --in_flight_jobs_;
50
+ return result;
51
+ }
52
+ return std::nullopt;
53
+ }
54
+
55
+ /// Discards any jobs that are not yet in flight, and waits for all in-flight
56
+ /// jobs to finish, discarding their result.
57
+ void drain() {
58
+ // Clear all inputs so that no further jobs are scheduled.
59
+ auto number_cleared = new_jobs_.clear();
60
+ in_flight_jobs_ -= number_cleared;
61
+ // Remove any outstanding results.
62
+ while (in_flight_jobs_ > 0) {
63
+ pop_result();
64
+ }
65
+ }
66
+
67
+ /// Returns the number of jobs that are still in progress.
68
+ /// When this number is zero, an epoch is finished.
69
+ size_t in_flight_jobs() const noexcept {
70
+ return in_flight_jobs_;
71
+ }
72
+
73
+ private:
74
+ /// The queue for jobs that are not yet in flight.
75
+ Queue<Job> new_jobs_;
76
+ /// The number of in-flight jobs.
77
+ /// NOTE: Not atomic because only manipulated by the main thread.
78
+ size_t in_flight_jobs_ = 0;
79
+ /// The queue for results of finished jobs.
80
+ Queue<Result> results_;
81
+ };
82
+
83
+ } // namespace torch::data::detail
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/queue.h ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/types.h>
4
+
5
+ #include <c10/util/Exception.h>
6
+
7
+ #include <chrono>
8
+ #include <condition_variable>
9
+ #include <cstddef>
10
+ #include <mutex>
11
+ #include <queue>
12
+
13
+ namespace torch::data::detail {
14
+
15
+ /// A basic locked, blocking MPMC queue.
16
+ ///
17
+ /// Every `push` and `pop` is guarded by a mutex. A condition variable is used
18
+ /// to communicate insertion of new elements, such that waiting threads will be
19
+ /// woken up if they are currently waiting inside a call to `pop()`.
20
+ ///
21
+ /// Note that this data structure is written specifically for use with the
22
+ /// `DataLoader`. Its behavior is tailored to this use case and may not be
23
+ /// applicable to more general uses.
24
+ template <typename T>
25
+ class Queue {
26
+ public:
27
+ /// Pushes a new value to the back of the `Queue` and notifies one thread on
28
+ /// the waiting side about this event.
29
+ void push(T value) {
30
+ {
31
+ std::lock_guard<std::mutex> lock(mutex_);
32
+ queue_.push(std::move(value));
33
+ }
34
+ cv_.notify_one();
35
+ }
36
+
37
+ /// Blocks until at least one element is ready to be popped from the front of
38
+ /// the queue. An optional `timeout` in seconds can be used to limit the time
39
+ /// spent waiting for an element. If the wait times out, an exception is
40
+ /// raised.
41
+ T pop(std::optional<std::chrono::milliseconds> timeout = std::nullopt) {
42
+ std::unique_lock<std::mutex> lock(mutex_);
43
+ if (timeout) {
44
+ if (!cv_.wait_for(
45
+ lock, *timeout, [this] { return !this->queue_.empty(); })) {
46
+ // clang-format off
47
+ TORCH_CHECK(false,
48
+ "Timeout in DataLoader queue while waiting for next batch"
49
+ " (timeout was ", timeout->count(), " ms)");
50
+ // clang-format on
51
+ }
52
+ } else {
53
+ cv_.wait(lock, [this] { return !this->queue_.empty(); });
54
+ }
55
+ AT_ASSERT(!queue_.empty());
56
+ T value = queue_.front();
57
+ queue_.pop();
58
+ lock.unlock();
59
+ return value;
60
+ }
61
+
62
+ /// Empties the queue and returns the number of elements that were present at
63
+ /// the start of the function. No threads are notified about this event as it
64
+ /// is assumed to be used to drain the queue during shutdown of a
65
+ /// `DataLoader`.
66
+ size_t clear() {
67
+ std::lock_guard<std::mutex> lock(this->mutex_);
68
+ const auto size = queue_.size();
69
+ while (!queue_.empty()) {
70
+ queue_.pop();
71
+ }
72
+ return size;
73
+ }
74
+
75
+ private:
76
+ std::queue<T> queue_;
77
+ std::mutex mutex_;
78
+ std::condition_variable cv_;
79
+ };
80
+ } // namespace torch::data::detail
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/sequencers.h ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/types.h>
4
+
5
+ #include <algorithm>
6
+ #include <cstddef>
7
+ #include <vector>
8
+
9
+ namespace torch::data::detail::sequencers {
10
+ namespace detail {
11
+ template <typename Result>
12
+ bool buffer_contains_result(const std::vector<std::optional<Result>>& buffer) {
13
+ return std::any_of(
14
+ buffer.begin(), buffer.end(), [](const std::optional<Result>& result) {
15
+ return result.has_value();
16
+ });
17
+ }
18
+ } // namespace detail
19
+
20
+ /// A `Sequencer` accepts a function that yields the next result of a
21
+ /// `DataLoader` and then has the opportunity to influence the order in which
22
+ /// these results are returned. The `NoSequencer` does not enforce any
23
+ /// sequencing and returns any result directly. The `OrderedSequencer` instead
24
+ /// buffers results internally to return them in order of their sequence number.
25
+ template <typename Result>
26
+ struct Sequencer {
27
+ using ResultProducer = std::function<std::optional<Result>()>;
28
+ virtual ~Sequencer() = default;
29
+ virtual std::optional<Result> next(ResultProducer next_result) = 0;
30
+ };
31
+
32
+ /// A `Sequencer` that does not enforce any ordering. It is effectively the
33
+ /// identity function.
34
+ template <typename Result>
35
+ struct NoSequencer final : public Sequencer<Result> {
36
+ using typename Sequencer<Result>::ResultProducer;
37
+ std::optional<Result> next(ResultProducer next_result) override {
38
+ return next_result();
39
+ }
40
+ };
41
+
42
+ /// A `Sequencer` that buffers results and returns them in order of their
43
+ /// sequence number. The `OrderedSequencer` maintains an internal, monotonically
44
+ /// incrementing counter for the next sequence number it expects. If it receives
45
+ /// a result with a higher sequence number, it will buffer it for later (when
46
+ /// the sequence number reaches that of this result). Otherwise, if the sequence
47
+ /// numbers match, the result is returned.
48
+ ///
49
+ /// Implementation note: The `OrderedSequencer` is implemented with a fixed-size
50
+ /// buffer. Let `m` be the maximum number of jobs in the data loader's queue and
51
+ /// `s` be the current sequence number. Assume `m` jobs are scheduled in the
52
+ /// `DataLoader`. Any new result is stored at index `job.sqn mod m` in the
53
+ /// `OrderedSequencer`. Why are we sure sequence numbers of new jobs will not
54
+ /// collide with sequence numbers of buffered jobs? The `OrderedSequencer` will
55
+ /// not return from `next()` until it receives the result with sqn `s`. This
56
+ /// means no new jobs can be scheduled in the `DataLoader` in the meantime,
57
+ /// which enforces that as long as sqn `s` has not been received, `s + m` (which
58
+ /// would cause a collision in the fixed-size buffer) will not yet be scheduled.
59
+ template <typename Result>
60
+ struct OrderedSequencer : public Sequencer<Result> {
61
+ using typename Sequencer<Result>::ResultProducer;
62
+
63
+ /// Constructs the `OrderedSequencer` with the maximum number of results it
64
+ /// will ever hold at one point in time.
65
+ explicit OrderedSequencer(size_t max_jobs) : buffer_(max_jobs) {}
66
+
67
+ /// Buffers results until the next one in the expected order is received.
68
+ std::optional<Result> next(ResultProducer next_result) override {
69
+ // If we already have the result for the next sqn, return it.
70
+ if (auto& maybe_result = buffer(next_sequence_number_)) {
71
+ auto result = std::move(*maybe_result);
72
+ buffer(next_sequence_number_++).reset();
73
+ return result;
74
+ }
75
+ // Otherwise wait for the next result.
76
+ while (true) {
77
+ auto result = next_result();
78
+ if (!result) {
79
+ AT_ASSERT(!detail::buffer_contains_result(buffer_));
80
+ break;
81
+ }
82
+ // If it was not nullopt and the sequence numbers match, return it
83
+ // directly and bump the sequence number.
84
+ if (result->sequence_number == next_sequence_number_) {
85
+ ++next_sequence_number_;
86
+ return result;
87
+ }
88
+ // Stash the result for later.
89
+ AT_ASSERT(!buffer(result->sequence_number).has_value());
90
+ buffer(result->sequence_number) = std::move(result);
91
+ }
92
+ // The result was an empty optional, so we are done with this epoch.
93
+ return std::nullopt;
94
+ }
95
+
96
+ /// Accesses the buffer at the `index` modulo the buffer size.
97
+ std::optional<Result>& buffer(size_t index) {
98
+ return buffer_.at(index % buffer_.size());
99
+ }
100
+
101
+ /// The monotonically increasing sequence number we expect.
102
+ size_t next_sequence_number_ = 0;
103
+
104
+ /// A fixed-size buffer (after construction).
105
+ std::vector<std::optional<Result>> buffer_;
106
+ };
107
+ } // namespace torch::data::detail::sequencers
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/example.h ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/types.h>
4
+
5
+ namespace torch::data {
6
+
7
+ /// An `Example` from a dataset.
8
+ ///
9
+ /// A dataset consists of data and an associated target (label).
10
+ template <typename Data = at::Tensor, typename Target = at::Tensor>
11
+ struct Example {
12
+ using DataType = Data;
13
+ using TargetType = Target;
14
+
15
+ Example() = default;
16
+ Example(Data data, Target target)
17
+ : data(std::move(data)), target(std::move(target)) {}
18
+
19
+ Data data;
20
+ Target target;
21
+ };
22
+
23
+ namespace example {
24
+ using NoTarget = void;
25
+ } // namespace example
26
+
27
+ /// A specialization for `Example` that does not have a target.
28
+ ///
29
+ /// This class exists so that code can be written for a templated `Example`
30
+ /// type, and work both for labeled and unlabeled datasets.
31
+ template <typename Data>
32
+ struct Example<Data, example::NoTarget> {
33
+ using DataType = Data;
34
+ using TargetType = example::NoTarget;
35
+
36
+ Example() = default;
37
+ /* implicit */ Example(Data data) : data(std::move(data)) {}
38
+
39
+ // When a DataLoader returns an Example like this, that example should be
40
+ // implicitly convertible to the underlying data type.
41
+
42
+ operator Data&() {
43
+ return data;
44
+ }
45
+ operator const Data&() const {
46
+ return data;
47
+ }
48
+
49
+ Data data;
50
+ };
51
+
52
+ using TensorExample = Example<at::Tensor, example::NoTarget>;
53
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/iterator.h ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/utils/variadic.h>
4
+ #include <torch/types.h>
5
+
6
+ #include <c10/util/Exception.h>
7
+
8
+ #include <functional>
9
+ #include <iterator>
10
+ #include <memory>
11
+ #include <type_traits>
12
+ #include <utility>
13
+
14
+ namespace torch::data {
15
+ namespace detail {
16
+ // For increased safety and more separated logic, this implementation of
17
+ // `Iterator` consists of a `ValidIterator` and a `SentinelIterator`. A
18
+ // `ValidIterator` yields new batches until the `DataLoader` is exhausted. While
19
+ // the `DataLoader` is not exhausted, `ValidIterator`s compare equal if they are
20
+ // the same object. When the `ValidIterator` becomes exhausted, it compares
21
+ // equal to the `SentinelIterator`, but not before. Half the code here is to
22
+ // implement double dispatch for the comparison. Got damnit, C++.
23
+
24
+ template <typename Batch>
25
+ struct ValidIterator;
26
+
27
+ template <typename Batch>
28
+ struct SentinelIterator;
29
+
30
+ /// Base class for the `ValidIterator` and `SentinelIterator`
31
+ template <typename Batch>
32
+ struct IteratorImpl {
33
+ virtual ~IteratorImpl() = default;
34
+ virtual void next() = 0;
35
+ virtual Batch& get() = 0;
36
+ virtual bool operator==(const IteratorImpl& other) const = 0;
37
+ virtual bool operator==(const ValidIterator<Batch>& other) const = 0;
38
+ virtual bool operator==(const SentinelIterator<Batch>& other) const = 0;
39
+ };
40
+
41
+ template <typename Batch>
42
+ struct ValidIterator : public IteratorImpl<Batch> {
43
+ using BatchProducer = std::function<std::optional<Batch>()>;
44
+
45
+ explicit ValidIterator(BatchProducer next_batch)
46
+ : next_batch_(std::move(next_batch)) {}
47
+
48
+ /// Fetches the next batch.
49
+ void next() override {
50
+ // If we didn't get the very first batch yet, get it now.
51
+ lazy_initialize();
52
+ TORCH_CHECK(
53
+ batch_.has_value(), "Attempted to increment iterator past the end");
54
+ // Increment to the next batch.
55
+ batch_ = next_batch_();
56
+ }
57
+
58
+ /// Returns the current batch. The precondition for this operation to not
59
+ /// throw an exception is that it has been compared to the `SentinelIterator`
60
+ /// and did not compare equal.
61
+ Batch& get() override {
62
+ // If we didn't get the very first batch yet, get it now.
63
+ lazy_initialize();
64
+ TORCH_CHECK(
65
+ batch_.has_value(),
66
+ "Attempted to dereference iterator that was past the end");
67
+ return batch_.value();
68
+ }
69
+
70
+ /// Does double dispatch.
71
+ bool operator==(const IteratorImpl<Batch>& other) const override {
72
+ return other == *this;
73
+ }
74
+
75
+ /// A `ValidIterator` is equal to the `SentinelIterator` iff. the
76
+ /// `ValidIterator` has reached the end of the dataloader.
77
+ bool operator==(const SentinelIterator<Batch>& /* unused */) const override {
78
+ lazy_initialize();
79
+ return !batch_;
80
+ }
81
+
82
+ /// Returns true if the memory address of `other` equals that of `this`.
83
+ bool operator==(const ValidIterator<Batch>& other) const override {
84
+ return &other == this;
85
+ }
86
+
87
+ /// Gets the very first batch if it has not yet been fetched.
88
+ void lazy_initialize() const {
89
+ if (!initialized_) {
90
+ batch_ = next_batch_();
91
+ initialized_ = true;
92
+ }
93
+ }
94
+
95
+ BatchProducer next_batch_;
96
+ mutable std::optional<Batch> batch_;
97
+ mutable bool initialized_ = false;
98
+ };
99
+
100
+ template <typename Batch>
101
+ struct SentinelIterator : public IteratorImpl<Batch> {
102
+ void next() override {
103
+ TORCH_CHECK(
104
+ false,
105
+ "Incrementing the DataLoader's past-the-end iterator is not allowed");
106
+ }
107
+
108
+ Batch& get() override {
109
+ TORCH_CHECK(
110
+ false,
111
+ "Dereferencing the DataLoader's past-the-end iterator is not allowed");
112
+ }
113
+
114
+ /// Does double dispatch.
115
+ bool operator==(const IteratorImpl<Batch>& other) const override {
116
+ return other == *this;
117
+ }
118
+
119
+ /// Calls the comparison operator between `ValidIterator` and
120
+ /// `SentinelIterator`.
121
+ bool operator==(const ValidIterator<Batch>& other) const override {
122
+ return other == *this;
123
+ }
124
+
125
+ /// Sentinel iterators always compare equal.
126
+ bool operator==(const SentinelIterator<Batch>& other) const override {
127
+ return true;
128
+ }
129
+ };
130
+ } // namespace detail
131
+
132
+ template <typename Batch>
133
+ class Iterator {
134
+ public:
135
+ // Type aliases to make the class recognized as a proper iterator.
136
+ using difference_type = std::ptrdiff_t;
137
+ using value_type = Batch;
138
+ using pointer = Batch*;
139
+ using reference = Batch&;
140
+ using iterator_category = std::input_iterator_tag;
141
+
142
+ explicit Iterator(std::unique_ptr<detail::IteratorImpl<Batch>> impl)
143
+ : impl_(std::move(impl)) {}
144
+
145
+ /// Increments the iterator.
146
+ /// Only permitted for valid iterators (not past the end).
147
+ Iterator& operator++() {
148
+ impl_->next();
149
+ return *this;
150
+ }
151
+
152
+ /// Returns the current batch.
153
+ /// Only permitted for valid iterators (not past the end).
154
+ Batch& operator*() {
155
+ return impl_->get();
156
+ }
157
+
158
+ /// Returns a pointer to the current batch.
159
+ /// Only permitted for valid iterators (not past the end).
160
+ Batch* operator->() {
161
+ return &impl_->get();
162
+ }
163
+
164
+ /// Compares two iterators for equality.
165
+ bool operator==(const Iterator& other) const {
166
+ return *impl_ == *other.impl_;
167
+ }
168
+
169
+ /// Compares two iterators for inequality.
170
+ bool operator!=(const Iterator& other) const {
171
+ return !(*this == other);
172
+ }
173
+
174
+ private:
175
+ /// Points either to a `ValidIterator` or to a `SentinelIterator`.
176
+ std::shared_ptr<detail::IteratorImpl<Batch>> impl_;
177
+ };
178
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/samplers/base.h>
4
+ #include <torch/data/samplers/custom_batch_request.h>
5
+ #include <torch/data/samplers/distributed.h>
6
+ #include <torch/data/samplers/random.h>
7
+ #include <torch/data/samplers/sequential.h>
8
+ #include <torch/data/samplers/serialize.h>
9
+ #include <torch/data/samplers/stream.h>
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/base.h ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/types.h>
5
+
6
+ #include <cstddef>
7
+ #include <mutex>
8
+ #include <vector>
9
+
10
+ namespace torch::serialize {
11
+ class OutputArchive;
12
+ class InputArchive;
13
+ } // namespace torch::serialize
14
+
15
+ namespace torch::data::samplers {
16
+ /// A `Sampler` is an object that yields an index with which to access a
17
+ /// dataset.
18
+ template <typename BatchRequest = std::vector<size_t>>
19
+ class Sampler {
20
+ public:
21
+ using BatchRequestType = BatchRequest;
22
+
23
+ virtual ~Sampler() = default;
24
+
25
+ /// Resets the `Sampler`'s internal state.
26
+ /// Typically called before a new epoch.
27
+ /// Optionally, accepts a new size when reseting the sampler.
28
+ virtual void reset(std::optional<size_t> new_size) = 0;
29
+
30
+ /// Returns the next index if possible, or an empty optional if the
31
+ /// sampler is exhausted for this epoch.
32
+ virtual std::optional<BatchRequest> next(size_t batch_size) = 0;
33
+
34
+ /// Serializes the `Sampler` to the `archive`.
35
+ virtual void save(serialize::OutputArchive& archive) const = 0;
36
+
37
+ /// Deserializes the `Sampler` from the `archive`.
38
+ virtual void load(serialize::InputArchive& archive) = 0;
39
+ };
40
+
41
+ } // namespace torch::data::samplers
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/custom_batch_request.h ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <cstddef>
5
+
6
+ namespace torch::data::samplers {
7
+ /// A base class for custom index types.
8
+ struct TORCH_API CustomBatchRequest {
9
+ CustomBatchRequest() = default;
10
+ CustomBatchRequest(const CustomBatchRequest&) = default;
11
+ CustomBatchRequest(CustomBatchRequest&&) noexcept = default;
12
+ virtual ~CustomBatchRequest() = default;
13
+
14
+ /// The number of elements accessed by this index.
15
+ virtual size_t size() const = 0;
16
+ };
17
+ } // namespace torch::data::samplers
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/distributed.h ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/data/samplers/base.h>
5
+
6
+ #include <cstddef>
7
+ #include <vector>
8
+
9
+ namespace torch::serialize {
10
+ class OutputArchive;
11
+ class InputArchive;
12
+ } // namespace torch::serialize
13
+
14
+ namespace torch::data::samplers {
15
+
16
+ /// A `Sampler` that selects a subset of indices to sample from and defines a
17
+ /// sampling behavior. In a distributed setting, this selects a subset of the
18
+ /// indices depending on the provided num_replicas and rank parameters. The
19
+ /// `Sampler` performs a rounding operation based on the `allow_duplicates`
20
+ /// parameter to decide the local sample count.
21
+ template <typename BatchRequest = std::vector<size_t>>
22
+ class DistributedSampler : public Sampler<BatchRequest> {
23
+ public:
24
+ DistributedSampler(
25
+ size_t size,
26
+ size_t num_replicas = 1,
27
+ size_t rank = 0,
28
+ bool allow_duplicates = true)
29
+ : size_(size),
30
+ num_replicas_(num_replicas),
31
+ rank_(rank),
32
+
33
+ allow_duplicates_(allow_duplicates) {}
34
+
35
+ /// Set the epoch for the current enumeration. This can be used to alter the
36
+ /// sample selection and shuffling behavior.
37
+ void set_epoch(size_t epoch) {
38
+ epoch_ = epoch;
39
+ }
40
+
41
+ size_t epoch() const {
42
+ return epoch_;
43
+ }
44
+
45
+ protected:
46
+ size_t local_sample_count() {
47
+ if (allow_duplicates_) {
48
+ return (size_ + num_replicas_ - 1) / num_replicas_;
49
+ } else {
50
+ return size_ / num_replicas_;
51
+ }
52
+ }
53
+
54
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
55
+ size_t size_;
56
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
57
+ size_t num_replicas_;
58
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
59
+ size_t rank_;
60
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
61
+ size_t epoch_{0};
62
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
63
+ bool allow_duplicates_;
64
+ };
65
+
66
+ /// Select samples randomly. The sampling order is shuffled at each `reset()`
67
+ /// call.
68
+ class TORCH_API DistributedRandomSampler : public DistributedSampler<> {
69
+ public:
70
+ DistributedRandomSampler(
71
+ size_t size,
72
+ size_t num_replicas = 1,
73
+ size_t rank = 0,
74
+ bool allow_duplicates = true);
75
+
76
+ /// Resets the `DistributedRandomSampler` to a new set of indices.
77
+ void reset(std::optional<size_t> new_size = std::nullopt) override;
78
+
79
+ /// Returns the next batch of indices.
80
+ std::optional<std::vector<size_t>> next(size_t batch_size) override;
81
+
82
+ /// Serializes the `DistributedRandomSampler` to the `archive`.
83
+ void save(serialize::OutputArchive& archive) const override;
84
+
85
+ /// Deserializes the `DistributedRandomSampler` from the `archive`.
86
+ void load(serialize::InputArchive& archive) override;
87
+
88
+ /// Returns the current index of the `DistributedRandomSampler`.
89
+ size_t index() const noexcept;
90
+
91
+ private:
92
+ void populate_indices();
93
+
94
+ size_t begin_index_;
95
+ size_t end_index_;
96
+ size_t sample_index_;
97
+ std::vector<size_t> all_indices_;
98
+ };
99
+
100
+ /// Select samples sequentially.
101
+ class TORCH_API DistributedSequentialSampler : public DistributedSampler<> {
102
+ public:
103
+ DistributedSequentialSampler(
104
+ size_t size,
105
+ size_t num_replicas = 1,
106
+ size_t rank = 0,
107
+ bool allow_duplicates = true);
108
+
109
+ /// Resets the `DistributedSequentialSampler` to a new set of indices.
110
+ void reset(std::optional<size_t> new_size = std::nullopt) override;
111
+
112
+ /// Returns the next batch of indices.
113
+ std::optional<std::vector<size_t>> next(size_t batch_size) override;
114
+
115
+ /// Serializes the `DistributedSequentialSampler` to the `archive`.
116
+ void save(serialize::OutputArchive& archive) const override;
117
+
118
+ /// Deserializes the `DistributedSequentialSampler` from the `archive`.
119
+ void load(serialize::InputArchive& archive) override;
120
+
121
+ /// Returns the current index of the `DistributedSequentialSampler`.
122
+ size_t index() const noexcept;
123
+
124
+ private:
125
+ void populate_indices();
126
+
127
+ size_t begin_index_;
128
+ size_t end_index_;
129
+ size_t sample_index_;
130
+ std::vector<size_t> all_indices_;
131
+ };
132
+
133
+ } // namespace torch::data::samplers
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/random.h ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/data/samplers/base.h>
5
+ #include <torch/types.h>
6
+
7
+ #include <cstddef>
8
+ #include <vector>
9
+
10
+ namespace torch::serialize {
11
+ class OutputArchive;
12
+ class InputArchive;
13
+ } // namespace torch::serialize
14
+
15
+ namespace torch::data::samplers {
16
+
17
+ /// A `Sampler` that returns random indices.
18
+ class TORCH_API RandomSampler : public Sampler<> {
19
+ public:
20
+ /// Constructs a `RandomSampler` with a size and dtype for the stored indices.
21
+ ///
22
+ /// The constructor will eagerly allocate all required indices, which is the
23
+ /// sequence `0 ... size - 1`. `index_dtype` is the data type of the stored
24
+ /// indices. You can change it to influence memory usage.
25
+ explicit RandomSampler(int64_t size, Dtype index_dtype = torch::kInt64);
26
+
27
+ ~RandomSampler() override;
28
+
29
+ /// Resets the `RandomSampler` to a new set of indices.
30
+ void reset(std::optional<size_t> new_size = std::nullopt) override;
31
+
32
+ /// Returns the next batch of indices.
33
+ std::optional<std::vector<size_t>> next(size_t batch_size) override;
34
+
35
+ /// Serializes the `RandomSampler` to the `archive`.
36
+ void save(serialize::OutputArchive& archive) const override;
37
+
38
+ /// Deserializes the `RandomSampler` from the `archive`.
39
+ void load(serialize::InputArchive& archive) override;
40
+
41
+ /// Returns the current index of the `RandomSampler`.
42
+ size_t index() const noexcept;
43
+
44
+ private:
45
+ at::Tensor indices_;
46
+ int64_t index_ = 0;
47
+ };
48
+ } // namespace torch::data::samplers
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/sequential.h ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/data/samplers/base.h>
5
+ #include <torch/types.h>
6
+
7
+ #include <cstddef>
8
+ #include <vector>
9
+
10
+ namespace torch::serialize {
11
+ class OutputArchive;
12
+ class InputArchive;
13
+ } // namespace torch::serialize
14
+
15
+ namespace torch::data::samplers {
16
+
17
+ /// A `Sampler` that returns indices sequentially.
18
+ class TORCH_API SequentialSampler : public Sampler<> {
19
+ public:
20
+ /// Creates a `SequentialSampler` that will return indices in the range
21
+ /// `0...size - 1`.
22
+ explicit SequentialSampler(size_t size);
23
+
24
+ /// Resets the `SequentialSampler` to zero.
25
+ void reset(std::optional<size_t> new_size = std::nullopt) override;
26
+
27
+ /// Returns the next batch of indices.
28
+ std::optional<std::vector<size_t>> next(size_t batch_size) override;
29
+
30
+ /// Serializes the `SequentialSampler` to the `archive`.
31
+ void save(serialize::OutputArchive& archive) const override;
32
+
33
+ /// Deserializes the `SequentialSampler` from the `archive`.
34
+ void load(serialize::InputArchive& archive) override;
35
+
36
+ /// Returns the current index of the `SequentialSampler`.
37
+ size_t index() const noexcept;
38
+
39
+ private:
40
+ size_t size_;
41
+ size_t index_{0};
42
+ };
43
+
44
+ } // namespace torch::data::samplers
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/serialize.h ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/samplers/base.h>
4
+ #include <torch/serialize/archive.h>
5
+
6
+ namespace torch::data::samplers {
7
+ /// Serializes a `Sampler` into an `OutputArchive`.
8
+ template <typename BatchRequest>
9
+ serialize::OutputArchive& operator<<(
10
+ serialize::OutputArchive& archive,
11
+ const Sampler<BatchRequest>& sampler) {
12
+ sampler.save(archive);
13
+ return archive;
14
+ }
15
+
16
+ /// Deserializes a `Sampler` from an `InputArchive`.
17
+ template <typename BatchRequest>
18
+ serialize::InputArchive& operator>>(
19
+ serialize::InputArchive& archive,
20
+ Sampler<BatchRequest>& sampler) {
21
+ sampler.load(archive);
22
+ return archive;
23
+ }
24
+ } // namespace torch::data::samplers
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/stream.h ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/data/samplers/base.h>
5
+ #include <torch/data/samplers/custom_batch_request.h>
6
+ #include <torch/types.h>
7
+
8
+ #include <cstddef>
9
+
10
+ namespace torch::serialize {
11
+ class InputArchive;
12
+ class OutputArchive;
13
+ } // namespace torch::serialize
14
+
15
+ namespace torch::data::samplers {
16
+
17
+ /// A wrapper around a batch size value, which implements the
18
+ /// `CustomBatchRequest` interface.
19
+ struct TORCH_API BatchSize : public CustomBatchRequest {
20
+ explicit BatchSize(size_t size);
21
+ size_t size() const noexcept override;
22
+ operator size_t() const noexcept;
23
+ size_t size_;
24
+ };
25
+
26
+ /// A sampler for (potentially infinite) streams of data.
27
+ ///
28
+ /// The major feature of the `StreamSampler` is that it does not return
29
+ /// particular indices, but instead only the number of elements to fetch from
30
+ /// the dataset. The dataset has to decide how to produce those elements.
31
+ class TORCH_API StreamSampler : public Sampler<BatchSize> {
32
+ public:
33
+ /// Constructs the `StreamSampler` with the number of individual examples that
34
+ /// should be fetched until the sampler is exhausted.
35
+ explicit StreamSampler(size_t epoch_size);
36
+
37
+ /// Resets the internal state of the sampler.
38
+ void reset(std::optional<size_t> new_size = std::nullopt) override;
39
+
40
+ /// Returns a `BatchSize` object with the number of elements to fetch in the
41
+ /// next batch. This number is the minimum of the supplied `batch_size` and
42
+ /// the difference between the `epoch_size` and the current index. If the
43
+ /// `epoch_size` has been reached, returns an empty optional.
44
+ std::optional<BatchSize> next(size_t batch_size) override;
45
+
46
+ /// Serializes the `StreamSampler` to the `archive`.
47
+ void save(serialize::OutputArchive& archive) const override;
48
+
49
+ /// Deserializes the `StreamSampler` from the `archive`.
50
+ void load(serialize::InputArchive& archive) override;
51
+
52
+ private:
53
+ size_t examples_retrieved_so_far_ = 0;
54
+ size_t epoch_size_;
55
+ };
56
+
57
+ } // namespace torch::data::samplers
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms.h ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/transforms/base.h>
4
+ #include <torch/data/transforms/collate.h>
5
+ #include <torch/data/transforms/lambda.h>
6
+ #include <torch/data/transforms/stack.h>
7
+ #include <torch/data/transforms/tensor.h>
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/base.h ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/types.h>
4
+
5
+ #include <utility>
6
+ #include <vector>
7
+
8
+ namespace torch::data::transforms {
9
+
10
+ /// A transformation of a batch to a new batch.
11
+ template <typename InputBatch, typename OutputBatch>
12
+ class BatchTransform {
13
+ public:
14
+ using InputBatchType = InputBatch;
15
+ using OutputBatchType = OutputBatch;
16
+
17
+ virtual ~BatchTransform() = default;
18
+
19
+ /// Applies the transformation to the given `input_batch`.
20
+ virtual OutputBatch apply_batch(InputBatch input_batch) = 0;
21
+ };
22
+
23
+ /// A transformation of individual input examples to individual output examples.
24
+ ///
25
+ /// Just like a `Dataset` is a `BatchDataset`, a `Transform` is a
26
+ /// `BatchTransform` that can operate on the level of individual examples rather
27
+ /// than entire batches. The batch-level transform is implemented (by default)
28
+ /// in terms of the example-level transform, though this can be customized.
29
+ template <typename Input, typename Output>
30
+ class Transform
31
+ : public BatchTransform<std::vector<Input>, std::vector<Output>> {
32
+ public:
33
+ using InputType = Input;
34
+ using OutputType = Output;
35
+
36
+ /// Applies the transformation to the given `input`.
37
+ virtual OutputType apply(InputType input) = 0;
38
+
39
+ /// Applies the `transformation` over the entire `input_batch`.
40
+ std::vector<Output> apply_batch(std::vector<Input> input_batch) override {
41
+ std::vector<Output> output_batch;
42
+ output_batch.reserve(input_batch.size());
43
+ for (auto&& input : input_batch) {
44
+ output_batch.push_back(apply(std::move(input)));
45
+ }
46
+ return output_batch;
47
+ }
48
+ };
49
+ } // namespace torch::data::transforms
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/collate.h ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/example.h>
4
+ #include <torch/data/transforms/lambda.h>
5
+
6
+ #include <vector>
7
+
8
+ namespace torch::data::transforms {
9
+
10
+ /// A `Collation` is a transform that reduces a batch into a single value.
11
+ /// The result is a `BatchDataset` that has the type of the single value as its
12
+ /// `BatchType`.
13
+ template <typename T, typename BatchType = std::vector<T>>
14
+ using Collation = BatchTransform<BatchType, T>;
15
+
16
+ /// A `Collate` allows passing a custom function to reduce/collate a batch
17
+ /// into a single value. It's effectively the lambda version of `Collation`,
18
+ /// which you could subclass and override `operator()` to achieve the same.
19
+ ///
20
+ /// \rst
21
+ /// .. code-block:: cpp
22
+ /// using namespace torch::data;
23
+ ///
24
+ /// auto dataset = datasets::MNIST("path/to/mnist")
25
+ /// .map(transforms::Collate<Example<>>([](std::vector<Example<>> e) {
26
+ /// return std::move(e.front());
27
+ /// }));
28
+ /// \endrst
29
+ template <typename T, typename BatchType = std::vector<T>>
30
+ using Collate = BatchLambda<BatchType, T>;
31
+ } // namespace torch::data::transforms
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/lambda.h ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/transforms/base.h>
4
+
5
+ #include <functional>
6
+ #include <utility>
7
+ #include <vector>
8
+
9
+ namespace torch::data::transforms {
10
+
11
+ /// A `BatchTransform` that applies a user-provided functor to a batch.
12
+ template <typename Input, typename Output = Input>
13
+ class BatchLambda : public BatchTransform<Input, Output> {
14
+ public:
15
+ using typename BatchTransform<Input, Output>::InputBatchType;
16
+ using typename BatchTransform<Input, Output>::OutputBatchType;
17
+ using FunctionType = std::function<OutputBatchType(InputBatchType)>;
18
+
19
+ /// Constructs the `BatchLambda` from the given `function` object.
20
+ explicit BatchLambda(FunctionType function)
21
+ : function_(std::move(function)) {}
22
+
23
+ /// Applies the user-provided function object to the `input_batch`.
24
+ OutputBatchType apply_batch(InputBatchType input_batch) override {
25
+ return function_(std::move(input_batch));
26
+ }
27
+
28
+ private:
29
+ FunctionType function_;
30
+ };
31
+
32
+ // A `Transform` that applies a user-provided functor to individual examples.
33
+ template <typename Input, typename Output = Input>
34
+ class Lambda : public Transform<Input, Output> {
35
+ public:
36
+ using typename Transform<Input, Output>::InputType;
37
+ using typename Transform<Input, Output>::OutputType;
38
+ using FunctionType = std::function<Output(Input)>;
39
+
40
+ /// Constructs the `Lambda` from the given `function` object.
41
+ explicit Lambda(FunctionType function) : function_(std::move(function)) {}
42
+
43
+ /// Applies the user-provided function object to the `input`.
44
+ OutputType apply(InputType input) override {
45
+ return function_(std::move(input));
46
+ }
47
+
48
+ private:
49
+ FunctionType function_;
50
+ };
51
+
52
+ } // namespace torch::data::transforms
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/stack.h ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/example.h>
4
+ #include <torch/data/transforms/collate.h>
5
+ #include <torch/types.h>
6
+
7
+ #include <utility>
8
+ #include <vector>
9
+
10
+ namespace torch::data::transforms {
11
+
12
+ template <typename T = Example<>>
13
+ struct Stack;
14
+
15
+ /// A `Collation` for `Example<Tensor, Tensor>` types that stacks all data
16
+ /// tensors into one tensor, and all target (label) tensors into one tensor.
17
+ template <>
18
+ struct Stack<Example<>> : public Collation<Example<>> {
19
+ Example<> apply_batch(std::vector<Example<>> examples) override {
20
+ std::vector<torch::Tensor> data, targets;
21
+ data.reserve(examples.size());
22
+ targets.reserve(examples.size());
23
+ for (auto& example : examples) {
24
+ data.push_back(std::move(example.data));
25
+ targets.push_back(std::move(example.target));
26
+ }
27
+ return {torch::stack(data), torch::stack(targets)};
28
+ }
29
+ };
30
+
31
+ /// A `Collation` for `Example<Tensor, NoTarget>` types that stacks all data
32
+ /// tensors into one tensor.
33
+ template <>
34
+ struct Stack<TensorExample>
35
+ : public Collation<Example<Tensor, example::NoTarget>> {
36
+ TensorExample apply_batch(std::vector<TensorExample> examples) override {
37
+ std::vector<torch::Tensor> data;
38
+ data.reserve(examples.size());
39
+ for (auto& example : examples) {
40
+ data.push_back(std::move(example.data));
41
+ }
42
+ return torch::stack(data);
43
+ }
44
+ };
45
+ } // namespace torch::data::transforms
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/tensor.h ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/data/example.h>
4
+ #include <torch/data/transforms/base.h>
5
+ #include <torch/types.h>
6
+
7
+ #include <functional>
8
+ #include <utility>
9
+
10
+ namespace torch::data::transforms {
11
+
12
+ /// A `Transform` that is specialized for the typical `Example<Tensor, Tensor>`
13
+ /// combination. It exposes a single `operator()` interface hook (for
14
+ /// subclasses), and calls this function on input `Example` objects.
15
+ template <typename Target = Tensor>
16
+ class TensorTransform
17
+ : public Transform<Example<Tensor, Target>, Example<Tensor, Target>> {
18
+ public:
19
+ using E = Example<Tensor, Target>;
20
+ using typename Transform<E, E>::InputType;
21
+ using typename Transform<E, E>::OutputType;
22
+
23
+ /// Transforms a single input tensor to an output tensor.
24
+ virtual Tensor operator()(Tensor input) = 0;
25
+
26
+ /// Implementation of `Transform::apply` that calls `operator()`.
27
+ OutputType apply(InputType input) override {
28
+ input.data = (*this)(std::move(input.data));
29
+ return input;
30
+ }
31
+ };
32
+
33
+ /// A `Lambda` specialized for the typical `Example<Tensor, Tensor>` input type.
34
+ template <typename Target = Tensor>
35
+ class TensorLambda : public TensorTransform<Target> {
36
+ public:
37
+ using FunctionType = std::function<Tensor(Tensor)>;
38
+
39
+ /// Creates a `TensorLambda` from the given `function`.
40
+ explicit TensorLambda(FunctionType function)
41
+ : function_(std::move(function)) {}
42
+
43
+ /// Applies the user-provided functor to the input tensor.
44
+ Tensor operator()(Tensor input) override {
45
+ return function_(std::move(input));
46
+ }
47
+
48
+ private:
49
+ FunctionType function_;
50
+ };
51
+
52
+ /// Normalizes input tensors by subtracting the supplied mean and dividing by
53
+ /// the given standard deviation.
54
+ template <typename Target = Tensor>
55
+ struct Normalize : public TensorTransform<Target> {
56
+ /// Constructs a `Normalize` transform. The mean and standard deviation can be
57
+ /// anything that is broadcastable over the input tensors (like single
58
+ /// scalars).
59
+ Normalize(ArrayRef<double> mean, ArrayRef<double> stddev)
60
+ : mean(torch::tensor(mean, torch::kFloat32)
61
+ .unsqueeze(/*dim=*/1)
62
+ .unsqueeze(/*dim=*/2)),
63
+ stddev(torch::tensor(stddev, torch::kFloat32)
64
+ .unsqueeze(/*dim=*/1)
65
+ .unsqueeze(/*dim=*/2)) {}
66
+
67
+ torch::Tensor operator()(Tensor input) override {
68
+ return input.sub(mean).div(stddev);
69
+ }
70
+
71
+ torch::Tensor mean, stddev;
72
+ };
73
+ } // namespace torch::data::transforms
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/worker_exception.h ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <exception>
4
+ #include <string>
5
+ #include <utility>
6
+
7
+ namespace torch::data {
8
+
9
+ /// An exception thrown when a DataLoader's worker thread throws an exception,
10
+ /// which is caught. A `WorkerException` stores an `exception_ptr` to the
11
+ /// original exception thrown in the worker thread.
12
+ struct WorkerException : public std::exception {
13
+ /// Constructs a `WorkerException` from an `exception_ptr`.
14
+ explicit WorkerException(std::exception_ptr original)
15
+ // NOLINTNEXTLINE(bugprone-throw-keyword-missing)
16
+ : original_exception(std::move(original)),
17
+ message("Caught exception in DataLoader worker thread.") {
18
+ try {
19
+ std::rethrow_exception(original_exception);
20
+ } catch (std::exception& e) {
21
+ message += " Original message: ";
22
+ message += e.what();
23
+ }
24
+ }
25
+
26
+ const char* what() const noexcept override {
27
+ return message.c_str();
28
+ }
29
+
30
+ /// The original exception thrown in the worker thread.
31
+ std::exception_ptr original_exception;
32
+
33
+ /// This exception's message (not the original exception's message).
34
+ std::string message;
35
+ };
36
+
37
+ } // namespace torch::data
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/detail/TensorDataContainer.h ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/Dispatch.h>
4
+ #include <ATen/ScalarOps.h>
5
+ #include <ATen/core/Tensor.h>
6
+ #include <ATen/core/grad_mode.h>
7
+
8
+ #include <c10/util/irange.h>
9
+
10
+ #ifndef AT_PER_OPERATOR_HEADERS
11
+ #include <ATen/Functions.h>
12
+ #else
13
+ #include <ATen/ops/empty.h>
14
+ #include <ATen/ops/tensor.h>
15
+ #endif
16
+
17
+ #include <initializer_list>
18
+
19
+ namespace torch::detail {
20
+
21
+ enum class TensorDataContainerType { Scalar, InitList, Tensor };
22
+
23
+ struct TensorDataContainer;
24
+
25
+ inline std::ostream& operator<<(
26
+ std::ostream& stream,
27
+ const TensorDataContainer& tensor_data_container);
28
+
29
+ inline c10::ScalarType compute_desired_dtype(c10::ScalarType scalar_type) {
30
+ if (scalar_type == at::kInt || scalar_type == at::kLong) {
31
+ // C++ `torch::tensor` with an integer type or an `at::ArrayRef` /
32
+ // `std::vector` / (nested) braced-init-list of integer types always
33
+ // produces a tensor of dtype `at::kLong` (aka. int64_t), matching Python
34
+ // `torch.tensor` behavior.
35
+ return at::kLong;
36
+ } else if (scalar_type == at::kFloat || scalar_type == at::kDouble) {
37
+ // C++ `torch::tensor` with a floating-point type or an `at::ArrayRef` /
38
+ // `std::vector` / (nested) braced-init-list of floating-point types always
39
+ // produces a tensor of dtype `torch::get_default_dtype()`, matching Python
40
+ // `torch.tensor` behavior.
41
+ return at::typeMetaToScalarType(at::get_default_dtype());
42
+ } else {
43
+ return scalar_type;
44
+ }
45
+ }
46
+
47
+ // We use `TensorDataContainer` to support converting the following data
48
+ // container types into the equivalent Tensor:
49
+ //
50
+ // 1. Arbitrarily nested braced-init-list (e.g. `{{1, 2}, {3, 4}}`).
51
+ // 2. `at::ArrayRef` of supported tensor data types.
52
+ // 3. `std::vector` of supported tensor data types.
53
+ //
54
+ // At any time, a `TensorDataContainer` object represents one of the following:
55
+ //
56
+ // 1. A scalar with value `scalar()` and type `scalar_type()`.
57
+ // 2. A Tensor represented in `std::initializer_list<TensorDataContainer>` form,
58
+ // with value `init_list()`, Tensor scalar type `scalar_type()`, and Tensor
59
+ // sizes `sizes()`.
60
+ // 3. A Tensor represented in `at::Tensor` form, with value `tensor()`, scalar
61
+ // type `scalar_type()`,
62
+ // and Tensor sizes `sizes()`.
63
+ //
64
+ // All the infrastructure here is mostly to support converting an arbitrarily
65
+ // nested braced-init-list to the equivalent Tensor successfully. Consider the
66
+ // following example:
67
+ //
68
+ // `torch::tensor({{1}, {2}})`
69
+ //
70
+ // this will call into the `torch::tensor` function:
71
+ //
72
+ // `at::Tensor tensor(detail::TensorDataContainer tensor_data_container, const
73
+ // at::TensorOptions& options = {})`
74
+ //
75
+ // the compiler will first try to convert `{{1}, {2}}` to `TensorDataContainer`
76
+ // type:
77
+ //
78
+ // `TensorDataContainer({{1}, {2}})`
79
+ //
80
+ // which matches to the
81
+ // `TensorDataContainer(std::initializer_list<TensorDataContainer>)`
82
+ // constructor, and in an attempt to convert `{1}` and `{2}` to
83
+ // `TensorDataContainer`, it calls the following:
84
+ //
85
+ // `TensorDataContainer({1})` (same call path happens for `{2}`, and we'll just
86
+ // focus on `{1}` here)
87
+ //
88
+ // At this point, theoretically there are two plausible ways for `{1}` to be
89
+ // matched to one of the constructors of `TensorDataContainer`:
90
+ //
91
+ // 1. It can be a list-initialization of a scalar value, thus matching
92
+ // `TensorDataContainer(int value)`.
93
+ // 2. It can be converted to `std::initializer_list<TensorDataContainer>`, thus
94
+ // matching
95
+ // `TensorDataContainer(std::initializer_list<TensorDataContainer>)`.
96
+ //
97
+ // How does the compiler decide which one to choose? According to
98
+ // `https://en.cppreference.com/w/cpp/language/list_initialization`,
99
+ // braced-init-list always prefers the constructor that takes
100
+ // `std::initializer_list`. Hence we happily move forward with constructor #2,
101
+ // and it calls the following:
102
+ //
103
+ // `TensorDataContainer(1)`
104
+ //
105
+ // Now it matches `TensorDataContainer(int value)`, which stores `1` as a scalar
106
+ // value. All is good.
107
+ struct TensorDataContainer {
108
+ // NOTE: For tensors with zero-size dimensions (e.g. `torch::tensor({{},
109
+ // {}})`), the innermost empty braced-init-list `{}` matches the default
110
+ // constructor of the innermost `TensorDataContainer`.
111
+ TensorDataContainer()
112
+ : sizes_({0}),
113
+ // NOTE: In Python, the dtype of tensors with zero-size dimensions (e.g.
114
+ // `torch.tensor([[], []])`) depends on the value of
115
+ // `torch.get_default_dtype()`, and we should do the same for the C++
116
+ // equivalent.
117
+ scalar_type_(at::typeMetaToScalarType(at::get_default_dtype())),
118
+ type_(TensorDataContainerType::InitList) {}
119
+ #define TENSOR(T, S) \
120
+ TensorDataContainer(T value) \
121
+ : sizes_(), \
122
+ scalar_type_(at::k##S), \
123
+ type_(TensorDataContainerType::Scalar), \
124
+ scalar_(value) {}
125
+ AT_FORALL_SCALAR_TYPES_AND3(Bool, Half, BFloat16, TENSOR)
126
+ AT_FORALL_COMPLEX_TYPES(TENSOR)
127
+ #undef TENSOR
128
+ TensorDataContainer(std::initializer_list<TensorDataContainer> init_list)
129
+ : sizes_(),
130
+ scalar_type_(init_list.begin()->scalar_type()),
131
+ type_(TensorDataContainerType::InitList),
132
+ init_list_(init_list) {
133
+ const TensorDataContainer& first_elem = *(init_list.begin());
134
+ for (const auto& elem : init_list) {
135
+ TORCH_CHECK(
136
+ elem.sizes() == first_elem.sizes(),
137
+ "Expected all sub-lists to have sizes: ",
138
+ first_elem.sizes(),
139
+ " (e.g. ",
140
+ first_elem,
141
+ "), ",
142
+ "but got sub-list ",
143
+ elem,
144
+ " with sizes: ",
145
+ elem.sizes());
146
+ TORCH_CHECK(
147
+ elem.scalar_type() == first_elem.scalar_type(),
148
+ "Expected all elements of the tensor to have the same scalar type: ",
149
+ first_elem.scalar_type(),
150
+ ", but got element of scalar type: ",
151
+ elem.scalar_type());
152
+ }
153
+ sizes_.reserve(first_elem.sizes().size() + 1);
154
+ sizes_.push_back(static_cast<int64_t>(init_list.size()));
155
+ sizes_.insert(
156
+ sizes_.end(), first_elem.sizes().begin(), first_elem.sizes().end());
157
+ }
158
+
159
+ #define TENSOR(T, S) \
160
+ TensorDataContainer(at::ArrayRef<T> values) \
161
+ : sizes_({(int64_t)values.size()}), \
162
+ scalar_type_(at::k##S), \
163
+ type_(TensorDataContainerType::Tensor) { \
164
+ at::AutoDispatchBelowAutograd mode; \
165
+ if (scalar_type_ == at::kBool) { \
166
+ tensor_ = at::tensor(values, at::TensorOptions().device(at::kCPU)); \
167
+ } else { \
168
+ tensor_ = at::tensor(values, at::dtype(scalar_type_).device(at::kCPU)); \
169
+ } \
170
+ }
171
+ AT_FORALL_SCALAR_TYPES_AND3(Bool, Half, BFloat16, TENSOR)
172
+ AT_FORALL_COMPLEX_TYPES(TENSOR)
173
+ #undef TENSOR
174
+
175
+ // NOTE: We need to handle `std::vector` explicitly instead of relying on an
176
+ // implicit conversion to `at::ArrayRef`, otherwise the following error can be
177
+ // thrown when calling `torch::tensor(std::vector<int>({1, 2}))`:
178
+ // ```
179
+ // error: no matching function for call to 'tensor(const std::vector<int>&)'
180
+ // no known conversion for argument 1 from 'const std::vector<int>' to
181
+ // 'torch::detail::TensorDataContainer'
182
+ // ```
183
+ //
184
+ // NOTE: `torch::tensor(std::vector<bool>)` is not supported for now, because
185
+ // ArrayRef<bool> cannot be constructed from a std::vector<bool> bitfield.
186
+ #define TENSOR(T, S) \
187
+ TensorDataContainer(const std::vector<T>& values) \
188
+ : TensorDataContainer(at::ArrayRef<T>(values)) {}
189
+ AT_FORALL_SCALAR_TYPES_AND2(Half, BFloat16, TENSOR)
190
+ AT_FORALL_COMPLEX_TYPES(TENSOR)
191
+ #undef TENSOR
192
+
193
+ bool is_scalar() const {
194
+ return type_ == TensorDataContainerType::Scalar;
195
+ }
196
+
197
+ const c10::Scalar& scalar() const {
198
+ TORCH_CHECK(
199
+ is_scalar(),
200
+ "Can only call `scalar()` on a TensorDataContainer that has `is_scalar() == true`");
201
+ return scalar_;
202
+ }
203
+
204
+ bool is_init_list() const {
205
+ return type_ == TensorDataContainerType::InitList;
206
+ }
207
+
208
+ const std::initializer_list<TensorDataContainer>& init_list() const {
209
+ TORCH_CHECK(
210
+ is_init_list(),
211
+ "Can only call `init_list()` on a TensorDataContainer that has `is_init_list() == true`");
212
+ return init_list_;
213
+ }
214
+
215
+ bool is_tensor() const {
216
+ return type_ == TensorDataContainerType::Tensor;
217
+ }
218
+
219
+ const at::Tensor& tensor() const {
220
+ TORCH_CHECK(
221
+ is_tensor(),
222
+ "Can only call `tensor()` on a TensorDataContainer that has `is_tensor() == true`");
223
+ return tensor_;
224
+ }
225
+
226
+ const std::vector<int64_t>& sizes() const {
227
+ return sizes_;
228
+ }
229
+
230
+ const c10::ScalarType& scalar_type() const {
231
+ return scalar_type_;
232
+ }
233
+
234
+ at::Tensor convert_to_tensor(at::TensorOptions options) const {
235
+ if (!options.has_dtype()) {
236
+ options = options.dtype(compute_desired_dtype(scalar_type_));
237
+ }
238
+
239
+ if (is_scalar()) {
240
+ at::AutoDispatchBelowAutograd mode;
241
+ return at::scalar_tensor(scalar_, options);
242
+ } else if (is_init_list()) {
243
+ // NOTE: Here we explicitly choose to initialize the tensor on CPU first,
244
+ // fill each element of the tensor, and then move the tensor to the
245
+ // desired device. For CUDA device, this approach only involves 1 CUDA
246
+ // kernel launch, and is much faster than initializing the tensor on CUDA
247
+ // first and then filling each element of it (which involves `N` CUDA
248
+ // kernel launches where `N` is the number of the elements in the tensor).
249
+ at::Tensor tensor = ([&]() {
250
+ at::AutoDispatchBelowAutograd mode;
251
+ return at::empty(sizes_, options.device(at::kCPU));
252
+ })();
253
+ fill_tensor(tensor);
254
+ return tensor.to(options.device());
255
+ } else if (is_tensor()) {
256
+ auto output = tensor_.to(options);
257
+ TORCH_CHECK(
258
+ !tensor_.is_complex() || output.is_complex(),
259
+ "can not do torch::tensor(complex, dtype=non-complex) because complex can not be casted to real number without loss of information");
260
+ return output;
261
+ } else {
262
+ TORCH_INTERNAL_ASSERT(false, "Invalid TensorDataContainer type");
263
+ }
264
+ }
265
+
266
+ void pretty_print_recursive(std::ostream& stream) const {
267
+ if (is_scalar()) {
268
+ AT_DISPATCH_ALL_TYPES_AND3(
269
+ at::kBool,
270
+ at::kHalf,
271
+ at::kBFloat16,
272
+ scalar_type_,
273
+ "TensorDataContainer_pretty_print_scalar",
274
+ [&] { stream << scalar_.to<scalar_t>(); });
275
+ } else if (is_init_list()) {
276
+ stream << "{";
277
+ for (const TensorDataContainer* it = init_list_.begin();
278
+ it != init_list_.end();
279
+ it++) {
280
+ stream << *it;
281
+ if (std::next(it) != init_list_.end())
282
+ stream << ", ";
283
+ }
284
+ stream << "}";
285
+ } else if (is_tensor()) {
286
+ stream << "{";
287
+ for (const auto i : c10::irange(tensor_.sizes()[0])) {
288
+ AT_DISPATCH_ALL_TYPES_AND3(
289
+ at::kBool,
290
+ at::kHalf,
291
+ at::kBFloat16,
292
+ scalar_type_,
293
+ "TensorDataContainer_pretty_print_tensor_item",
294
+ [&] { stream << tensor_[i].item<scalar_t>(); });
295
+ if (i != tensor_.sizes()[0] - 1)
296
+ stream << ", ";
297
+ }
298
+ stream << "}";
299
+ } else {
300
+ TORCH_INTERNAL_ASSERT(false, "Invalid TensorDataContainer type");
301
+ }
302
+ }
303
+
304
+ private:
305
+ void fill_tensor(at::Tensor& tensor) const {
306
+ if (is_scalar()) {
307
+ TORCH_INTERNAL_ASSERT(
308
+ tensor.dim() == 0,
309
+ "Expected a 0-dim Tensor, but got Tensor with dimensions: ",
310
+ tensor.dim());
311
+ at::NoGradGuard guard;
312
+ tensor.fill_(scalar_);
313
+ } else if (is_init_list()) {
314
+ TORCH_INTERNAL_ASSERT(
315
+ tensor.sizes()[0] == (int64_t)init_list_.size(),
316
+ "Expected a Tensor with size ",
317
+ init_list_.size(),
318
+ " in its first dimension, but got Tensor with size ",
319
+ tensor.sizes()[0],
320
+ " in its first dimension");
321
+ int64_t index = 0;
322
+ for (const auto& elem : init_list_) {
323
+ at::Tensor slice = tensor[index];
324
+ elem.fill_tensor(slice);
325
+ index++;
326
+ }
327
+ } else if (is_tensor()) {
328
+ TORCH_INTERNAL_ASSERT(
329
+ false,
330
+ "TensorDataContainer is already a Tensor type, `fill_tensor` should not be called");
331
+ } else {
332
+ TORCH_INTERNAL_ASSERT(false, "Invalid TensorDataContainer type");
333
+ }
334
+ }
335
+
336
+ std::vector<int64_t> sizes_;
337
+ c10::ScalarType scalar_type_;
338
+ TensorDataContainerType type_;
339
+ c10::Scalar scalar_;
340
+ std::initializer_list<TensorDataContainer> init_list_;
341
+ at::Tensor tensor_;
342
+ };
343
+
344
+ inline std::ostream& operator<<(
345
+ std::ostream& stream,
346
+ const TensorDataContainer& tensor_data_container) {
347
+ tensor_data_container.pretty_print_recursive(stream);
348
+ return stream;
349
+ }
350
+
351
+ } // namespace torch::detail
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/detail/static.h ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/utils/variadic.h>
4
+ #include <torch/types.h>
5
+
6
+ #include <cstdint>
7
+ #include <type_traits>
8
+
9
+ namespace torch::nn {
10
+ class Module;
11
+ } // namespace torch::nn
12
+
13
+ namespace torch::detail {
14
+ /// Detects if a type T has a forward() method.
15
+ template <typename T>
16
+ struct has_forward {
17
+ // Declare two types with differing size.
18
+ using yes = int8_t;
19
+ using no = int16_t;
20
+
21
+ // Here we declare two functions. The first is only enabled if `&U::forward`
22
+ // is well-formed and returns the `yes` type. In C++, the ellipsis parameter
23
+ // type (`...`) always puts the function at the bottom of overload resolution.
24
+ // This is specified in the standard as: 1) A standard conversion sequence is
25
+ // always better than a user-defined conversion sequence or an ellipsis
26
+ // conversion sequence. 2) A user-defined conversion sequence is always better
27
+ // than an ellipsis conversion sequence This means that if the first overload
28
+ // is viable, it will be preferred over the second as long as we pass any
29
+ // convertible type. The type of `&U::forward` is a pointer type, so we can
30
+ // pass e.g. 0.
31
+ template <typename U>
32
+ static yes test(decltype(&U::forward));
33
+ template <typename U>
34
+ static no test(...);
35
+
36
+ // Finally we test statically whether the size of the type returned by the
37
+ // selected overload is the size of the `yes` type.
38
+ static constexpr bool value = (sizeof(test<T>(nullptr)) == sizeof(yes));
39
+ };
40
+
41
+ template <typename Head = void, typename... Tail>
42
+ constexpr bool check_not_lvalue_references() {
43
+ return (
44
+ !std::is_lvalue_reference_v<Head> ||
45
+ std::is_const_v<std::remove_reference_t<
46
+ Head>>)&&check_not_lvalue_references<Tail...>();
47
+ }
48
+
49
+ template <>
50
+ inline constexpr bool check_not_lvalue_references<void>() {
51
+ return true;
52
+ }
53
+
54
+ /// A type trait whose `value` member is true if `M` derives from `Module`.
55
+ template <typename M>
56
+ using is_module = std::is_base_of<torch::nn::Module, std::decay_t<M>>;
57
+
58
+ template <typename M, typename T = void>
59
+ using enable_if_module_t = std::enable_if_t<is_module<M>::value, T>;
60
+ } // namespace torch::detail
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/enum.h ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <variant>
5
+
6
+ #include <ATen/core/Reduction.h>
7
+ #include <c10/util/Exception.h>
8
+ #include <torch/csrc/Export.h>
9
+
10
+ #define TORCH_ENUM_DECLARE(name) \
11
+ namespace torch { \
12
+ namespace enumtype { \
13
+ /* \
14
+ NOTE: We need to provide the default constructor for each struct, \
15
+ otherwise Clang 3.8 would complain: \
16
+ ``` \
17
+ error: default initialization of an object of const type 'const \
18
+ enumtype::Enum1' without a user-provided default constructor \
19
+ ``` \
20
+ */ \
21
+ struct k##name { \
22
+ k##name() {} \
23
+ }; \
24
+ } \
25
+ TORCH_API extern const enumtype::k##name k##name; \
26
+ }
27
+
28
+ #define TORCH_ENUM_DEFINE(name) \
29
+ namespace torch { \
30
+ const enumtype::k##name k##name; \
31
+ }
32
+
33
+ #define TORCH_ENUM_PRETTY_PRINT(name) \
34
+ std::string operator()(const enumtype::k##name& v [[maybe_unused]]) const { \
35
+ std::string k("k"); \
36
+ return k + #name; \
37
+ }
38
+
39
+ // NOTE: Backstory on why we need the following two macros:
40
+ //
41
+ // Consider the following options class:
42
+ //
43
+ // ```
44
+ // struct TORCH_API SomeOptions {
45
+ // typedef std::variant<enumtype::kNone, enumtype::kMean, enumtype::kSum>
46
+ // reduction_t; SomeOptions(reduction_t reduction = torch::kMean) :
47
+ // reduction_(reduction) {}
48
+ //
49
+ // TORCH_ARG(reduction_t, reduction);
50
+ // };
51
+ // ```
52
+ //
53
+ // and the functional that uses it:
54
+ //
55
+ // ```
56
+ // Tensor some_functional(
57
+ // const Tensor& input,
58
+ // SomeOptions options = {}) {
59
+ // ...
60
+ // }
61
+ // ```
62
+ //
63
+ // Normally, we would expect this to work:
64
+ //
65
+ // `F::some_functional(input, torch::kNone)`
66
+ //
67
+ // However, it throws the following error instead:
68
+ //
69
+ // ```
70
+ // error: could not convert `torch::kNone` from `const torch::enumtype::kNone`
71
+ // to `torch::nn::SomeOptions`
72
+ // ```
73
+ //
74
+ // To get around this problem, we explicitly provide the following constructors
75
+ // for `SomeOptions`:
76
+ //
77
+ // ```
78
+ // SomeOptions(torch::enumtype::kNone reduction) : reduction_(torch::kNone) {}
79
+ // SomeOptions(torch::enumtype::kMean reduction) : reduction_(torch::kMean) {}
80
+ // SomeOptions(torch::enumtype::kSum reduction) : reduction_(torch::kSum) {}
81
+ // ```
82
+ //
83
+ // so that the conversion from `torch::kNone` to `SomeOptions` would work.
84
+ //
85
+ // Note that we also provide the default constructor `SomeOptions() {}`, so that
86
+ // `SomeOptions options = {}` can work.
87
+ #define TORCH_OPTIONS_CTOR_VARIANT_ARG3( \
88
+ OPTIONS_NAME, ARG_NAME, TYPE1, TYPE2, TYPE3) \
89
+ OPTIONS_NAME() = default; \
90
+ OPTIONS_NAME(torch::enumtype::TYPE1 ARG_NAME) : ARG_NAME##_(torch::TYPE1) {} \
91
+ OPTIONS_NAME(torch::enumtype::TYPE2 ARG_NAME) : ARG_NAME##_(torch::TYPE2) {} \
92
+ OPTIONS_NAME(torch::enumtype::TYPE3 ARG_NAME) : ARG_NAME##_(torch::TYPE3) {}
93
+
94
+ #define TORCH_OPTIONS_CTOR_VARIANT_ARG4( \
95
+ OPTIONS_NAME, ARG_NAME, TYPE1, TYPE2, TYPE3, TYPE4) \
96
+ OPTIONS_NAME() = default; \
97
+ OPTIONS_NAME(torch::enumtype::TYPE1 ARG_NAME) : ARG_NAME##_(torch::TYPE1) {} \
98
+ OPTIONS_NAME(torch::enumtype::TYPE2 ARG_NAME) : ARG_NAME##_(torch::TYPE2) {} \
99
+ OPTIONS_NAME(torch::enumtype::TYPE3 ARG_NAME) : ARG_NAME##_(torch::TYPE3) {} \
100
+ OPTIONS_NAME(torch::enumtype::TYPE4 ARG_NAME) : ARG_NAME##_(torch::TYPE4) {}
101
+
102
+ TORCH_ENUM_DECLARE(Linear)
103
+ TORCH_ENUM_DECLARE(Conv1D)
104
+ TORCH_ENUM_DECLARE(Conv2D)
105
+ TORCH_ENUM_DECLARE(Conv3D)
106
+ TORCH_ENUM_DECLARE(ConvTranspose1D)
107
+ TORCH_ENUM_DECLARE(ConvTranspose2D)
108
+ TORCH_ENUM_DECLARE(ConvTranspose3D)
109
+ TORCH_ENUM_DECLARE(Sigmoid)
110
+ TORCH_ENUM_DECLARE(Tanh)
111
+ TORCH_ENUM_DECLARE(ReLU)
112
+ TORCH_ENUM_DECLARE(GELU)
113
+ TORCH_ENUM_DECLARE(SiLU)
114
+ TORCH_ENUM_DECLARE(Mish)
115
+ TORCH_ENUM_DECLARE(LeakyReLU)
116
+ TORCH_ENUM_DECLARE(FanIn)
117
+ TORCH_ENUM_DECLARE(FanOut)
118
+ TORCH_ENUM_DECLARE(Constant)
119
+ TORCH_ENUM_DECLARE(Reflect)
120
+ TORCH_ENUM_DECLARE(Replicate)
121
+ TORCH_ENUM_DECLARE(Circular)
122
+ TORCH_ENUM_DECLARE(Nearest)
123
+ TORCH_ENUM_DECLARE(Bilinear)
124
+ TORCH_ENUM_DECLARE(Bicubic)
125
+ TORCH_ENUM_DECLARE(Trilinear)
126
+ TORCH_ENUM_DECLARE(Area)
127
+ TORCH_ENUM_DECLARE(NearestExact)
128
+ TORCH_ENUM_DECLARE(Sum)
129
+ TORCH_ENUM_DECLARE(Mean)
130
+ TORCH_ENUM_DECLARE(Max)
131
+ TORCH_ENUM_DECLARE(None)
132
+ TORCH_ENUM_DECLARE(BatchMean)
133
+ TORCH_ENUM_DECLARE(Zeros)
134
+ TORCH_ENUM_DECLARE(Border)
135
+ TORCH_ENUM_DECLARE(Reflection)
136
+ TORCH_ENUM_DECLARE(RNN_TANH)
137
+ TORCH_ENUM_DECLARE(RNN_RELU)
138
+ TORCH_ENUM_DECLARE(LSTM)
139
+ TORCH_ENUM_DECLARE(GRU)
140
+ TORCH_ENUM_DECLARE(Valid)
141
+ TORCH_ENUM_DECLARE(Same)
142
+
143
+ namespace torch::enumtype {
144
+
145
+ struct _compute_enum_name {
146
+ TORCH_ENUM_PRETTY_PRINT(Linear)
147
+ TORCH_ENUM_PRETTY_PRINT(Conv1D)
148
+ TORCH_ENUM_PRETTY_PRINT(Conv2D)
149
+ TORCH_ENUM_PRETTY_PRINT(Conv3D)
150
+ TORCH_ENUM_PRETTY_PRINT(ConvTranspose1D)
151
+ TORCH_ENUM_PRETTY_PRINT(ConvTranspose2D)
152
+ TORCH_ENUM_PRETTY_PRINT(ConvTranspose3D)
153
+ TORCH_ENUM_PRETTY_PRINT(Sigmoid)
154
+ TORCH_ENUM_PRETTY_PRINT(Tanh)
155
+ TORCH_ENUM_PRETTY_PRINT(ReLU)
156
+ TORCH_ENUM_PRETTY_PRINT(GELU)
157
+ TORCH_ENUM_PRETTY_PRINT(SiLU)
158
+ TORCH_ENUM_PRETTY_PRINT(Mish)
159
+ TORCH_ENUM_PRETTY_PRINT(LeakyReLU)
160
+ TORCH_ENUM_PRETTY_PRINT(FanIn)
161
+ TORCH_ENUM_PRETTY_PRINT(FanOut)
162
+ TORCH_ENUM_PRETTY_PRINT(Constant)
163
+ TORCH_ENUM_PRETTY_PRINT(Reflect)
164
+ TORCH_ENUM_PRETTY_PRINT(Replicate)
165
+ TORCH_ENUM_PRETTY_PRINT(Circular)
166
+ TORCH_ENUM_PRETTY_PRINT(Nearest)
167
+ TORCH_ENUM_PRETTY_PRINT(Bilinear)
168
+ TORCH_ENUM_PRETTY_PRINT(Bicubic)
169
+ TORCH_ENUM_PRETTY_PRINT(Trilinear)
170
+ TORCH_ENUM_PRETTY_PRINT(Area)
171
+ TORCH_ENUM_PRETTY_PRINT(NearestExact)
172
+ TORCH_ENUM_PRETTY_PRINT(Sum)
173
+ TORCH_ENUM_PRETTY_PRINT(Mean)
174
+ TORCH_ENUM_PRETTY_PRINT(Max)
175
+ TORCH_ENUM_PRETTY_PRINT(None)
176
+ TORCH_ENUM_PRETTY_PRINT(BatchMean)
177
+ TORCH_ENUM_PRETTY_PRINT(Zeros)
178
+ TORCH_ENUM_PRETTY_PRINT(Border)
179
+ TORCH_ENUM_PRETTY_PRINT(Reflection)
180
+ TORCH_ENUM_PRETTY_PRINT(RNN_TANH)
181
+ TORCH_ENUM_PRETTY_PRINT(RNN_RELU)
182
+ TORCH_ENUM_PRETTY_PRINT(LSTM)
183
+ TORCH_ENUM_PRETTY_PRINT(GRU)
184
+ TORCH_ENUM_PRETTY_PRINT(Valid)
185
+ TORCH_ENUM_PRETTY_PRINT(Same)
186
+ };
187
+
188
+ template <typename V>
189
+ std::string get_enum_name(V variant_enum) {
190
+ return std::visit(enumtype::_compute_enum_name{}, variant_enum);
191
+ }
192
+
193
+ template <typename V>
194
+ at::Reduction::Reduction reduction_get_enum(V variant_enum) {
195
+ if (std::holds_alternative<enumtype::kNone>(variant_enum)) {
196
+ return at::Reduction::None;
197
+ } else if (std::holds_alternative<enumtype::kMean>(variant_enum)) {
198
+ return at::Reduction::Mean;
199
+ } else if (std::holds_alternative<enumtype::kSum>(variant_enum)) {
200
+ return at::Reduction::Sum;
201
+ } else {
202
+ TORCH_CHECK(
203
+ false,
204
+ get_enum_name(variant_enum),
205
+ " is not a valid value for reduction");
206
+ return at::Reduction::END;
207
+ }
208
+ }
209
+
210
+ } // namespace torch::enumtype
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/expanding_array.h ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <c10/util/ArrayRef.h>
4
+ #include <c10/util/Exception.h>
5
+ #include <c10/util/irange.h>
6
+ #include <optional>
7
+
8
+ #include <algorithm>
9
+ #include <array>
10
+ #include <cstdint>
11
+ #include <initializer_list>
12
+ #include <string>
13
+ #include <vector>
14
+
15
+ namespace torch {
16
+
17
+ /// A utility class that accepts either a container of `D`-many values, or a
18
+ /// single value, which is internally repeated `D` times. This is useful to
19
+ /// represent parameters that are multidimensional, but often equally sized in
20
+ /// all dimensions. For example, the kernel size of a 2D convolution has an `x`
21
+ /// and `y` length, but `x` and `y` are often equal. In such a case you could
22
+ /// just pass `3` to an `ExpandingArray<2>` and it would "expand" to `{3, 3}`.
23
+ template <size_t D, typename T = int64_t>
24
+ class ExpandingArray {
25
+ public:
26
+ /// Constructs an `ExpandingArray` from an `initializer_list`. The extent of
27
+ /// the length is checked against the `ExpandingArray`'s extent parameter `D`
28
+ /// at runtime.
29
+ /*implicit*/ ExpandingArray(std::initializer_list<T> list)
30
+ : ExpandingArray(c10::ArrayRef<T>(list)) {}
31
+
32
+ /// Constructs an `ExpandingArray` from an `std::vector`. The extent of
33
+ /// the length is checked against the `ExpandingArray`'s extent parameter `D`
34
+ /// at runtime.
35
+ /*implicit*/ ExpandingArray(std::vector<T> vec)
36
+ : ExpandingArray(c10::ArrayRef<T>(vec)) {}
37
+
38
+ /// Constructs an `ExpandingArray` from an `c10::ArrayRef`. The extent of
39
+ /// the length is checked against the `ExpandingArray`'s extent parameter `D`
40
+ /// at runtime.
41
+ /*implicit*/ ExpandingArray(c10::ArrayRef<T> values) {
42
+ // clang-format off
43
+ TORCH_CHECK(
44
+ values.size() == D,
45
+ "Expected ", D, " values, but instead got ", values.size());
46
+ // clang-format on
47
+ std::copy(values.begin(), values.end(), values_.begin());
48
+ }
49
+
50
+ /// Constructs an `ExpandingArray` from a single value, which is repeated `D`
51
+ /// times (where `D` is the extent parameter of the `ExpandingArray`).
52
+ /*implicit*/ ExpandingArray(T single_size) {
53
+ values_.fill(single_size);
54
+ }
55
+
56
+ /// Constructs an `ExpandingArray` from a correctly sized `std::array`.
57
+ /*implicit*/ ExpandingArray(const std::array<T, D>& values)
58
+ : values_(values) {}
59
+
60
+ /// Accesses the underlying `std::array`.
61
+ std::array<T, D>& operator*() {
62
+ return values_;
63
+ }
64
+
65
+ /// Accesses the underlying `std::array`.
66
+ const std::array<T, D>& operator*() const {
67
+ return values_;
68
+ }
69
+
70
+ /// Accesses the underlying `std::array`.
71
+ std::array<T, D>* operator->() {
72
+ return &values_;
73
+ }
74
+
75
+ /// Accesses the underlying `std::array`.
76
+ const std::array<T, D>* operator->() const {
77
+ return &values_;
78
+ }
79
+
80
+ /// Returns an `ArrayRef` to the underlying `std::array`.
81
+ operator c10::ArrayRef<T>() const {
82
+ return values_;
83
+ }
84
+
85
+ /// Returns the extent of the `ExpandingArray`.
86
+ size_t size() const noexcept {
87
+ return D;
88
+ }
89
+
90
+ protected:
91
+ /// The backing array.
92
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
93
+ std::array<T, D> values_;
94
+ };
95
+
96
+ template <size_t D, typename T>
97
+ std::ostream& operator<<(
98
+ std::ostream& stream,
99
+ const ExpandingArray<D, T>& expanding_array) {
100
+ if (expanding_array.size() == 1) {
101
+ return stream << expanding_array->at(0);
102
+ }
103
+ return stream << static_cast<c10::ArrayRef<T>>(expanding_array);
104
+ }
105
+
106
+ /// A utility class that accepts either a container of `D`-many
107
+ /// `std::optional<T>` values, or a single `std::optional<T>` value, which is
108
+ /// internally repeated `D` times. It has the additional ability to accept
109
+ /// containers of the underlying type `T` and convert them to a container of
110
+ /// `std::optional<T>`.
111
+ template <size_t D, typename T = int64_t>
112
+ class ExpandingArrayWithOptionalElem
113
+ : public ExpandingArray<D, std::optional<T>> {
114
+ public:
115
+ using ExpandingArray<D, std::optional<T>>::ExpandingArray;
116
+
117
+ /// Constructs an `ExpandingArrayWithOptionalElem` from an `initializer_list`
118
+ /// of the underlying type `T`. The extent of the length is checked against
119
+ /// the `ExpandingArrayWithOptionalElem`'s extent parameter `D` at runtime.
120
+ /*implicit*/ ExpandingArrayWithOptionalElem(std::initializer_list<T> list)
121
+ : ExpandingArrayWithOptionalElem(c10::ArrayRef<T>(list)) {}
122
+
123
+ /// Constructs an `ExpandingArrayWithOptionalElem` from an `std::vector` of
124
+ /// the underlying type `T`. The extent of the length is checked against the
125
+ /// `ExpandingArrayWithOptionalElem`'s extent parameter `D` at runtime.
126
+ /*implicit*/ ExpandingArrayWithOptionalElem(std::vector<T> vec)
127
+ : ExpandingArrayWithOptionalElem(c10::ArrayRef<T>(vec)) {}
128
+
129
+ /// Constructs an `ExpandingArrayWithOptionalElem` from an `c10::ArrayRef` of
130
+ /// the underlying type `T`. The extent of the length is checked against the
131
+ /// `ExpandingArrayWithOptionalElem`'s extent parameter `D` at runtime.
132
+ /*implicit*/ ExpandingArrayWithOptionalElem(c10::ArrayRef<T> values)
133
+ : ExpandingArray<D, std::optional<T>>(0) {
134
+ // clang-format off
135
+ TORCH_CHECK(
136
+ values.size() == D,
137
+ "Expected ", D, " values, but instead got ", values.size());
138
+ // clang-format on
139
+ for (const auto i : c10::irange(this->values_.size())) {
140
+ this->values_[i] = values[i];
141
+ }
142
+ }
143
+
144
+ /// Constructs an `ExpandingArrayWithOptionalElem` from a single value of the
145
+ /// underlying type `T`, which is repeated `D` times (where `D` is the extent
146
+ /// parameter of the `ExpandingArrayWithOptionalElem`).
147
+ /*implicit*/ ExpandingArrayWithOptionalElem(T single_size)
148
+ : ExpandingArray<D, std::optional<T>>(0) {
149
+ for (const auto i : c10::irange(this->values_.size())) {
150
+ this->values_[i] = single_size;
151
+ }
152
+ }
153
+
154
+ /// Constructs an `ExpandingArrayWithOptionalElem` from a correctly sized
155
+ /// `std::array` of the underlying type `T`.
156
+ /*implicit*/ ExpandingArrayWithOptionalElem(const std::array<T, D>& values)
157
+ : ExpandingArray<D, std::optional<T>>(0) {
158
+ for (const auto i : c10::irange(this->values_.size())) {
159
+ this->values_[i] = values[i];
160
+ }
161
+ }
162
+ };
163
+
164
+ template <size_t D, typename T>
165
+ std::ostream& operator<<(
166
+ std::ostream& stream,
167
+ const ExpandingArrayWithOptionalElem<D, T>& expanding_array_with_opt_elem) {
168
+ if (expanding_array_with_opt_elem.size() == 1) {
169
+ const auto& elem = expanding_array_with_opt_elem->at(0);
170
+ stream << (elem.has_value() ? c10::str(elem.value()) : "None");
171
+ } else {
172
+ std::vector<std::string> str_array;
173
+ for (const auto& elem : *expanding_array_with_opt_elem) {
174
+ str_array.emplace_back(
175
+ elem.has_value() ? c10::str(elem.value()) : "None");
176
+ }
177
+ stream << c10::ArrayRef<std::string>(str_array);
178
+ }
179
+ return stream;
180
+ }
181
+
182
+ } // namespace torch
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/fft.h ADDED
@@ -0,0 +1,390 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/ATen.h>
4
+ #include <torch/types.h>
5
+
6
+ #include <utility>
7
+
8
+ namespace torch::fft {
9
+
10
+ /// Computes the 1 dimensional fast Fourier transform over a given dimension.
11
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.fft.
12
+ ///
13
+ /// Example:
14
+ /// ```
15
+ /// auto t = torch::randn(128, dtype=kComplexDouble);
16
+ /// torch::fft::fft(t);
17
+ /// ```
18
+ inline Tensor fft(
19
+ const Tensor& self,
20
+ std::optional<SymInt> n = std::nullopt,
21
+ int64_t dim = -1,
22
+ std::optional<c10::string_view> norm = std::nullopt) {
23
+ return torch::fft_fft_symint(self, std::move(n), dim, norm);
24
+ }
25
+
26
+ /// Computes the 1 dimensional inverse Fourier transform over a given dimension.
27
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.ifft.
28
+ ///
29
+ /// Example:
30
+ /// ```
31
+ /// auto t = torch::randn(128, dtype=kComplexDouble);
32
+ /// torch::fft::ifft(t);
33
+ /// ```
34
+ inline Tensor ifft(
35
+ const Tensor& self,
36
+ std::optional<SymInt> n = std::nullopt,
37
+ int64_t dim = -1,
38
+ std::optional<c10::string_view> norm = std::nullopt) {
39
+ return torch::fft_ifft_symint(self, std::move(n), dim, norm);
40
+ }
41
+
42
+ /// Computes the 2-dimensional fast Fourier transform over the given dimensions.
43
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.fft2.
44
+ ///
45
+ /// Example:
46
+ /// ```
47
+ /// auto t = torch::randn({128, 128}, dtype=kComplexDouble);
48
+ /// torch::fft::fft2(t);
49
+ /// ```
50
+ inline Tensor fft2(
51
+ const Tensor& self,
52
+ OptionalIntArrayRef s = std::nullopt,
53
+ IntArrayRef dim = {-2, -1},
54
+ std::optional<c10::string_view> norm = std::nullopt) {
55
+ return torch::fft_fft2(self, s, dim, norm);
56
+ }
57
+
58
+ /// Computes the inverse of torch.fft.fft2
59
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.ifft2.
60
+ ///
61
+ /// Example:
62
+ /// ```
63
+ /// auto t = torch::randn({128, 128}, dtype=kComplexDouble);
64
+ /// torch::fft::ifft2(t);
65
+ /// ```
66
+ inline Tensor ifft2(
67
+ const Tensor& self,
68
+ at::OptionalIntArrayRef s = std::nullopt,
69
+ IntArrayRef dim = {-2, -1},
70
+ std::optional<c10::string_view> norm = std::nullopt) {
71
+ return torch::fft_ifft2(self, s, dim, norm);
72
+ }
73
+
74
+ /// Computes the N dimensional fast Fourier transform over given dimensions.
75
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.fftn.
76
+ ///
77
+ /// Example:
78
+ /// ```
79
+ /// auto t = torch::randn({128, 128}, dtype=kComplexDouble);
80
+ /// torch::fft::fftn(t);
81
+ /// ```
82
+ inline Tensor fftn(
83
+ const Tensor& self,
84
+ at::OptionalIntArrayRef s = std::nullopt,
85
+ at::OptionalIntArrayRef dim = std::nullopt,
86
+ std::optional<c10::string_view> norm = std::nullopt) {
87
+ return torch::fft_fftn(self, s, dim, norm);
88
+ }
89
+
90
+ /// Computes the N dimensional fast Fourier transform over given dimensions.
91
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.ifftn.
92
+ ///
93
+ /// Example:
94
+ /// ```
95
+ /// auto t = torch::randn({128, 128}, dtype=kComplexDouble);
96
+ /// torch::fft::ifftn(t);
97
+ /// ```
98
+ inline Tensor ifftn(
99
+ const Tensor& self,
100
+ at::OptionalIntArrayRef s = std::nullopt,
101
+ at::OptionalIntArrayRef dim = std::nullopt,
102
+ std::optional<c10::string_view> norm = std::nullopt) {
103
+ return torch::fft_ifftn(self, s, dim, norm);
104
+ }
105
+
106
+ /// Computes the 1 dimensional FFT of real input with onesided Hermitian output.
107
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.rfft.
108
+ ///
109
+ /// Example:
110
+ /// ```
111
+ /// auto t = torch::randn(128);
112
+ /// auto T = torch::fft::rfft(t);
113
+ /// assert(T.is_complex() && T.numel() == 128 / 2 + 1);
114
+ /// ```
115
+ inline Tensor rfft(
116
+ const Tensor& self,
117
+ std::optional<SymInt> n = std::nullopt,
118
+ int64_t dim = -1,
119
+ std::optional<c10::string_view> norm = std::nullopt) {
120
+ return torch::fft_rfft_symint(self, std::move(n), dim, norm);
121
+ }
122
+
123
+ /// Computes the inverse of torch.fft.rfft
124
+ ///
125
+ /// The input is a onesided Hermitian Fourier domain signal, with real-valued
126
+ /// output. See https://pytorch.org/docs/main/fft.html#torch.fft.irfft
127
+ ///
128
+ /// Example:
129
+ /// ```
130
+ /// auto T = torch::randn(128 / 2 + 1, torch::kComplexDouble);
131
+ /// auto t = torch::fft::irfft(t, /*n=*/128);
132
+ /// assert(t.is_floating_point() && T.numel() == 128);
133
+ /// ```
134
+ inline Tensor irfft(
135
+ const Tensor& self,
136
+ std::optional<SymInt> n = std::nullopt,
137
+ int64_t dim = -1,
138
+ std::optional<c10::string_view> norm = std::nullopt) {
139
+ return torch::fft_irfft_symint(self, std::move(n), dim, norm);
140
+ }
141
+
142
+ /// Computes the 2-dimensional FFT of real input. Returns a onesided Hermitian
143
+ /// output. See https://pytorch.org/docs/main/fft.html#torch.fft.rfft2
144
+ ///
145
+ /// Example:
146
+ /// ```
147
+ /// auto t = torch::randn({128, 128}, dtype=kDouble);
148
+ /// torch::fft::rfft2(t);
149
+ /// ```
150
+ inline Tensor rfft2(
151
+ const Tensor& self,
152
+ at::OptionalIntArrayRef s = std::nullopt,
153
+ IntArrayRef dim = {-2, -1},
154
+ std::optional<c10::string_view> norm = std::nullopt) {
155
+ return torch::fft_rfft2(self, s, dim, norm);
156
+ }
157
+
158
+ /// Computes the inverse of torch.fft.rfft2.
159
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.irfft2.
160
+ ///
161
+ /// Example:
162
+ /// ```
163
+ /// auto t = torch::randn({128, 128}, dtype=kComplexDouble);
164
+ /// torch::fft::irfft2(t);
165
+ /// ```
166
+ inline Tensor irfft2(
167
+ const Tensor& self,
168
+ at::OptionalIntArrayRef s = std::nullopt,
169
+ IntArrayRef dim = {-2, -1},
170
+ std::optional<c10::string_view> norm = std::nullopt) {
171
+ return torch::fft_irfft2(self, s, dim, norm);
172
+ }
173
+
174
+ /// Computes the N dimensional FFT of real input with onesided Hermitian output.
175
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.rfftn
176
+ ///
177
+ /// Example:
178
+ /// ```
179
+ /// auto t = torch::randn({128, 128}, dtype=kDouble);
180
+ /// torch::fft::rfftn(t);
181
+ /// ```
182
+ inline Tensor rfftn(
183
+ const Tensor& self,
184
+ at::OptionalIntArrayRef s = std::nullopt,
185
+ at::OptionalIntArrayRef dim = std::nullopt,
186
+ std::optional<c10::string_view> norm = std::nullopt) {
187
+ return torch::fft_rfftn(self, s, dim, norm);
188
+ }
189
+
190
+ /// Computes the inverse of torch.fft.rfftn.
191
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.irfftn.
192
+ ///
193
+ /// Example:
194
+ /// ```
195
+ /// auto t = torch::randn({128, 128}, dtype=kComplexDouble);
196
+ /// torch::fft::irfftn(t);
197
+ /// ```
198
+ inline Tensor irfftn(
199
+ const Tensor& self,
200
+ at::OptionalIntArrayRef s = std::nullopt,
201
+ at::OptionalIntArrayRef dim = std::nullopt,
202
+ std::optional<c10::string_view> norm = std::nullopt) {
203
+ return torch::fft_irfftn(self, s, dim, norm);
204
+ }
205
+
206
+ /// Computes the 1 dimensional FFT of a onesided Hermitian signal
207
+ ///
208
+ /// The input represents a Hermitian symmetric time domain signal. The returned
209
+ /// Fourier domain representation of such a signal is a real-valued. See
210
+ /// https://pytorch.org/docs/main/fft.html#torch.fft.hfft
211
+ ///
212
+ /// Example:
213
+ /// ```
214
+ /// auto t = torch::randn(128 / 2 + 1, torch::kComplexDouble);
215
+ /// auto T = torch::fft::hfft(t, /*n=*/128);
216
+ /// assert(T.is_floating_point() && T.numel() == 128);
217
+ /// ```
218
+ inline Tensor hfft(
219
+ const Tensor& self,
220
+ std::optional<SymInt> n = std::nullopt,
221
+ int64_t dim = -1,
222
+ std::optional<c10::string_view> norm = std::nullopt) {
223
+ return torch::fft_hfft_symint(self, std::move(n), dim, norm);
224
+ }
225
+
226
+ /// Computes the inverse FFT of a real-valued Fourier domain signal.
227
+ ///
228
+ /// The output is a onesided representation of the Hermitian symmetric time
229
+ /// domain signal. See https://pytorch.org/docs/main/fft.html#torch.fft.ihfft.
230
+ ///
231
+ /// Example:
232
+ /// ```
233
+ /// auto T = torch::randn(128, torch::kDouble);
234
+ /// auto t = torch::fft::ihfft(T);
235
+ /// assert(t.is_complex() && T.numel() == 128 / 2 + 1);
236
+ /// ```
237
+ inline Tensor ihfft(
238
+ const Tensor& self,
239
+ std::optional<SymInt> n = std::nullopt,
240
+ int64_t dim = -1,
241
+ std::optional<c10::string_view> norm = std::nullopt) {
242
+ return torch::fft_ihfft_symint(self, std::move(n), dim, norm);
243
+ }
244
+
245
+ /// Computes the 2-dimensional FFT of a Hermitian symmetric input signal.
246
+ ///
247
+ /// The input is a onesided representation of the Hermitian symmetric time
248
+ /// domain signal. See https://pytorch.org/docs/main/fft.html#torch.fft.hfft2.
249
+ ///
250
+ /// Example:
251
+ /// ```
252
+ /// auto t = torch::randn({128, 65}, torch::kComplexDouble);
253
+ /// auto T = torch::fft::hfft2(t, /*s=*/{128, 128});
254
+ /// assert(T.is_floating_point() && T.numel() == 128 * 128);
255
+ /// ```
256
+ inline Tensor hfft2(
257
+ const Tensor& self,
258
+ at::OptionalIntArrayRef s = std::nullopt,
259
+ IntArrayRef dim = {-2, -1},
260
+ std::optional<c10::string_view> norm = std::nullopt) {
261
+ return torch::fft_hfft2(self, s, dim, norm);
262
+ }
263
+
264
+ /// Computes the 2-dimensional IFFT of a real input signal.
265
+ ///
266
+ /// The output is a onesided representation of the Hermitian symmetric time
267
+ /// domain signal. See
268
+ /// https://pytorch.org/docs/main/fft.html#torch.fft.ihfft2.
269
+ ///
270
+ /// Example:
271
+ /// ```
272
+ /// auto T = torch::randn({128, 128}, torch::kDouble);
273
+ /// auto t = torch::fft::hfft2(T);
274
+ /// assert(t.is_complex() && t.size(1) == 65);
275
+ /// ```
276
+ inline Tensor ihfft2(
277
+ const Tensor& self,
278
+ at::OptionalIntArrayRef s = std::nullopt,
279
+ IntArrayRef dim = {-2, -1},
280
+ std::optional<c10::string_view> norm = std::nullopt) {
281
+ return torch::fft_ihfft2(self, s, dim, norm);
282
+ }
283
+
284
+ /// Computes the N-dimensional FFT of a Hermitian symmetric input signal.
285
+ ///
286
+ /// The input is a onesided representation of the Hermitian symmetric time
287
+ /// domain signal. See https://pytorch.org/docs/main/fft.html#torch.fft.hfftn.
288
+ ///
289
+ /// Example:
290
+ /// ```
291
+ /// auto t = torch::randn({128, 65}, torch::kComplexDouble);
292
+ /// auto T = torch::fft::hfftn(t, /*s=*/{128, 128});
293
+ /// assert(T.is_floating_point() && T.numel() == 128 * 128);
294
+ /// ```
295
+ inline Tensor hfftn(
296
+ const Tensor& self,
297
+ at::OptionalIntArrayRef s = std::nullopt,
298
+ IntArrayRef dim = {-2, -1},
299
+ std::optional<c10::string_view> norm = std::nullopt) {
300
+ return torch::fft_hfftn(self, s, dim, norm);
301
+ }
302
+
303
+ /// Computes the N-dimensional IFFT of a real input signal.
304
+ ///
305
+ /// The output is a onesided representation of the Hermitian symmetric time
306
+ /// domain signal. See
307
+ /// https://pytorch.org/docs/main/fft.html#torch.fft.ihfftn.
308
+ ///
309
+ /// Example:
310
+ /// ```
311
+ /// auto T = torch::randn({128, 128}, torch::kDouble);
312
+ /// auto t = torch::fft::hfft2(T);
313
+ /// assert(t.is_complex() && t.size(1) == 65);
314
+ /// ```
315
+ inline Tensor ihfftn(
316
+ const Tensor& self,
317
+ at::OptionalIntArrayRef s = std::nullopt,
318
+ IntArrayRef dim = {-2, -1},
319
+ std::optional<c10::string_view> norm = std::nullopt) {
320
+ return torch::fft_ihfftn(self, s, dim, norm);
321
+ }
322
+
323
+ /// Computes the discrete Fourier Transform sample frequencies for a signal of
324
+ /// size n.
325
+ ///
326
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.fftfreq
327
+ ///
328
+ /// Example:
329
+ /// ```
330
+ /// auto frequencies = torch::fft::fftfreq(128, torch::kDouble);
331
+ /// ```
332
+ inline Tensor fftfreq(int64_t n, double d, const TensorOptions& options = {}) {
333
+ return torch::fft_fftfreq(n, d, options);
334
+ }
335
+
336
+ inline Tensor fftfreq(int64_t n, const TensorOptions& options = {}) {
337
+ return torch::fft_fftfreq(n, /*d=*/1.0, options);
338
+ }
339
+
340
+ /// Computes the sample frequencies for torch.fft.rfft with a signal of size n.
341
+ ///
342
+ /// Like torch.fft.rfft, only the positive frequencies are included.
343
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.rfftfreq
344
+ ///
345
+ /// Example:
346
+ /// ```
347
+ /// auto frequencies = torch::fft::rfftfreq(128, torch::kDouble);
348
+ /// ```
349
+ inline Tensor rfftfreq(int64_t n, double d, const TensorOptions& options) {
350
+ return torch::fft_rfftfreq(n, d, options);
351
+ }
352
+
353
+ inline Tensor rfftfreq(int64_t n, const TensorOptions& options) {
354
+ return torch::fft_rfftfreq(n, /*d=*/1.0, options);
355
+ }
356
+
357
+ /// Reorders n-dimensional FFT output to have negative frequency terms first, by
358
+ /// a torch.roll operation.
359
+ ///
360
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.fftshift
361
+ ///
362
+ /// Example:
363
+ /// ```
364
+ /// auto x = torch::randn({127, 4});
365
+ /// auto centred_fft = torch::fft::fftshift(torch::fft::fftn(x));
366
+ /// ```
367
+ inline Tensor fftshift(
368
+ const Tensor& x,
369
+ at::OptionalIntArrayRef dim = std::nullopt) {
370
+ return torch::fft_fftshift(x, dim);
371
+ }
372
+
373
+ /// Inverse of torch.fft.fftshift
374
+ ///
375
+ /// See https://pytorch.org/docs/main/fft.html#torch.fft.ifftshift
376
+ ///
377
+ /// Example:
378
+ /// ```
379
+ /// auto x = torch::randn({127, 4});
380
+ /// auto shift = torch::fft::fftshift(x)
381
+ /// auto unshift = torch::fft::ifftshift(shift);
382
+ /// assert(torch::allclose(x, unshift));
383
+ /// ```
384
+ inline Tensor ifftshift(
385
+ const Tensor& x,
386
+ at::OptionalIntArrayRef dim = std::nullopt) {
387
+ return torch::fft_ifftshift(x, dim);
388
+ }
389
+
390
+ } // namespace torch::fft
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/imethod.h ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <ATen/core/ivalue.h>
3
+ #include <vector>
4
+
5
+ namespace torch {
6
+
7
+ class TORCH_API IMethod {
8
+ /*
9
+ IMethod provides a portable interface for torch methods, whether
10
+ they are backed by torchscript or python/deploy.
11
+
12
+ This is helpful since torchscript methods provide additional information
13
+ (e.g. FunctionSchema, Graph) which aren't available in pure python methods.
14
+
15
+ Higher level APIs should prefer depending on this interface rather
16
+ than a specific implementation of it, to promote portability and reuse, and
17
+ avoid unintentional dependencies on e.g. script methods.
18
+
19
+ Note: This API is experimental, and may evolve.
20
+ */
21
+ public:
22
+ using IValueList = std::vector<c10::IValue>;
23
+ using IValueMap = std::unordered_map<std::string, at::IValue>;
24
+
25
+ IMethod() = default;
26
+ IMethod(const IMethod&) = default;
27
+ IMethod& operator=(const IMethod&) = default;
28
+ IMethod(IMethod&&) noexcept = default;
29
+ IMethod& operator=(IMethod&&) noexcept = default;
30
+ virtual ~IMethod() = default;
31
+
32
+ virtual c10::IValue operator()(
33
+ std::vector<c10::IValue> args,
34
+ const IValueMap& kwargs = IValueMap()) const = 0;
35
+
36
+ virtual const std::string& name() const = 0;
37
+
38
+ // Returns an ordered list of argument names, possible in both
39
+ // script and python methods. This is a more portable dependency
40
+ // than a ScriptMethod FunctionSchema, which has more information
41
+ // than can be generally expected from a python method.
42
+ const std::vector<std::string>& getArgumentNames() const;
43
+
44
+ protected:
45
+ virtual void setArgumentNames(
46
+ std::vector<std::string>& argumentNames) const = 0;
47
+
48
+ private:
49
+ mutable bool isArgumentNamesInitialized_{false};
50
+ mutable std::vector<std::string> argumentNames_;
51
+ };
52
+
53
+ } // namespace torch
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/jit.h ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/csrc/jit/api/module.h>
5
+
6
+ #include <memory>
7
+ #include <string>
8
+
9
+ namespace torch::jit {
10
+
11
+ /// Compiles script code into an executable graph.
12
+ ///
13
+ /// Takes a string containing functions in script syntax and compiles them into
14
+ /// a module (graph). The returned module provides a `run_method` function
15
+ /// that may be used to invoke the compiled functions.
16
+ ///
17
+ /// For example:
18
+ /// \rst
19
+ /// .. code-block:: cpp
20
+ ///
21
+ /// auto module = torch::jit::compile(R"JIT(
22
+ /// def relu_script(a, b):
23
+ /// return torch.relu(a + b)
24
+ /// def test_while(a, i):
25
+ /// while i < 10:
26
+ /// a += a
27
+ /// i += 1
28
+ /// return a
29
+ /// )JIT");
30
+ /// IValue output = module->run_method("relu_script", a, b);
31
+ /// \endrst
32
+ TORCH_API std::shared_ptr<CompilationUnit> compile(const std::string& source);
33
+
34
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/mps.h ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+
5
+ #include <cstddef>
6
+ #include <cstdint>
7
+
8
+ #ifdef __OBJC__
9
+ #include <Foundation/Foundation.h>
10
+ #include <Metal/Metal.h>
11
+ using MTLCommandBuffer_t = id<MTLCommandBuffer>;
12
+ using DispatchQueue_t = dispatch_queue_t;
13
+ #else
14
+ using MTLCommandBuffer_t = void*;
15
+ using DispatchQueue_t = void*;
16
+ #endif
17
+
18
+ namespace torch::mps {
19
+
20
+ /// Returns true if MPS device is available.
21
+ bool TORCH_API is_available();
22
+
23
+ /// Sets the RNG seed for the MPS device.
24
+ void TORCH_API manual_seed(uint64_t seed);
25
+
26
+ /// Waits for all streams on the MPS device to complete.
27
+ /// This blocks the calling CPU thread by using the 'waitUntilCompleted()'
28
+ /// method to wait for Metal command buffers finish executing all the
29
+ /// encoded GPU operations before returning.
30
+ void TORCH_API synchronize();
31
+
32
+ /// Submits the currently active command buffer to run on the MPS device.
33
+ void TORCH_API commit();
34
+
35
+ /// Get the current command buffer to encode the Metal commands.
36
+ MTLCommandBuffer_t TORCH_API get_command_buffer();
37
+
38
+ /// Get the dispatch_queue_t to synchronize encoding the custom kernels
39
+ /// with the PyTorch MPS backend.
40
+ DispatchQueue_t TORCH_API get_dispatch_queue();
41
+
42
+ } // namespace torch::mps
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nested.h ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/ATen.h>
4
+ #include <ATen/core/ATen_fwd.h>
5
+ #include <torch/csrc/api/include/torch/detail/TensorDataContainer.h>
6
+ #include <algorithm>
7
+
8
+ namespace torch::nested {
9
+
10
+ /// Nested tensor
11
+ ///
12
+ /// See
13
+ /// https://pytorch.org/docs/main/nested.html#torch.nested.nested_tensor
14
+ ///
15
+ /// ```
16
+ // implemented on python object to allow torch.nested.nested_tensor to be
17
+ // constructed with arbitrarily nested python objects - for now, only arbitrary
18
+ // python lists and lists of Tensors
19
+ // See torch/csrc/autograd/python_nested_functions_manual.cpp for Python
20
+ // implementation
21
+ // See here for C++ implementation
22
+ inline at::Tensor nested_tensor(
23
+ at::TensorList nested_tensor_data,
24
+ const at::TensorOptions& options = {}) {
25
+ auto out = at::_nested_tensor_from_tensor_list(
26
+ nested_tensor_data,
27
+ c10::typeMetaToScalarType(options.dtype()),
28
+ std::nullopt,
29
+ options.device(),
30
+ options.pinned_memory());
31
+ if (options.has_requires_grad() && options.requires_grad()) {
32
+ out.requires_grad_(true);
33
+ }
34
+ return out;
35
+ }
36
+
37
+ inline at::Tensor nested_tensor(
38
+ at::ArrayRef<detail::TensorDataContainer> nested_tensor_data,
39
+ const at::TensorOptions& options = {}) {
40
+ for (const auto& tdc : nested_tensor_data) {
41
+ TORCH_CHECK(
42
+ tdc.is_init_list(),
43
+ "nested_tensor() not implemented for these parameters");
44
+ }
45
+ // Construct a TensorList using nested_tensor_data
46
+ std::vector<at::Tensor> tensor_list(nested_tensor_data.size());
47
+ std::transform(
48
+ nested_tensor_data.begin(),
49
+ nested_tensor_data.end(),
50
+ tensor_list.begin(),
51
+ [&](const detail::TensorDataContainer& tdc) {
52
+ return tdc.convert_to_tensor(options);
53
+ });
54
+ auto out = at::_nested_tensor_from_tensor_list(
55
+ tensor_list,
56
+ c10::typeMetaToScalarType(options.dtype()),
57
+ std::nullopt,
58
+ options.device(),
59
+ options.pinned_memory());
60
+ if (options.has_requires_grad() && options.requires_grad()) {
61
+ out.requires_grad_(true);
62
+ }
63
+ return out;
64
+ }
65
+
66
+ /// As Nested Tensor
67
+ ///
68
+ /// See
69
+ /// https://pytorch.org/docs/main/nested.html#torch.nested.as_nested_tensor
70
+ ///
71
+ /// ```
72
+ inline at::Tensor as_nested_tensor(
73
+ at::TensorList list,
74
+ std::optional<at::ScalarType> dtype = std::nullopt,
75
+ std::optional<at::Device> device = std::nullopt) {
76
+ return at::_nested_tensor_from_tensor_list(
77
+ list, dtype, std::nullopt, device, std::nullopt);
78
+ }
79
+
80
+ /// Nested to padded tensor
81
+ ///
82
+ /// See
83
+ /// https://pytorch.org/docs/main/nested.html#torch.nested.to_padded_tensor
84
+ ///
85
+ /// ```
86
+ inline at::Tensor to_padded_tensor(
87
+ const at::Tensor& self,
88
+ double padding,
89
+ at::OptionalIntArrayRef output_size = std::nullopt) {
90
+ return at::nested_to_padded_tensor(self, padding, output_size);
91
+ }
92
+
93
+ } // namespace torch::nested
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nn.h ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/nn/cloneable.h>
4
+ #include <torch/nn/functional.h>
5
+ #include <torch/nn/init.h>
6
+ #include <torch/nn/module.h>
7
+ #include <torch/nn/modules.h>
8
+ #include <torch/nn/options.h>
9
+ #include <torch/nn/pimpl.h>
10
+ #include <torch/nn/utils.h>
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nn/cloneable.h ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/nn/module.h>
4
+ #include <torch/types.h>
5
+ #include <torch/utils.h>
6
+
7
+ #include <c10/core/TensorOptions.h>
8
+ #include <c10/util/Exception.h>
9
+
10
+ #include <memory>
11
+ #include <utility>
12
+
13
+ namespace torch::nn {
14
+ /// The `clone()` method in the base `Module` class does not have knowledge of
15
+ /// the concrete runtime type of its subclasses. Therefore, `clone()` must
16
+ /// either be called from within the subclass, or from a base class that has
17
+ /// knowledge of the concrete type. `Cloneable` uses the CRTP to gain
18
+ /// knowledge of the subclass' static type and provide an implementation of the
19
+ /// `clone()` method. We do not want to use this pattern in the base class,
20
+ /// because then storing a module would always require templatizing it.
21
+ template <typename Derived>
22
+ // NOLINTNEXTLINE(bugprone-exception-escape)
23
+ class Cloneable : public Module {
24
+ public:
25
+ using Module::Module;
26
+
27
+ /// `reset()` must perform initialization of all members with reference
28
+ /// semantics, most importantly parameters, buffers and submodules.
29
+ virtual void reset() = 0;
30
+
31
+ /// Performs a recursive "deep copy" of the `Module`, such that all parameters
32
+ /// and submodules in the cloned module are different from those in the
33
+ /// original module.
34
+ std::shared_ptr<Module> clone(
35
+ const std::optional<Device>& device = std::nullopt) const override {
36
+ NoGradGuard no_grad;
37
+
38
+ const auto& self = static_cast<const Derived&>(*this);
39
+ auto copy = std::make_shared<Derived>(self);
40
+ copy->parameters_.clear();
41
+ copy->buffers_.clear();
42
+ copy->children_.clear();
43
+ copy->reset();
44
+ TORCH_CHECK(
45
+ copy->parameters_.size() == parameters_.size(),
46
+ "The cloned module does not have the same number of "
47
+ "parameters as the original module after calling reset(). "
48
+ "Are you sure you called register_parameter() inside reset() "
49
+ "and not the constructor?");
50
+ for (const auto& parameter : named_parameters(/*recurse=*/false)) {
51
+ auto& tensor = *parameter;
52
+ auto data = device && tensor.device() != *device ? tensor.to(*device)
53
+ : tensor.clone();
54
+ copy->parameters_[parameter.key()].set_data(data);
55
+ }
56
+ TORCH_CHECK(
57
+ copy->buffers_.size() == buffers_.size(),
58
+ "The cloned module does not have the same number of "
59
+ "buffers as the original module after calling reset(). "
60
+ "Are you sure you called register_buffer() inside reset() "
61
+ "and not the constructor?");
62
+ for (const auto& buffer : named_buffers(/*recurse=*/false)) {
63
+ auto& tensor = *buffer;
64
+ auto data = device && tensor.device() != *device ? tensor.to(*device)
65
+ : tensor.clone();
66
+ copy->buffers_[buffer.key()].set_data(data);
67
+ }
68
+ TORCH_CHECK(
69
+ copy->children_.size() == children_.size(),
70
+ "The cloned module does not have the same number of "
71
+ "child modules as the original module after calling reset(). "
72
+ "Are you sure you called register_module() inside reset() "
73
+ "and not the constructor?");
74
+ for (const auto& child : children_) {
75
+ copy->children_[child.key()]->clone_(*child.value(), device);
76
+ }
77
+ return copy;
78
+ }
79
+
80
+ private:
81
+ void clone_(Module& other, const std::optional<Device>& device) final {
82
+ // Here we are *pretty* certain that `other's` type is `Derived` (because it
83
+ // was registered under the same name as `this`), but you never know what
84
+ // crazy things `reset()` does, so `dynamic_cast` just to be safe.
85
+ auto clone = std::dynamic_pointer_cast<Derived>(other.clone(device));
86
+ TORCH_CHECK(
87
+ clone != nullptr,
88
+ "Attempted to clone submodule, but it is of a "
89
+ "different type than the submodule it was to be cloned into");
90
+ static_cast<Derived&>(*this) = *clone;
91
+ }
92
+ };
93
+
94
+ } // namespace torch::nn
lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nn/functional.h ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/nn/functional/batchnorm.h>
4
+ #include <torch/nn/functional/conv.h>
5
+ #include <torch/nn/functional/distance.h>
6
+ #include <torch/nn/functional/dropout.h>
7
+ #include <torch/nn/functional/embedding.h>
8
+ #include <torch/nn/functional/fold.h>
9
+ #include <torch/nn/functional/instancenorm.h>
10
+ #include <torch/nn/functional/linear.h>
11
+ #include <torch/nn/functional/loss.h>
12
+ #include <torch/nn/functional/normalization.h>
13
+ #include <torch/nn/functional/padding.h>
14
+ #include <torch/nn/functional/pixelshuffle.h>
15
+ #include <torch/nn/functional/pooling.h>
16
+ #include <torch/nn/functional/upsampling.h>
17
+ #include <torch/nn/functional/vision.h>