Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/all.h +23 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/arg.h +23 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/autograd.h +5 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/cuda.h +28 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data.h +13 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader.h +54 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/base.h +250 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/stateful.h +61 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader/stateless.h +80 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/dataloader_options.h +63 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/base.h +96 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/chunk.h +526 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/map.h +114 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/mnist.h +44 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/shared.h +79 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/stateful.h +64 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/datasets/tensor.h +34 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/data_shuttle.h +83 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/queue.h +80 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/detail/sequencers.h +107 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/example.h +53 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/iterator.h +178 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/base.h +41 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/custom_batch_request.h +17 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/distributed.h +133 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/random.h +48 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/sequential.h +44 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/serialize.h +24 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/samplers/stream.h +57 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms.h +7 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/base.h +49 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/collate.h +31 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/lambda.h +52 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/stack.h +45 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/transforms/tensor.h +73 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/data/worker_exception.h +37 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/detail/TensorDataContainer.h +351 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/detail/static.h +60 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/enum.h +210 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/expanding_array.h +182 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/fft.h +390 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/imethod.h +53 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/jit.h +34 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/mps.h +42 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nested.h +93 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nn.h +10 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/api/include/torch/nn/cloneable.h +94 -0
- 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>
|