anhtld commited on
Commit
89cc407
·
verified ·
1 Parent(s): be4a23c

Auto-sync: 2026-06-25 22:43:25 (part 27)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +6 -0
  2. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/python/update_graph_executor_opt.h +11 -0
  3. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/python/utf8_decoding_ignore.h +11 -0
  4. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/resource_guard.h +30 -0
  5. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/argument_spec.h +509 -0
  6. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/autodiff.h +99 -0
  7. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/calculate_necessary_args.h +74 -0
  8. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/custom_operator.h +35 -0
  9. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/decomposition_registry.h +38 -0
  10. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/decomposition_registry_util.h +17 -0
  11. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/exception_message.h +34 -0
  12. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_executor.h +157 -0
  13. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_executor_impl.h +123 -0
  14. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_iterator.h +152 -0
  15. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/instruction.h +103 -0
  16. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter.h +165 -0
  17. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/can_emit_inline.h +111 -0
  18. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/code_impl.h +1066 -0
  19. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/frame.h +45 -0
  20. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/preprocess_graph.h +24 -0
  21. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/jit_exception.h +43 -0
  22. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/jit_trace.h +13 -0
  23. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/logging.h +94 -0
  24. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/operator.h +348 -0
  25. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/operator_options.h +14 -0
  26. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/print_handler.h +20 -0
  27. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/profiling_graph_executor_impl.h +87 -0
  28. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/profiling_record.h +211 -0
  29. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/register_ops_utils.h +888 -0
  30. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/script_profile.h +108 -0
  31. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/serialized_shape_function_registry.h +20 -0
  32. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/shape_function_registry.h +17 -0
  33. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/simple_graph_executor_impl.h +31 -0
  34. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/slice_indices_adjust.h +31 -0
  35. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/ProcessedNodeInputs.h +246 -0
  36. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/fusion.h +20 -0
  37. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/impl.h +1152 -0
  38. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/init.h +12 -0
  39. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/memory_planner.h +303 -0
  40. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/ops.h +192 -0
  41. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/passes.h +96 -0
  42. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/processed_node_wrapper.h +216 -0
  43. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/static_method.h +53 -0
  44. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/te_wrapper.h +49 -0
  45. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_script.h +23 -0
  46. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_shape_registry.h +74 -0
  47. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_shape_registry_util.h +17 -0
  48. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/vararg_functions.h +46 -0
  49. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/variable_tensor_list.h +22 -0
  50. outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/serialization/callstack_debug_info_serialization.h +94 -0
.gitattributes CHANGED
@@ -125,3 +125,9 @@ outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/t64.exe filt
125
  outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64-arm.exe filter=lfs diff=lfs merge=lfs -text
126
  outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64.exe filter=lfs diff=lfs merge=lfs -text
127
  outputs/audit_venv/lib/python3.11/site-packages/pydantic_core/_pydantic_core.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
125
  outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64-arm.exe filter=lfs diff=lfs merge=lfs -text
126
  outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64.exe filter=lfs diff=lfs merge=lfs -text
127
  outputs/audit_venv/lib/python3.11/site-packages/pydantic_core/_pydantic_core.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
128
+ outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libc10.so filter=lfs diff=lfs merge=lfs -text
129
+ outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libc10_cuda.so filter=lfs diff=lfs merge=lfs -text
130
+ outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cpu.so filter=lfs diff=lfs merge=lfs -text
131
+ outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cuda.so filter=lfs diff=lfs merge=lfs -text
132
+ outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cuda_linalg.so filter=lfs diff=lfs merge=lfs -text
133
+ outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_python.so filter=lfs diff=lfs merge=lfs -text
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/python/update_graph_executor_opt.h ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <torch/csrc/Export.h>
4
+ namespace torch::jit {
5
+ TORCH_API void setGraphExecutorOptimize(bool o);
6
+ TORCH_API bool getGraphExecutorOptimize();
7
+ } // namespace torch::jit
8
+
9
+ #else
10
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
11
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/python/utf8_decoding_ignore.h ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <torch/csrc/Export.h>
4
+ namespace torch::jit {
5
+ TORCH_API void setUTF8DecodingIgnore(bool o);
6
+ TORCH_API bool getUTF8DecodingIgnore();
7
+ } // namespace torch::jit
8
+
9
+ #else
10
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
11
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/resource_guard.h ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <functional>
4
+
5
+ namespace torch::jit {
6
+
7
+ class ResourceGuard {
8
+ std::function<void()> _destructor;
9
+ bool _released{false};
10
+
11
+ public:
12
+ ResourceGuard(std::function<void()> destructor)
13
+ : _destructor(std::move(destructor)) {}
14
+
15
+ // NOLINTNEXTLINE(bugprone-exception-escape)
16
+ ~ResourceGuard() {
17
+ if (!_released)
18
+ _destructor();
19
+ }
20
+
21
+ void release() {
22
+ _released = true;
23
+ }
24
+ };
25
+
26
+ } // namespace torch::jit
27
+
28
+ #else
29
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
30
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/argument_spec.h ADDED
@@ -0,0 +1,509 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <ATen/core/jit_type.h>
5
+ #include <ATen/core/stack.h>
6
+ #include <c10/util/hash.h>
7
+ #include <c10/util/irange.h>
8
+ #include <torch/csrc/Export.h>
9
+ #include <torch/csrc/autograd/variable.h>
10
+ #include <torch/csrc/jit/ir/ir.h>
11
+ #include <ostream>
12
+ #include <vector>
13
+
14
+ C10_CLANG_DIAGNOSTIC_PUSH()
15
+ #if C10_CLANG_HAS_WARNING("-Wshorten-64-to-32")
16
+ C10_CLANG_DIAGNOSTIC_IGNORE("-Wshorten-64-to-32")
17
+ #endif
18
+
19
+ namespace torch::jit {
20
+
21
+ // GraphExecutor creates specializations of Graphs for different
22
+ // dimensionalitities and types of inputs.
23
+
24
+ struct ArgumentInfo {
25
+ friend struct ArgumentSpec;
26
+ using plain_data_type = uint64_t;
27
+
28
+ bool defined() const {
29
+ return defined_;
30
+ }
31
+ at::Device device() const {
32
+ return at::Device(DeviceType(dev_type_), device_);
33
+ }
34
+ // XXX: It is guaranteed that this will return false when called on non-tensor
35
+ // arguments
36
+ bool requires_grad() const {
37
+ return requires_grad_;
38
+ }
39
+ int dim() const {
40
+ return dim_;
41
+ }
42
+ at::ScalarType type() const {
43
+ return at::ScalarType(type_);
44
+ }
45
+ TypePtr toType() const {
46
+ if (!defined())
47
+ return TensorType::get();
48
+
49
+ return TensorType::create(
50
+ type(), device(), std::optional<size_t>(dim()), requires_grad());
51
+ }
52
+ operator TypePtr() const {
53
+ return toType();
54
+ }
55
+
56
+ private:
57
+ unsigned defined_ : 1;
58
+ unsigned requires_grad_ : 1;
59
+ unsigned : 5;
60
+ unsigned dim_ : 8;
61
+ unsigned device_ : 8;
62
+ unsigned type_ : 8;
63
+ unsigned dev_type_ : 16;
64
+ unsigned : 16;
65
+ };
66
+
67
+ static_assert(
68
+ std::is_standard_layout_v<ArgumentInfo>,
69
+ "ArgumentInfo is to be a POD struct");
70
+ static_assert(
71
+ sizeof(ArgumentInfo) == sizeof(ArgumentInfo::plain_data_type),
72
+ "ArgumentInfo is expected to be a 32-bit struct");
73
+
74
+ struct ArgumentSpec {
75
+ ArgumentSpec(size_t num_flat_tensor_inputs, size_t num_flat_optional_inputs)
76
+ : hash_code(c10::hash_combine(
77
+ num_flat_tensor_inputs,
78
+ num_flat_optional_inputs)) {
79
+ tensor_args.reserve(num_flat_tensor_inputs);
80
+ optional_presence.reserve(num_flat_optional_inputs);
81
+ }
82
+
83
+ void addOptional(const IValue& input) {
84
+ bool is_present = !input.isNone();
85
+ optional_presence.push_back(is_present);
86
+ hash_code = c10::hash_combine(hash_code, is_present);
87
+ }
88
+
89
+ void addTensor(const IValue& input, bool with_grad) {
90
+ AT_ASSERT(input.isTensor(), "Expected Tensor but found ", input.tagKind());
91
+ tensor_args.emplace_back();
92
+ auto& arg = tensor_args.back();
93
+ // Initialize all fields to 0. This is convenient, because e.g.
94
+ // requires_grad() can be checked even on tensors AND will make
95
+ // padding bits all 0s.
96
+ std::memset(&arg, 0, sizeof(ArgumentInfo));
97
+
98
+ // [argspec refcounting] reinterpret the IValue to avoid having to refcount
99
+ // the Tensor microbenchmarks
100
+ // https://github.com/zdevito/pytorch/commit/21e7200a0a0fc456bea2f10e95b1781f83933d10
101
+ // show overhead in extra refcounting along this path
102
+ const at::Tensor* t = reinterpret_cast<const at::Tensor*>(&input);
103
+ arg.defined_ = t->defined();
104
+ if (arg.defined_) {
105
+ arg.requires_grad_ = with_grad && t->requires_grad();
106
+ arg.dim_ = t->dim();
107
+ at::Device device = t->device();
108
+ arg.dev_type_ =
109
+ // NOLINTNEXTLINE(bugprone-signed-char-misuse)
110
+ static_cast<std::underlying_type_t<DeviceType>>(device.type());
111
+ // NOLINTNEXTLINE(bugprone-signed-char-misuse)
112
+ arg.device_ = device.index();
113
+ arg.type_ = static_cast<unsigned>(t->scalar_type());
114
+ }
115
+ combineHash(arg);
116
+ }
117
+
118
+ void combineHash(const ArgumentInfo& arg) {
119
+ ArgumentInfo::plain_data_type arg_data = 0;
120
+ std::memcpy(&arg_data, &arg, sizeof(ArgumentInfo));
121
+ hash_code = c10::hash_combine(hash_code, arg_data);
122
+ }
123
+
124
+ // equality is fast: check ninputs, and then check the raw array data,
125
+ // there are no size/stride indirections
126
+ // hopefully std::vector<bool> has fast equality
127
+ bool operator==(const ArgumentSpec& spec) const {
128
+ if (optional_presence != spec.optional_presence) {
129
+ return false;
130
+ }
131
+ if (tensor_args.size() != spec.tensor_args.size())
132
+ return false;
133
+ // NB: we need to break out early when there are no elements, because
134
+ // passing a nullptr to memcmp is UB.
135
+ if (tensor_args.empty())
136
+ return true;
137
+ return std::memcmp(
138
+ tensor_args.data(),
139
+ spec.tensor_args.data(),
140
+ tensor_args.size() * sizeof(ArgumentInfo)) == 0;
141
+ }
142
+ bool operator!=(const ArgumentSpec& spec) const {
143
+ return !(*this == spec);
144
+ }
145
+ size_t numTensors() const {
146
+ return tensor_args.size();
147
+ }
148
+ const ArgumentInfo& tensorAt(size_t i) const {
149
+ return tensor_args[i];
150
+ }
151
+ size_t numOptionals() const {
152
+ return optional_presence.size();
153
+ }
154
+ bool isPresent(size_t i) const {
155
+ return optional_presence[i];
156
+ }
157
+ size_t hashCode() const noexcept {
158
+ return hash_code;
159
+ }
160
+
161
+ private:
162
+ size_t hash_code; // precomputed on construction
163
+ std::vector<ArgumentInfo> tensor_args;
164
+ std::vector<bool> optional_presence;
165
+ };
166
+
167
+ namespace {
168
+ static constexpr size_t ARG_SPEC_DEPTH_LIMIT = 128;
169
+ }
170
+
171
+ // ArgumentSpecCreator takes an initial graph and comes up with a set
172
+ // of simple instructions to compute the ArgumentSpec given a set of
173
+ // input tensors.
174
+ struct TORCH_API ArgumentSpecCreator {
175
+ // instructs acts on a stack of a list of input IValues
176
+ // at the beginning the stack contains a single list of the inputs to the
177
+ // function the ENTER_ instructs descend into subobjects and push new lists
178
+ // onto the stack
179
+ enum Inst : char {
180
+ ENTER_TUPLE, // consume a tuple ivalue from the top-most list, and push the
181
+ // list of its elements onto the stack as a new list
182
+ ENTER_OBJECT, // same as ENTER_TUPLE, but the input is a class
183
+ LEAVE, // pop the top-most list from the stack
184
+ SKIP, // consume an element from the top-most list, and discard
185
+ SPECIALIZE_OPTIONAL_TENSOR, // consume a optional tensor for the top-most
186
+ // list, and add it to the ArgSpec key being
187
+ // created
188
+ SPECIALIZE_TENSOR, // consume a tensor for the top-most
189
+ // list, and add it to the ArgSpec key being created
190
+ SPECIALIZE_OPTIONAL,
191
+ // consume a nontensor optional from the top-most list,
192
+ // and add it to the ArgSpec key being created
193
+ };
194
+ ArgumentSpecCreator(Graph& graph);
195
+ ArgumentSpec create(bool with_grad, const Stack& stack) const;
196
+ void specializeTypes(Graph& g, const ArgumentSpec& spec) const;
197
+ void dump() const;
198
+ using WrittenSlots = std::unordered_set<std::string>;
199
+
200
+ private:
201
+ void scan(
202
+ const TypePtr& typ,
203
+ size_t depth,
204
+ const WrittenSlots& written_slots);
205
+ size_t num_inputs_;
206
+ size_t num_tensors_ = 0;
207
+ size_t num_optionals_ = 0;
208
+ std::vector<Inst> instructions_;
209
+ };
210
+
211
+ // CompleteArgumentSpec represents one particular specialization.
212
+ // It is designed so that it can be created, hashed, and compared quickly
213
+ // since it is used along the hot-path of the JIT to check if the code
214
+ // we have created is valid for the given inputs.
215
+
216
+ // COmpleteArgumentInfoPOD is only used internally in CompleteArgumentSpec
217
+ // API users should use ArgumentInfo
218
+ struct CompleteArgumentInfoPOD {
219
+ // total size is 64-bit
220
+ unsigned is_tensor : 8; // all other fields are invalid if this is false
221
+ unsigned type : 8; // scalar type
222
+ unsigned defined : 1;
223
+ unsigned requires_grad : 1;
224
+ signed device : 14;
225
+ unsigned dev_type : 16;
226
+ unsigned
227
+ total_dims : 16; // all TensorInfoPODs are in CompleteArgumentSpec's
228
+ // tensor_info() array. total_dims is the total number of
229
+ // dimensions seen so far in all previous members of
230
+ // tensor_info(), including this tensor 2*total_dims
231
+ // becomes the offset into the sizes_strides list for the
232
+ // _next_ tensor in the tensor_info array for tensor 0,
233
+ // the offset is always 0
234
+ };
235
+
236
+ static_assert(
237
+ sizeof(CompleteArgumentInfoPOD) == sizeof(int64_t),
238
+ "CompleteArgumentInfoPOD must be 64-bit struct for CompleteArgumentSpec encoding to work");
239
+
240
+ struct CompleteArgumentInfo;
241
+
242
+ struct CompleteArgumentSpec {
243
+ CompleteArgumentSpec(bool with_grad, at::ArrayRef<IValue> inputs)
244
+ : ninputs(inputs.size()) {
245
+ int64_t all_dims = 0;
246
+ const auto num_inputs = inputs.size();
247
+ for (const auto i : c10::irange(num_inputs)) {
248
+ if (!inputs[i].isTensor())
249
+ continue;
250
+ auto& tensor = inputs[i].toTensor();
251
+ all_dims += tensor.defined() ? tensor.ndimension() : 0;
252
+ }
253
+ // allocate enough room for all TensorPODs and dimensions
254
+ data.resize(ninputs + all_dims * 2);
255
+
256
+ // and reinterpret our data array as these structs
257
+ auto* pods = reinterpret_cast<CompleteArgumentInfoPOD*>(data.data());
258
+ int64_t* next_dim = sizes_strides();
259
+ int32_t total_dims = 0;
260
+ for (const auto i : c10::irange(num_inputs)) {
261
+ auto& pod = pods[i];
262
+ pod.is_tensor = static_cast<uint32_t>(inputs[i].isTensor());
263
+ if (pod.is_tensor) {
264
+ at::Tensor t = inputs[i].toTensor();
265
+ pod.defined = t.defined();
266
+ if (pod.defined) {
267
+ pod.type = static_cast<int>(t.scalar_type());
268
+ at::Device device = t.device();
269
+ // NOLINTNEXTLINE(bugprone-signed-char-misuse)
270
+ pod.dev_type =
271
+ static_cast<std::underlying_type_t<DeviceType>>(device.type());
272
+ // NOLINTNEXTLINE(bugprone-signed-char-misuse)
273
+ pod.device = device.index();
274
+ pod.requires_grad = with_grad && t.requires_grad();
275
+ total_dims += t.ndimension();
276
+ auto sizes = t.sizes();
277
+ std::copy(sizes.begin(), sizes.end(), next_dim);
278
+ next_dim += sizes.size();
279
+ auto strides = t.strides();
280
+ std::copy(strides.begin(), strides.end(), next_dim);
281
+ next_dim += strides.size();
282
+ }
283
+ }
284
+ // each POD has a running tally of all dimensions including its own
285
+ TORCH_CHECK(
286
+ total_dims < std::numeric_limits<uint16_t>::max(),
287
+ "The number of dims cannot be packed into CompleteArgumentSpec:",
288
+ total_dims);
289
+ pod.total_dims = total_dims;
290
+ }
291
+ // we precompute the hash_code to minimize the time inside of hash
292
+ // table operations where we may need to hold a compiler cache lock.
293
+ hash_code = c10::hash_combine(0, ninputs);
294
+ for (auto d : data) {
295
+ hash_code = c10::hash_combine(hash_code, d);
296
+ }
297
+ }
298
+
299
+ // equality is fast: check ninputs, and then check the raw array data,
300
+ // there are no size/stride indirections
301
+ bool operator==(const CompleteArgumentSpec& spec) const {
302
+ return ninputs == spec.ninputs && data == spec.data;
303
+ }
304
+ bool operator!=(const CompleteArgumentSpec& spec) const {
305
+ return !(*this == spec);
306
+ }
307
+ friend struct CompleteArgumentInfo;
308
+ CompleteArgumentInfo at(size_t i) const;
309
+ size_t size() const {
310
+ return ninputs;
311
+ }
312
+ size_t hashCode() const noexcept {
313
+ return hash_code;
314
+ }
315
+
316
+ private:
317
+ ArrayRef<CompleteArgumentInfoPOD> tensor_info() const {
318
+ return ArrayRef<CompleteArgumentInfoPOD>(
319
+ reinterpret_cast<const CompleteArgumentInfoPOD*>(data.data()), ninputs);
320
+ }
321
+ // the start of the sizes_strides information, which comes after the
322
+ // CompleteArgumentInfoPOD list.
323
+ const int64_t* sizes_strides() const {
324
+ return data.data() + ninputs;
325
+ }
326
+ int64_t* sizes_strides() {
327
+ return data.data() + ninputs;
328
+ }
329
+ size_t hash_code{0}; // precomputed on construction
330
+ size_t ninputs;
331
+ // layout is ninputs of TensorPOD (each 64-bit) followed by their size and
332
+ // stride info for 3 tensors:
333
+ // [t0POD][t1POD][t2POD]...
334
+ // [t0 sizes][t0 strides][t1 sizes][t1 strides][t2 sizes][t2 strides]
335
+ std::vector<int64_t> data;
336
+ };
337
+
338
+ // public view of compressed CompleteArgumentInfo
339
+ struct CompleteArgumentInfo {
340
+ CompleteArgumentInfo(const CompleteArgumentSpec& spec, const int i)
341
+ : spec(spec), i(i) {}
342
+ bool isTensor() const {
343
+ return pod(i).is_tensor;
344
+ }
345
+ at::ScalarType type() const {
346
+ return at::ScalarType(pod(i).type);
347
+ }
348
+ bool defined() const {
349
+ return pod(i).defined;
350
+ }
351
+ bool requires_grad() const {
352
+ return pod(i).requires_grad;
353
+ }
354
+ at::Device device() const {
355
+ return at::Device(
356
+ DeviceType(pod(i).dev_type),
357
+ static_cast<c10::DeviceIndex>(pod(i).device));
358
+ }
359
+ int ndimension() const {
360
+ // See [valid range], it is always valid to ask for offset for (i + 1)
361
+ return (sizes_strides_offset(i + 1) - sizes_strides_offset(i)) / 2;
362
+ }
363
+ at::IntArrayRef sizes() const {
364
+ return at::IntArrayRef(
365
+ spec.sizes_strides() + sizes_strides_offset(i), ndimension());
366
+ }
367
+ at::IntArrayRef strides() const {
368
+ int ndim = ndimension();
369
+ return at::IntArrayRef(
370
+ spec.sizes_strides() + sizes_strides_offset(i) + ndim, ndim);
371
+ }
372
+ operator TypePtr() const {
373
+ if (!defined())
374
+ return TensorType::get();
375
+ return TensorType::create(
376
+ type(),
377
+ device(),
378
+ c10::VaryingShape<int64_t>{sizes()},
379
+ c10::VaryingShape<int64_t>{strides()},
380
+ requires_grad());
381
+ }
382
+
383
+ private:
384
+ // offsetinto sizes_strides() array where the sizes start for tensor j
385
+ // [valid range] valid range is [0, ninputs]
386
+ // (i.e. you can ask for the offset at ninputs, which would be the offset of
387
+ // the next tensor if it existed)
388
+ int sizes_strides_offset(int j) const {
389
+ if (j == 0)
390
+ return 0;
391
+ return 2 * pod(j - 1).total_dims;
392
+ }
393
+ const CompleteArgumentInfoPOD& pod(int j) const {
394
+ return spec.tensor_info().at(j);
395
+ }
396
+ const CompleteArgumentSpec& spec;
397
+ const int i;
398
+ };
399
+
400
+ inline std::ostream& operator<<(std::ostream& out, const ArgumentInfo& info) {
401
+ if (!info.defined()) {
402
+ return out << "<undefined>";
403
+ }
404
+ out << "Tensor(device=" << info.device() << ", type=" << toString(info.type())
405
+ << ", requires_grad=" << info.requires_grad() << ", dims=" << info.dim()
406
+ << ')';
407
+ return out;
408
+ }
409
+
410
+ inline std::ostream& operator<<(std::ostream& out, const ArgumentSpec& spec) {
411
+ out << '{';
412
+ for (const auto i : c10::irange(spec.numTensors())) {
413
+ if (i > 0)
414
+ out << ", ";
415
+ out << spec.tensorAt(i);
416
+ }
417
+ out << "; ";
418
+ for (const auto i : c10::irange(spec.numOptionals())) {
419
+ if (i > 0)
420
+ out << ", ";
421
+ out << spec.isPresent(i);
422
+ }
423
+ out << '}';
424
+ return out;
425
+ }
426
+
427
+ inline std::ostream& operator<<(
428
+ std::ostream& out,
429
+ const CompleteArgumentInfo& info) {
430
+ if (!info.defined()) {
431
+ return out << "<undefined>";
432
+ }
433
+ out << "Tensor(device=" << info.device() << ", type=" << toString(info.type())
434
+ << ", requires_grad=" << info.requires_grad()
435
+ << ", sizes=" << info.sizes() << ", strides=" << info.strides() << ')';
436
+ return out;
437
+ }
438
+
439
+ inline std::ostream& operator<<(
440
+ std::ostream& out,
441
+ const CompleteArgumentSpec& spec) {
442
+ out << '{';
443
+ for (const auto i : c10::irange(spec.size())) {
444
+ if (i > 0)
445
+ out << ", ";
446
+ out << spec.at(i);
447
+ }
448
+ out << '}';
449
+ return out;
450
+ }
451
+
452
+ inline CompleteArgumentInfo CompleteArgumentSpec::at(size_t i) const {
453
+ return CompleteArgumentInfo(*this, i);
454
+ }
455
+
456
+ inline std::optional<int8_t> convertOptional(
457
+ std::optional<c10::ScalarType> const& from) {
458
+ return from ? std::optional<int8_t>(static_cast<int8_t>(*from))
459
+ : std::optional<int8_t>{};
460
+ }
461
+
462
+ } // namespace torch::jit
463
+
464
+ namespace std {
465
+
466
+ template <typename T>
467
+ struct hash<c10::VaryingShape<T>> {
468
+ size_t operator()(const c10::VaryingShape<T>& vs) const {
469
+ return c10::get_hash(
470
+ vs.size(),
471
+ vs.size() ? vs.sizes().value() : std::vector<std::optional<T>>());
472
+ }
473
+ };
474
+
475
+ template <>
476
+ struct hash<c10::TensorType> {
477
+ size_t operator()(const c10::TensorType& ptt) const {
478
+ return c10::get_hash<
479
+ std::optional<int8_t>,
480
+ c10::VaryingShape<int64_t>,
481
+ c10::VaryingShape<int64_t>,
482
+ std::optional<bool>>(
483
+ torch::jit::convertOptional(ptt.scalarType()),
484
+ ptt.sizes(),
485
+ ptt.strides(),
486
+ ptt.requiresGrad());
487
+ }
488
+ };
489
+
490
+ template <>
491
+ struct hash<torch::jit::ArgumentSpec> {
492
+ size_t operator()(const torch::jit::ArgumentSpec& spec) const noexcept {
493
+ return spec.hashCode();
494
+ }
495
+ };
496
+ template <>
497
+ struct hash<torch::jit::CompleteArgumentSpec> {
498
+ size_t operator()(
499
+ const torch::jit::CompleteArgumentSpec& spec) const noexcept {
500
+ return spec.hashCode();
501
+ }
502
+ };
503
+ } // namespace std
504
+
505
+ C10_CLANG_DIAGNOSTIC_POP()
506
+
507
+ #else
508
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
509
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/autodiff.h ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/Export.h>
5
+ #include <torch/csrc/jit/ir/ir.h>
6
+
7
+ #include <memory>
8
+ #include <vector>
9
+
10
+ namespace torch::jit {
11
+
12
+ using value_list = std::vector<Value*>;
13
+ // clang-format off
14
+ // Example showcasing how Gradient is constructed:
15
+ //
16
+ // Let's assume we have a function f, `m` and `n` do not require grad
17
+ // (`n` can depend only on `m`):
18
+ // y, n = f(x, m)
19
+ //
20
+ // Now, let's assume that the reverse of f (called f') needs to use values of `x`, `t` and `y`.
21
+ // `t` is an intermediate value produced in the body of f, and let's assume that it requires
22
+ // grad too.
23
+ //
24
+ // In this case differentiate(f) will return this:
25
+ // y, n, t = f(x, m) // `t` is appended to the output list
26
+ // dx = f'(dy, dt, x, t, y) // No `dm` or `dn` because they do not require gradient
27
+ // // All needed values from f are prepended to the input list
28
+ //
29
+ // f_real_outputs = 2 // Only first two outputs were present in f originally
30
+ // df_input_vjps = {0, 2} // i.e. connect grad_fn of y and t variables produced by f,
31
+ // y t // with y's output_nr = 0 and t's output_nr = 1
32
+ // df_input_captures = {I0, O2, O0} // Order matches the prefix of inputs to df
33
+ // x t y
34
+ // df_output_vjps = {0} // i.e. connect next_edge[0] of grad_fn to x's (grad_fn, output_nr).
35
+ //
36
+ // Terminology: vjp = vector-jacobian product
37
+ // clang-format on
38
+
39
+ struct Gradient {
40
+ explicit operator bool() const {
41
+ return df != nullptr;
42
+ }
43
+ std::shared_ptr<Graph> f;
44
+ std::shared_ptr<Graph> df;
45
+
46
+ // Describes how to construct outputs of f from what its graph will return.
47
+ // This is necessary because some trailing outputs are intermediates produced
48
+ // only to be saved for df (and should be ignored).
49
+ size_t f_real_outputs = 0; // initialized for safety.
50
+
51
+ // df inputs are split into two sections: vjps (aka grad_outputs) and
52
+ // captures. VJPs are "seeds" for the gradient computation given for each
53
+ // input capture of an Output kind. Captures are values the need to be saved
54
+ // when f is run. We handle inputs specially, because this allows us to avoid
55
+ // adding extra vjps as df inputs.
56
+
57
+ std::vector<size_t> df_input_vjps; // Offsets into f's outputs.
58
+ // capture can come from inputs or outputs
59
+ std::vector<size_t> df_input_captured_inputs; // Offsets into f's inputs
60
+ std::vector<size_t> df_input_captured_outputs; // Offsets into f's outputs
61
+
62
+ // df will produce vjps for a subset of inputs of f that required grad.
63
+ // df_output_vjps[idx] == inp_idx means that idx-th output of df produces a
64
+ // vjp for inp_idx-th input of f.
65
+ std::vector<size_t> df_output_vjps; // Offsets into f's inputs.
66
+
67
+ // How to use gradient to implement a differentiable autograd function:
68
+ // When running f:
69
+ // - Unwrap input Variables
70
+ // - Run f's graph
71
+ // - Create grad_fn
72
+ // - Wrap outputs in Variables (assume we have a tensor_outputs array):
73
+ // outputs = map(Variable, tensor_output)
74
+ // for i, offset in enumerate(df_input_vjps):
75
+ // outputs[offset].set_grad_fn(grad_fn, output_nr=i)
76
+ // - Use df_output_vjps to connect next_edges of grad_fn:
77
+ // for idx in df_output_vjps:
78
+ // grad_fn.add_next_edge(inputs[idx].gradient_edge())
79
+ // - Save captures for df (care needs to be taken to use SavedVariables for
80
+ // inputs and outputs that we will actually return)
81
+ // - Return outputs[:f_real_outputs]
82
+ //
83
+ // When running df:
84
+ // - Concatenate received vjps and captured Variables
85
+ // - Interpret df
86
+ // - Wrap outputs of df into Variables (that don't require grad)
87
+ };
88
+ TORCH_API Gradient differentiate(std::shared_ptr<Graph>& graph);
89
+
90
+ // can we take a derivative of this node symbolically?
91
+ TORCH_API bool isDifferentiable(const Node* n);
92
+ TORCH_API bool isDifferentiable(Graph& g);
93
+ TORCH_API bool isZero(Value* v);
94
+
95
+ } // namespace torch::jit
96
+
97
+ #else
98
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
99
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/calculate_necessary_args.h ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/Export.h>
5
+ #include <torch/csrc/jit/frontend/schema_matching.h>
6
+ #include <cstddef>
7
+
8
+ namespace torch::jit {
9
+
10
+ // Calculates the number of args that need to be passed in.
11
+ // Less args may be needed if defaults are provided.
12
+ // Returns: {number args needed, number of out args}
13
+ inline std::pair<int64_t, int64_t> CalculateNecessaryArgs(
14
+ const std::vector<Argument>& schema_args,
15
+ at::ArrayRef<Value*> actual_inputs,
16
+ bool allow_trailing_out_args) {
17
+ if (schema_args.empty()) {
18
+ return std::make_pair(0, 0);
19
+ }
20
+
21
+ // count number of out arguments
22
+ int64_t schema_idx = static_cast<int64_t>(schema_args.size()) - 1;
23
+ if (allow_trailing_out_args) {
24
+ // skip over out arguments in the end.
25
+ while (schema_idx >= 0) {
26
+ const auto& current_arg = schema_args.at(schema_idx);
27
+ if (!current_arg.is_out()) {
28
+ break;
29
+ }
30
+ schema_idx--;
31
+ }
32
+ }
33
+
34
+ int64_t num_out = static_cast<int64_t>(schema_args.size()) - schema_idx - 1;
35
+
36
+ if (schema_args.size() < actual_inputs.size()) {
37
+ return std::make_pair(actual_inputs.size(), num_out);
38
+ }
39
+
40
+ // if it is the default args, we reset the index to the last element
41
+ if (!allow_trailing_out_args) {
42
+ schema_idx = schema_args.size() - 1;
43
+ }
44
+ // keeps track of trailing unnecessary args
45
+ while (schema_idx >= 0) {
46
+ // this means it is not default argument, so it is necessary
47
+ if (!schema_args.at(schema_idx).default_value().has_value()) {
48
+ return std::make_pair(schema_idx + 1, num_out);
49
+ } else {
50
+ auto schema_value =
51
+ schema_args.at(schema_idx).default_value().value().toIValue();
52
+ // non-const value will become nullptr here, so will be marked necessary
53
+ // non-const would include prim::ListConstruct, prim::DictConstruct as
54
+ // well.
55
+ auto actual_value = toIValue(actual_inputs[schema_idx]);
56
+ if (!actual_value.has_value()) {
57
+ return std::make_pair(schema_idx + 1, num_out);
58
+ }
59
+ // if the IR has same value as default value of the schema,
60
+ // it is not necessary argument.
61
+ if (schema_value != actual_value.value()) {
62
+ return std::make_pair(schema_idx + 1, num_out);
63
+ }
64
+ }
65
+ schema_idx--;
66
+ }
67
+ return std::make_pair(0, num_out);
68
+ }
69
+
70
+ } // namespace torch::jit
71
+
72
+ #else
73
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
74
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/custom_operator.h ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <ATen/core/op_registration/op_registration.h>
5
+ #include <ATen/core/stack.h>
6
+ #include <torch/csrc/jit/runtime/operator.h>
7
+
8
+ namespace torch::jit {
9
+
10
+ /// Registration class for new operators. Effectively calls
11
+ /// `torch::jit::registerOperator` for every supplied operator, but allows doing
12
+ /// so in the global scope when a `RegisterOperators` object is assigned to a
13
+ /// static variable.
14
+ /// Note: This is *not* the custom operator API. If you want to register custom
15
+ /// operators, take a look at torch::RegisterOperators.
16
+ struct TORCH_API RegisterOperators {
17
+ RegisterOperators() = default;
18
+
19
+ /// Registers a vector of already created `Operator`s.
20
+ /// The operator element is now optional to filter null ops. It's backward
21
+ /// compatible and works for selective operator registration.
22
+ explicit RegisterOperators(std::vector<std::optional<Operator>> operators) {
23
+ for (std::optional<Operator>& o : operators) {
24
+ if (o) {
25
+ registerOperator(std::move(o.value()));
26
+ }
27
+ }
28
+ }
29
+ };
30
+
31
+ } // namespace torch::jit
32
+
33
+ #else
34
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
35
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/decomposition_registry.h ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ // This file is temporary until native_functions.yaml and derivatives.yaml are
4
+ // merged. Ideally this should all go into native_functions.yaml
5
+
6
+ #include <torch/csrc/Export.h>
7
+ #include <torch/csrc/jit/ir/ir.h>
8
+
9
+ namespace torch::jit {
10
+
11
+ TORCH_API std::optional<std::shared_ptr<Graph>> GetDecomposition(
12
+ const FunctionSchema& schema);
13
+
14
+ TORCH_API void RegisterDecomposition(
15
+ const FunctionSchema& schema,
16
+ std::shared_ptr<Graph> g);
17
+
18
+ TORCH_API void RunDecompositions(std::shared_ptr<Graph> g);
19
+
20
+ TORCH_API std::optional<GraphFunction*> GetDecompositionFunction(
21
+ const FunctionSchema& schema);
22
+
23
+ // For invocation in C++, recommended is to assign to static local variable
24
+ TORCH_API Function* GetDecompositionExecutor(const char* schema_literal);
25
+
26
+ TORCH_API Function* GetDecompositionExecutor(const FunctionSchema& schema);
27
+
28
+ TORCH_API void run_jit_decomposition(
29
+ const c10::OperatorHandle& op,
30
+ torch::jit::Stack* stack);
31
+
32
+ TORCH_API bool has_jit_decomposition(const FunctionSchema& schema);
33
+
34
+ } // namespace torch::jit
35
+
36
+ #else
37
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
38
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/decomposition_registry_util.h ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/Export.h>
5
+ #include <torch/csrc/jit/ir/ir.h>
6
+
7
+ namespace torch::jit {
8
+
9
+ TORCH_API const std::string& GetSerializedDecompositions();
10
+
11
+ TORCH_API const OperatorMap<std::string>& GetDecompositionMapping();
12
+
13
+ } // namespace torch::jit
14
+
15
+ #else
16
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
17
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/exception_message.h ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <c10/util/Exception.h>
4
+ #include <stdexcept>
5
+
6
+ namespace torch::jit {
7
+
8
+ struct ExceptionMessage {
9
+ ExceptionMessage(const std::exception& e) : e_(e) {}
10
+
11
+ private:
12
+ const std::exception& e_;
13
+ friend std::ostream& operator<<(
14
+ std::ostream& out,
15
+ const ExceptionMessage& msg);
16
+ };
17
+
18
+ inline std::ostream& operator<<(
19
+ std::ostream& out,
20
+ const ExceptionMessage& msg) {
21
+ auto c10_error = dynamic_cast<const c10::Error*>(&msg.e_);
22
+ if (c10_error) {
23
+ out << c10_error->what_without_backtrace();
24
+ } else {
25
+ out << msg.e_.what();
26
+ }
27
+ return out;
28
+ }
29
+
30
+ } // namespace torch::jit
31
+
32
+ #else
33
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
34
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_executor.h ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <atomic>
5
+ #include <memory>
6
+
7
+ #include <torch/csrc/jit/ir/ir.h>
8
+ #include <torch/csrc/jit/python/update_graph_executor_opt.h>
9
+ #include <torch/csrc/jit/runtime/argument_spec.h>
10
+ #include <torch/csrc/jit/runtime/interpreter.h>
11
+ #include <torch/csrc/jit/runtime/variable_tensor_list.h>
12
+
13
+ TORCH_DECLARE_bool(torch_jit_enable_new_executor);
14
+
15
+ TORCH_DECLARE_bool(torch_jit_execution_plan_reuse_code_graph);
16
+
17
+ namespace torch::jit {
18
+ struct GraphExecutorState;
19
+ struct Code;
20
+
21
+ enum ExecutorExecutionMode {
22
+ SIMPLE,
23
+ PROFILING,
24
+ };
25
+
26
+ struct ExecutionPlan {
27
+ ExecutionPlan() = default;
28
+ ExecutionPlan(std::shared_ptr<Graph> graph, std::string function_name)
29
+ : code(graph, std::move(function_name)),
30
+ graph(
31
+ FLAGS_torch_jit_execution_plan_reuse_code_graph
32
+ ? code.graph()
33
+ : std::move(graph)) {}
34
+
35
+ operator bool() const {
36
+ return static_cast<bool>(graph);
37
+ }
38
+
39
+ Code code;
40
+ std::shared_ptr<Graph> graph;
41
+ };
42
+
43
+ // Notice that those structs don't manage lifetime of their members.
44
+ // They are only valid only right after you call getDebugState() and should
45
+ // never be used again once another GraphExecutor function is called.
46
+
47
+ struct GraphExecutorState {
48
+ const Graph* graph = nullptr;
49
+ ExecutionPlan fallback; // XXX: members of this field are optional
50
+ std::unordered_map<ArgumentSpec, ExecutionPlan> execution_plans;
51
+ };
52
+
53
+ struct TORCH_API EnableProfilingGuard {
54
+ EnableProfilingGuard();
55
+ ~EnableProfilingGuard();
56
+
57
+ private:
58
+ bool old_executor_mode = false;
59
+ bool old_get_optimize = false;
60
+ };
61
+
62
+ struct GraphExecutorImplBase;
63
+ struct TORCH_API GraphExecutor {
64
+ GraphExecutor() = default;
65
+ GraphExecutor(const std::shared_ptr<Graph>& graph, std::string function_name);
66
+
67
+ GraphExecutor(
68
+ const std::shared_ptr<Graph>& graph,
69
+ std::string function_name,
70
+ ExecutorExecutionMode executor_mode);
71
+
72
+ void run(Stack& inputs);
73
+ c10::intrusive_ptr<Future> runAsync(
74
+ Stack& stack,
75
+ TaskLauncher taskLauncher = at::launch);
76
+
77
+ // `remaining_bailout_depth` stands for the maximum number of profiled and
78
+ // specialized recompilations allowed for the current `GraphExecutor`. if
79
+ // remaining_bailout_depth is equal to 0, `GraphExecutor` won't perform any
80
+ // profiling and specialization. This is also equivalent to the
81
+ // SIMPLE_EXECUTOR mode. if remaining_bailout_depth is greater than 0,
82
+ // `GraphExecutor` will profile and specialize its input graph based on the
83
+ // profiled information whenever a bailout check is failed/triggered, a new
84
+ // `GraphExecutor` will be created. This new `GraphExecutor`'s
85
+ // remaining_bailout_depth will be reduced by 1.
86
+ // If no bailout depth is passed, the depth will be initialized from the
87
+ // current global fusion strategy settings.
88
+ const ExecutionPlan& getPlanFor(
89
+ Stack& inputs,
90
+ std::optional<size_t> remaining_bailout_depth = std::nullopt);
91
+ // Returns an optimized execution plan without requiring input arguments.
92
+ // Runs input-independent optimization passes (e.g. inlining, constant
93
+ // propagation, peephole, CSE) but skips profiling-based specializations
94
+ // that require runtime type/shape information.
95
+ const ExecutionPlan& getInputIndependentPlan();
96
+ GraphExecutorState getDebugState();
97
+
98
+ void debugFlushCompilationCache();
99
+
100
+ bool isOptimized() const;
101
+
102
+ private:
103
+ std::shared_ptr<GraphExecutorImplBase> pImpl;
104
+ };
105
+
106
+ TORCH_API Node* replaceBlockWithFallbackGraph(
107
+ Block* b,
108
+ ArrayRef<Value*> inputs);
109
+
110
+ // These passes need to run before it is valid to pass to the interpreter
111
+ // regardless of whether sizes have been specialized or not.
112
+ TORCH_API void runRequiredPasses(const std::shared_ptr<Graph>& g);
113
+
114
+ TORCH_API void debugSetFusionGroupInlining(bool state);
115
+ TORCH_API bool getFusionGroupInlining();
116
+
117
+ TORCH_API void debugSetAutodiffSubgraphInlining(bool state);
118
+ TORCH_API std::shared_ptr<Graph> lastExecutedOptimizedGraph();
119
+
120
+ TORCH_API std::atomic<bool>& getProfilingMode();
121
+ TORCH_API std::atomic<bool>& getExecutorMode();
122
+ TORCH_API std::atomic<size_t>& getNumProfiledRuns();
123
+ TORCH_API size_t getBailoutDepth();
124
+ TORCH_API bool IsNewExecutorEnabled();
125
+
126
+ struct TORCH_API GraphOptimizerEnabledGuard {
127
+ GraphOptimizerEnabledGuard(bool state)
128
+ : old_state_(getGraphExecutorOptimize()) {
129
+ setGraphExecutorOptimize(state);
130
+ }
131
+
132
+ ~GraphOptimizerEnabledGuard() {
133
+ setGraphExecutorOptimize(old_state_);
134
+ }
135
+
136
+ bool old_state_;
137
+ };
138
+
139
+ namespace detail {
140
+
141
+ GraphExecutor* getGradExecutor(Operation& op);
142
+
143
+ GraphExecutor* getDifferentiableGraphOpExecutor(Operation& op);
144
+
145
+ // for debugging information we expose a way to get the last actually
146
+ // run graph. Previous approaches allowed querying the GraphExecutor
147
+ // for what graph it would run in certain circumstances (graphFor), but
148
+ // this is fragile because we sometimes change how these decisions are made.
149
+ // This interface still allows our tests to look at optimized graphs, but
150
+ // with less plumbing.
151
+ } // namespace detail
152
+
153
+ } // namespace torch::jit
154
+
155
+ #else
156
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
157
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_executor_impl.h ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <torch/csrc/jit/runtime/graph_executor.h>
4
+
5
+ #include <ATen/core/ivalue.h>
6
+ #include <c10/util/Exception.h>
7
+ #include <torch/csrc/autograd/grad_mode.h>
8
+ #include <torch/csrc/jit/frontend/tracer.h>
9
+ #include <torch/csrc/jit/ir/ir.h>
10
+ #include <torch/csrc/jit/passes/shape_analysis.h>
11
+ #include <torch/csrc/jit/resource_guard.h>
12
+ #include <torch/csrc/jit/runtime/argument_spec.h>
13
+ #include <torch/csrc/jit/runtime/autodiff.h>
14
+ #include <torch/csrc/jit/runtime/custom_operator.h>
15
+ #include <torch/csrc/jit/runtime/interpreter.h>
16
+ #include <torch/csrc/jit/runtime/profiling_record.h>
17
+
18
+ #include <torch/csrc/autograd/edge.h>
19
+ #include <torch/csrc/autograd/function.h>
20
+ #include <torch/csrc/jit/frontend/ir_emitter.h>
21
+ #include <torch/csrc/jit/runtime/logging.h>
22
+
23
+ #include <cstdint>
24
+ #include <iterator>
25
+ #include <memory>
26
+ #include <mutex>
27
+ #include <unordered_map>
28
+ #include <utility>
29
+ #include <vector>
30
+
31
+ namespace torch::jit {
32
+
33
+ void packGradient(const Gradient& gradient, Node* dnode);
34
+ bool needsGradient(const std::shared_ptr<const Graph>& graph);
35
+ void runOptimization(
36
+ std::shared_ptr<Graph>& graph,
37
+ bool unroll_non_constant_loops = true,
38
+ bool const_prop_user_classes = true);
39
+ void runNondiffOptimization(
40
+ std::shared_ptr<Graph>& graph,
41
+ bool strict_fuser_check = false);
42
+ void debugSetAutodiffSubgraphInlining(bool state);
43
+ bool TORCH_API getAutodiffSubgraphInlining();
44
+
45
+ void debugSetFusionGroupInlining(bool state);
46
+ bool getFusionGroupInlining();
47
+
48
+ // Tunable parameters for deciding when to create/keep subgraphs of
49
+ // differentiable code
50
+ const size_t autodiffSubgraphNodeThreshold = 2;
51
+ const size_t autodiffSubgraphInlineThreshold = 5;
52
+
53
+ // a Graph can be created via tracing, or via a language-based frontend
54
+ // GraphExecutor runs it. It can run the same graph on many different sizes
55
+ // and different requires_grad states, and handles specializations for each
56
+ // situation. GraphExecutor is completely unaware of tracing or module
57
+ // parameters to keep the tracing concerns separated.
58
+ struct GraphExecutorImplBase {
59
+ static std::shared_ptr<Graph> prepareGraph(
60
+ const std::shared_ptr<Graph>& graph) {
61
+ auto copy = graph->copy();
62
+ EraseShapeInformation(copy);
63
+ return copy;
64
+ }
65
+
66
+ GraphExecutorImplBase(
67
+ const std::shared_ptr<Graph>& graph,
68
+ std::string function_name)
69
+ : graph(prepareGraph(graph)),
70
+ function_name_(std::move(function_name)),
71
+ num_inputs(this->graph->inputs().size()),
72
+ num_outputs(this->graph->outputs().size()) {}
73
+
74
+ // entry point where execution begins
75
+ void run(Stack& stack);
76
+ c10::intrusive_ptr<Future> runAsync(
77
+ Stack& stack,
78
+ TaskLauncher taskLauncher = at::launch);
79
+
80
+ virtual const ExecutionPlan& getPlanFor(
81
+ Stack& stack,
82
+ std::optional<size_t> remaining_bailout_depth = std::nullopt) = 0;
83
+ // Returns an optimized execution plan without requiring input arguments.
84
+ // Runs input-independent optimization passes (e.g. inlining, constant
85
+ // propagation, peephole, CSE) but skips profiling-based specializations
86
+ // that require runtime type/shape information.
87
+ virtual const ExecutionPlan& getInputIndependentPlan() = 0;
88
+ virtual GraphExecutorState getDebugState() = 0;
89
+ virtual ~GraphExecutorImplBase() = default;
90
+
91
+ virtual bool isOptimized() const {
92
+ return false;
93
+ }
94
+
95
+ protected:
96
+ friend struct GraphExecutor;
97
+
98
+ // The unoptimized starting graph. This field is effectively const, but we
99
+ // can't make it so because Graph::copy() is not const (and making it const is
100
+ // not that easy at this point).
101
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
102
+ std::shared_ptr<Graph> graph;
103
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
104
+ std::string function_name_;
105
+
106
+ // If false, we'll run the graph as we get it, without any optimizations.
107
+ // Useful for debugging.
108
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
109
+ const size_t num_inputs;
110
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
111
+ const size_t num_outputs;
112
+
113
+ // GraphExecutors can be accessed from multiple threads, so this thread needs
114
+ // to be held every time we access the fallback or plan_cache.
115
+ // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
116
+ std::mutex compile_mutex;
117
+ };
118
+
119
+ } // namespace torch::jit
120
+
121
+ #else
122
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
123
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_iterator.h ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #include <torch/csrc/jit/ir/ir.h>
3
+
4
+ namespace torch::jit {
5
+
6
+ // This class facilitates depth-first iteration over all nodes in a graph.
7
+ class DepthFirstGraphNodeIterator {
8
+ Node* current_;
9
+
10
+ public:
11
+ // Constructor.
12
+ explicit DepthFirstGraphNodeIterator(std::shared_ptr<Graph>& graph)
13
+ : current_(*(graph->block()->nodes().begin())) {}
14
+
15
+ // Moves up and to the next node (may move up recursively).
16
+ void move_up() {
17
+ if (current_ == nullptr) {
18
+ return;
19
+ }
20
+ // Basically we start from the child block (which is current_)
21
+ // and we try to find the block that owns it. Now we need to check
22
+ // if that block is the graph root block, or if it is an If/Loop/etc
23
+ // block.
24
+ //
25
+ // If it's the graph root block we can stop because there is no "up"
26
+ // but if it is a node (e.g. If/Loop/etc) we need to apply logic
27
+ // based on where we are coming from to move to the next block.
28
+ // This might mean that we need to traverse up again (e.g. if we've
29
+ // reached the end of the else clause in an if block we need to go)
30
+ // up to the parent block that contains the if.
31
+ //
32
+ // Similarly if we've reached the end of the parent block containing
33
+ // the else clause we might need to go up again so this is a recursive
34
+ // function.
35
+ //
36
+ // BlockNode (if/loop/with)
37
+ // |
38
+ // [Block1] ... [Block2]
39
+ // |
40
+ // [ Node1, Node2, Node3, FromNode]
41
+ //
42
+ auto parent_block = current_->owningBlock();
43
+ TORCH_INTERNAL_ASSERT(parent_block, "Every node must be owned by a block");
44
+
45
+ // Get the node that owns the parent block. This node has to be an if,
46
+ // loop, or with.
47
+ auto parent_node = parent_block->owningNode();
48
+ if (parent_node == nullptr) {
49
+ // If there's no node that owns this current block then we're at the
50
+ // top of the graph and since we're trying to move up we have reached
51
+ // the end of the traversal.
52
+ current_ = nullptr;
53
+ return;
54
+ }
55
+
56
+ // Check the type of node this root is.
57
+ if (parent_node->kind() == prim::If) {
58
+ // Need to check if we came from the `then` branch or the `else` branch.
59
+ auto* then_block = parent_node->blocks().at(0);
60
+ auto* else_block = parent_node->blocks().at(1);
61
+
62
+ if (parent_block == else_block) {
63
+ // If else block then we move to the next node in the parent block.
64
+ current_ = parent_node->next();
65
+ if (current_->kind() == prim::Return) {
66
+ move_up();
67
+ }
68
+ } else {
69
+ // If then block then move to the else block if it is not empty.
70
+ TORCH_INTERNAL_ASSERT(parent_block == then_block);
71
+ bool else_block_empty =
72
+ else_block->nodes().begin() == else_block->nodes().end();
73
+
74
+ if (!else_block_empty) {
75
+ current_ = *(else_block->nodes().begin());
76
+ } else {
77
+ // Since it's empty we move to the next node.
78
+ current_ = parent_node->next();
79
+ if (current_->kind() == prim::Return) {
80
+ move_up();
81
+ }
82
+ }
83
+ }
84
+ } else if (
85
+ parent_node->kind() == prim::Loop ||
86
+ parent_node->kind() == prim::With) {
87
+ current_ = parent_node->next();
88
+ if (current_->kind() == prim::Return) {
89
+ move_up();
90
+ }
91
+ } else {
92
+ TORCH_INTERNAL_ASSERT(
93
+ false, "Only if/loop/with nodes should have child blocks");
94
+ }
95
+ }
96
+
97
+ // Moves to the next adjacent node or up in to the parent if that is not
98
+ // possible.
99
+ void move_next() {
100
+ if (current_ == nullptr) {
101
+ return;
102
+ }
103
+
104
+ // Increment to the next node in the current block.
105
+ current_ = current_->next();
106
+
107
+ // Check if we're at the end of the block. If so we need
108
+ // to move upwards (if it makes sense to).
109
+ if (current_->kind() == prim::Return) {
110
+ move_up();
111
+ }
112
+ }
113
+
114
+ // Moves to the next node in the graph into children if it can.
115
+ void move_into() {
116
+ if (current_ == nullptr) {
117
+ return;
118
+ }
119
+
120
+ // Check if we're currently on a node that contains sub-nodes.
121
+ if (current_->kind() == prim::If || current_->kind() == prim::Loop ||
122
+ current_->kind() == prim::With) {
123
+ auto* first_block = current_->blocks().at(0);
124
+ current_ = first_block->param_node();
125
+ // Move next will move up and out of the current node if the block is
126
+ // empty. `move_up` which is called by `move_next` will handle the
127
+ // difference between If, Loop, and With blocks appropriately.
128
+ move_next();
129
+ } else {
130
+ move_next();
131
+ }
132
+ }
133
+
134
+ // Get the next Node in the graph. \returns nullptr if there are no nodes
135
+ // left.
136
+ Node* next() {
137
+ auto result = current_;
138
+
139
+ // Try move into the existing node to set the next node to be returned.
140
+ // This will move to the next node if not possible, or move upwards and
141
+ // to the next.
142
+ move_into();
143
+
144
+ return result;
145
+ }
146
+ };
147
+
148
+ } // namespace torch::jit
149
+
150
+ #else
151
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
152
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/instruction.h ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <cstdint>
5
+ #include <typeinfo>
6
+ #include <unordered_set>
7
+
8
+ namespace torch::jit {
9
+ // instruction look like:
10
+ // op_code X, N
11
+ // meaning of X, N depend on the op:
12
+ // O - index into operator table
13
+ // R - index into register table
14
+ // I - literal integer
15
+ // C - index into constant table
16
+ // P - jump offset relative to beginning of current instruction
17
+ // F - index into function table
18
+ // T - index into the type table, used for guard instructions
19
+ // S - index into object slots
20
+ // C - index into code table
21
+
22
+ #define FORALL_OPCODES(_) \
23
+ _(OP, "O") /* invoke operator X */ \
24
+ _(OPN, "OI") /* invoke vararg operator X with N arguments */ \
25
+ _(LOAD, "R") /* push a value from a register X */ \
26
+ _(MOVE, "R") /* push a value from register X, clearing the register */ \
27
+ _(STOREN, "RI") /* store N values to registers [X, X+N) */ \
28
+ _(STORE, "R") /* store 1 value to registers X */ \
29
+ _(DROP, "") /* drop 1 value from the top of the stack */ \
30
+ _(DROPR, "R") /* clear register X */ \
31
+ _(LOADC, "C") /* push the constant X */ \
32
+ _(JF, "P") /* pop the top of the stack, if false, branch to P */ \
33
+ _(JMP, "P") /* unconditional branch to X */ \
34
+ _(LOOP, "PI") /* perform a loop, X is where to branch if cond is false */ \
35
+ _(RET, "") /* exit execution */ \
36
+ _(WAIT, "") /* wait for a future to be complete */ \
37
+ _(CALL, "F") /* call function X */ \
38
+ _(GUARD, "T") /* check a guard against type_table, true if passes */ \
39
+ _(TYPECHECK, "TN") /* check each type of input[i] against type_table[X+N] */ \
40
+ _(FAIL_GUARD, "T") /* fail a guard, patch back to GUARD */ \
41
+ _(PROFILE_OP, "F") /* get a callback from profile_function_table at X */ \
42
+ _(TAIL_CALL, "F") /* replace current frame with function F */ \
43
+ _(INTERFACE_CALL, "CI") /* call method X on the first argument (of N) */ \
44
+ _(GET_ATTR, "S") /* get attribute from slot X in an Object */ \
45
+ _(SET_ATTR, "S") /* set attribute to slot X in an Object */ \
46
+ _(LIST_UNPACK, "I") /* unpack list expecting length I */ \
47
+ _(TUPLE_CONSTRUCT, "I") /* construct a tuple using X inputs */ \
48
+ _(NAMED_TUPLE_CONSTRUCT, \
49
+ "TI") /* construct a tuple of type X, using N inputs */ \
50
+ _(LIST_CONSTRUCT, "TI") /* construct a list of type X, using N inputs */ \
51
+ _(DICT_CONSTRUCT, "TI") /* construct a dict of type X, using N inputs */ \
52
+ _(CREATE_OBJECT, "T") /* create an object of type X */ \
53
+ _(ISINSTANCE, "TI") /* check object is one of types[X:X+N] */ \
54
+ _(TUPLE_SLICE, "II") /* slice tup[X:(X+N)] */ \
55
+ _(TUPLE_INDEX, "") /* get the value from a tuple at that index */ \
56
+ _(RAISE_EXCEPTION, "") /* throws the exception from Python */ \
57
+ _(DICT_INDEX, "") /* gets the value from the dict for given key */ \
58
+ _(UNCHECKED_CAST, "") /* perform an unchecked cast operation */ \
59
+ _(__IS__, "") /* performs `is` operator from Python */ \
60
+ _(UN_INITIALIZED, \
61
+ "") /* sets default values to variables that are uninitialized */ \
62
+ _(__ISNOT__, "") /* performs `is not` operator from Python */ \
63
+ _(FORMAT, "I") /* performs string format function `f strings` or `{}.format` \
64
+ the number of inputs in stored in X */ \
65
+ _(DEVICE, "") /* invokes aten::device for a Tensor */ \
66
+ _(DTYPE, "") /* invokes aten::dtype for a Tensor */ \
67
+ _(DIM, "") /* invokes aten::dim for a Tensor */ \
68
+ _(__NOT__, "") /* performs `not` operator from Python */ \
69
+ _(TO_LIST, "") /* convert the input to a list */ \
70
+ _(NUM_TO_TENSOR, \
71
+ "") /* performs the conversion of a number/scalar to Tensor */ \
72
+ _(IS_CUDA, "") /* invokes aten::is_cuda for a Tensor */ \
73
+ _(FORK, "CN") /* launch a thread to run code entry x with N inputs */ \
74
+ _(WARN, "I") /* emit a warning with line information */ \
75
+ _(ENTER, "EN") /* enter scope of a contextmanager */ \
76
+ _(EXIT, "EX") /* exit the last entered contextmanager */ \
77
+ _(AWAITABLE, "CN") /* initialize await for code entry x with N inputs */
78
+
79
+ enum OpCode : uint8_t {
80
+ #define DEFINE_OP(op, _) op,
81
+ FORALL_OPCODES(DEFINE_OP)
82
+ #undef DEFINE_OP
83
+ };
84
+
85
+ struct Instruction {
86
+ OpCode op;
87
+ uint8_t unused{0};
88
+ uint16_t N;
89
+ int32_t X;
90
+ // TODO: check for overflow
91
+ Instruction(OpCode op, int32_t X, uint16_t N) : op(op), N(N), X(X) {}
92
+ };
93
+ std::ostream& operator<<(std::ostream& out, Instruction inst);
94
+
95
+ bool isOpSupportedInMobile(OpCode op);
96
+ char const* toString(OpCode op);
97
+ OpCode parseOpCode(const char* str);
98
+
99
+ } // namespace torch::jit
100
+
101
+ #else
102
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
103
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter.h ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <memory>
4
+ #include <optional>
5
+ #include <vector>
6
+
7
+ #include <ATen/ThreadLocalState.h>
8
+ #include <ATen/core/ivalue.h>
9
+ #include <ATen/core/jit_type.h>
10
+ #include <torch/csrc/Export.h>
11
+ #include <torch/csrc/jit/frontend/source_range.h>
12
+
13
+ TORCH_DECLARE_bool(torch_jit_disable_warning_prints);
14
+ TORCH_DECLARE_bool(torch_jit_enable_rethrow_caught_exception);
15
+
16
+ namespace at {
17
+ class Tensor;
18
+ TORCH_API void launch(std::function<void()> func);
19
+ } // namespace at
20
+ namespace c10 {
21
+ struct IValue;
22
+ struct OperatorName;
23
+ } // namespace c10
24
+
25
+ namespace torch::jit {
26
+
27
+ // The interpreter run Graphs with Tensor inputs and Tensor outputs
28
+ // a separate component in the autograd handles unwrapping and wrapping
29
+ // variable objects for use in the interpreter.
30
+ namespace interpreter {
31
+ struct CodeImpl;
32
+ }
33
+
34
+ struct Node;
35
+ struct GraphExecutor;
36
+ struct InterpreterStateImpl;
37
+ struct Graph;
38
+ struct Node;
39
+ struct Instruction;
40
+ using Stack = std::vector<c10::IValue>;
41
+ using c10::ivalue::Future;
42
+ using TaskLauncher = std::function<void(std::function<void()>)>;
43
+
44
+ bool TORCH_API in_torchscript_runtime();
45
+
46
+ struct TORCH_API Code {
47
+ Code() = default;
48
+ explicit Code(interpreter::CodeImpl* pImpl);
49
+ // remaining_bailout_depth is irrelevant in a `Code` object unless the `Code`
50
+ // is directly created by `GraphExecutor` in which case it's likely to contain
51
+ // `prim::BailOut`s to control the maximum depth of bailout chains
52
+ explicit Code(
53
+ const std::shared_ptr<Graph>& graph,
54
+ std::string function_name,
55
+ size_t remaining_bailout_depth = 0);
56
+
57
+ const std::vector<GraphExecutor*>& grad_executors();
58
+ const std::vector<GraphExecutor*>& diff_graph_op_executors();
59
+
60
+ explicit operator bool() const {
61
+ return pImpl != nullptr;
62
+ }
63
+ size_t num_inputs() const;
64
+ size_t num_outputs() const;
65
+ size_t num_bailouts() const;
66
+ const std::vector<c10::IValue>& constant_table() const;
67
+ const std::vector<c10::TypePtr>& type_table() const;
68
+ const std::vector<Instruction>& instructions() const;
69
+ const std::unordered_map<std::string, size_t>& op_to_num_specified_args()
70
+ const;
71
+ const std::vector<Node*>& instructions_source() const;
72
+ void request_bailout(size_t index);
73
+ size_t register_size() const;
74
+ std::shared_ptr<Graph> graph() const;
75
+
76
+ private:
77
+ std::shared_ptr<interpreter::CodeImpl> pImpl;
78
+ friend struct InterpreterStateImpl;
79
+ friend std::ostream& operator<<(std::ostream& out, const Code& code);
80
+ };
81
+
82
+ struct TORCH_API MobileCode : Code {
83
+ explicit MobileCode(
84
+ const std::shared_ptr<Graph>& graph,
85
+ std::string function_name,
86
+ bool emit_default_input_instructions = true,
87
+ bool support_default_args_before_out = true,
88
+ bool emit_promoted_ops = true,
89
+ size_t remaining_bailout_depth = 0);
90
+ };
91
+
92
+ struct InterpreterState {
93
+ TORCH_API InterpreterState(
94
+ const Code& code,
95
+ TaskLauncher taskLauncher = at::launch);
96
+ TORCH_API void run(Stack& stack);
97
+ TORCH_API c10::intrusive_ptr<Future> runAsync(Stack& stack);
98
+ c10::intrusive_ptr<Future> getFuture();
99
+
100
+ private:
101
+ InterpreterState(c10::intrusive_ptr<c10::intrusive_ptr_target> pImpl);
102
+ // Ideally we should use c10::intrusive_ptr<InterpreterStateImpl> for pImpl;
103
+ // but intrusive_ptr requires full definition of InterpreterStateImpl,
104
+ // which we need to hide in the header.
105
+ c10::intrusive_ptr<c10::intrusive_ptr_target> pImpl;
106
+ friend struct InterpreterStateImpl;
107
+ };
108
+
109
+ // Created by wait()
110
+ struct Suspend : public std::exception {
111
+ const char* what() const noexcept override {
112
+ return "Suspend";
113
+ }
114
+
115
+ explicit Suspend(c10::intrusive_ptr<Future> future_)
116
+ : future(std::move(future_)) {}
117
+
118
+ c10::intrusive_ptr<Future> future;
119
+ };
120
+
121
+ // InterpreterContinuation propagates dist_autograd_context_id
122
+ // through (and only through) the forward pass manually, other
123
+ // thread local settings are propagated with ThreadLocalState
124
+ struct InterpreterContinuation {
125
+ InterpreterContinuation(
126
+ InterpreterState state_,
127
+ Stack stack_,
128
+ int64_t dist_autograd_context_id = 0,
129
+ std::optional<at::ThreadLocalState> tls_state = std::nullopt)
130
+ : state(std::move(state_)),
131
+ stack(std::move(stack_)),
132
+ tls_state_(std::move(tls_state))
133
+ #ifdef USE_DISTRIBUTED
134
+ ,
135
+ dist_autograd_context_id_(dist_autograd_context_id)
136
+ #endif
137
+ {
138
+ }
139
+
140
+ void operator()();
141
+
142
+ private:
143
+ InterpreterState state;
144
+ Stack stack;
145
+ std::optional<at::ThreadLocalState> tls_state_ = std::nullopt;
146
+ #ifdef USE_DISTRIBUTED
147
+ int64_t dist_autograd_context_id_;
148
+ #endif
149
+ };
150
+
151
+ // what is the tensors type, including state from the current execution context
152
+ // that modifies how the tensor behaves. For instance if no_grad is enabled
153
+ // this will cause the TensorType to have requires_grad=False.
154
+ TORCH_API at::TensorTypePtr tensorTypeInCurrentExecutionContext(
155
+ const at::Tensor& t);
156
+
157
+ // current (TLS) TorchScript interpreter callstack
158
+ TORCH_API std::vector<StackEntry> currentCallstack();
159
+ TORCH_API std::vector<std::string> currentModuleHierarchy();
160
+
161
+ } // namespace torch::jit
162
+
163
+ #else
164
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
165
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/can_emit_inline.h ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <memory>
5
+
6
+ #include <torch/csrc/jit/ir/ir.h>
7
+
8
+ namespace torch::jit::interpreter {
9
+ /*
10
+ This is an optimization that reduces the number of store/load/move nodes needed
11
+ by recognizing that parts of the graph are simple trees like a*x + b*y. When
12
+ this happens it is possible to work directly off of the stack by emitting the
13
+ tree in a depth-first left-to-right manner:
14
+ load a
15
+ load x
16
+ mul # stack now is a*x
17
+ load b
18
+ load y
19
+ mul # stack now is a*x, b*y
20
+ add
21
+
22
+ can_emit_inline_[node] == true means that this node participates as a non-root
23
+ member of one of these trees. The code emitter will not emit this node when
24
+ it is encountered in the node. Instead the node is emitted in a depth first
25
+ traversal from where it is used in a tree.
26
+
27
+ To participate in a tree a node must have a single use (otherwise it is not
28
+ tree-like) and output a single value (for simplicity.) If our IR was functional,
29
+ these would be the only constraints. However, many nodes have side effects, so
30
+ we must ensure that emitting the nodes in depth first order from the tree's root
31
+ _does not reorder the emission of the nodes_. To ensure this, we work backward
32
+ from the root of a potential tree, visiting its inputs in reverse depth first
33
+ order, while scanning the node list backward (with the block_point node). When
34
+ these traversal line up we know it is safe to emit the tree in this way. We
35
+ ignore constant nodes, which do not have side effects.
36
+ */
37
+ struct CanEmitInline {
38
+ explicit CanEmitInline(Graph& graph) {
39
+ scanBlock(graph.block());
40
+ }
41
+ bool canInline(Value* v) {
42
+ return v->node()->kind() != prim::Param &&
43
+ // without this a BailOut may float downstream past some later
44
+ // BailOut
45
+ // and receive a higher jf_index. Then a GUARD instruction
46
+ // we generated for the floated BailOut will get popped up from the
47
+ // instruction stack
48
+ // by the later BailOut in createBailoutBlock and its jf_index
49
+ // will become invalid.
50
+ v->node()->kind() != prim::TensorExprGroup &&
51
+ v->node()->kind() != prim::TensorExprDynamicGroup &&
52
+ v->node()->kind() != prim::StaticSubgraph &&
53
+ v->node()->kind() != prim::CudaFusionGroup &&
54
+ v->node()->kind() != prim::FusionGroup &&
55
+ v->node()->kind() != prim::BailOut && v->uses().size() == 1 &&
56
+ v->node()->outputs().size() == 1;
57
+ }
58
+
59
+ Node* previousNonConstant(Node* n) {
60
+ do {
61
+ n = n->prev();
62
+ } while (n->kind() == prim::Constant);
63
+ return n;
64
+ }
65
+
66
+ Node* scanValue(Node* block_point, Value* v) {
67
+ // this node is a candidate for inline, if our reverse scan of the
68
+ // node list lines up with the use of v, we know it will be emitted in
69
+ // tree order, and we can inlining. Scan continues for further nodes.
70
+ if (v->node() == block_point && canInline(v)) {
71
+ // since we inlined this node, we may be able to recursively inline
72
+ // its inputs, so we continue scanning it
73
+ block_point = scanNode(v->node());
74
+ can_emit_inline_[v->node()] = true;
75
+ }
76
+ // if it does not line up, we can't inline 'v', and will just generate
77
+ // a load/move for it. However, other inputs may still appear in tree
78
+ // order so we continue the scan of the inputs.
79
+ return block_point;
80
+ }
81
+
82
+ Node* scanNode(Node* n) {
83
+ // don't bother to scan nodes we have already determined to be inline
84
+ if (can_emit_inline_.count(n)) {
85
+ return nullptr;
86
+ }
87
+ for (auto b : n->blocks()) {
88
+ scanBlock(b);
89
+ }
90
+ Node* block_point = previousNonConstant(n);
91
+ for (auto it = n->inputs().rbegin(), end = n->inputs().rend(); it != end;
92
+ ++it) {
93
+ block_point = scanValue(block_point, *it);
94
+ }
95
+ return block_point;
96
+ }
97
+
98
+ void scanBlock(Block* b) {
99
+ scanNode(b->return_node());
100
+ for (auto node : b->nodes().reverse()) {
101
+ scanNode(node);
102
+ }
103
+ }
104
+ std::unordered_map<Node*, bool> can_emit_inline_;
105
+ };
106
+
107
+ } // namespace torch::jit::interpreter
108
+
109
+ #else
110
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
111
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/code_impl.h ADDED
@@ -0,0 +1,1066 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <memory>
5
+ #include <unordered_map>
6
+ #include <utility>
7
+ #include <vector>
8
+
9
+ #include <c10/util/irange.h>
10
+ #include <torch/csrc/jit/api/function_impl.h>
11
+ #include <torch/csrc/jit/ir/ir.h>
12
+ #include <torch/csrc/jit/jit_log.h>
13
+ #include <torch/csrc/jit/passes/bailout_graph.h>
14
+ #include <torch/csrc/jit/runtime/calculate_necessary_args.h>
15
+ #include <torch/csrc/jit/runtime/graph_iterator.h>
16
+ #include <torch/csrc/jit/runtime/instruction.h>
17
+ #include <torch/csrc/jit/runtime/interpreter/preprocess_graph.h>
18
+
19
+ TORCH_DECLARE_bool(torch_jit_enable_expanded_stacks);
20
+ TORCH_DECLARE_bool(torch_jit_expanded_stacks_mangled);
21
+
22
+ namespace torch::jit::interpreter {
23
+
24
+ template <class Ttarget, class Tsource>
25
+ Ttarget safe_narrow_cast(Tsource v) {
26
+ Ttarget res = static_cast<Ttarget>(v);
27
+ // Casting it back to check whether it overflew.
28
+ if (static_cast<Tsource>(res) != v) {
29
+ TORCH_WARN(
30
+ "ATTENTION: your model computation is overflowing, safe_narrow_cast<>() failed");
31
+ return v;
32
+ }
33
+ return res;
34
+ }
35
+
36
+ // BailoutBlocks are used to temporarily store
37
+ // instructions (typically, argument LOADs and TAIL_CALL)
38
+ // generated for prim::BailOut nodes
39
+ // before they are merged back into
40
+ // CodeImpl._instructions_ by insertBailoutBlocks
41
+ struct BailoutBlock {
42
+ size_t jf_instruction_index; // this node gets patched to jump here on failure
43
+ std::vector<Instruction> instructions; // ends in a TAIL_CALL
44
+
45
+ explicit BailoutBlock(size_t jf_index) : jf_instruction_index(jf_index) {}
46
+ };
47
+
48
+ // for keeping track of the current node
49
+ struct WithCurrentNode {
50
+ WithCurrentNode(Node** loc, Node* new_value) : loc_(loc), old_value_(*loc_) {
51
+ *loc = new_value;
52
+ }
53
+ ~WithCurrentNode() {
54
+ *loc_ = old_value_;
55
+ }
56
+
57
+ private:
58
+ Node** loc_;
59
+ Node* old_value_;
60
+ };
61
+
62
+ struct NodeSourceInfo {
63
+ const char* func_name_{nullptr};
64
+ const char* file_name_{nullptr};
65
+ size_t line_{0};
66
+ NodeSourceInfo() = default;
67
+ };
68
+
69
+ struct CodeImpl {
70
+ friend struct InterpreterState;
71
+ std::vector<Instruction> instructions_;
72
+
73
+ const c10::unique_t node_stack_attr_symbol_ =
74
+ static_cast<c10::unique_t>(attr::node_stack_idx);
75
+ // Expanded inlined stacks as pointers to values in inlined call stack.
76
+ std::vector<std::vector<NodeSourceInfo>> expanded_node_stacks_;
77
+
78
+ // same length as instructions.
79
+ // what node in the graph cause this
80
+ // instruction to be emitted?
81
+ std::vector<Node*> instructions_source_;
82
+ std::vector<IValue> constant_table_;
83
+ std::vector<Operation> operator_table_;
84
+ #ifndef NDEBUG
85
+ std::vector<Operator> full_operator_table_;
86
+ #endif
87
+ // map<(op name, num inputs), index in operator table>, to avoid duplicates,
88
+ // not including vararg operators
89
+ std::unordered_map<
90
+ std::pair<std::string, int>,
91
+ int,
92
+ std::function<size_t(const std::pair<std::string, int>& p)>>
93
+ operator_table_inv_;
94
+ std::vector<Function*> function_table_;
95
+ std::vector<std::unique_ptr<GraphFunction>> forked_functions_;
96
+ std::vector<std::unique_ptr<GraphFunction>> awaited_functions_;
97
+ std::vector<TypePtr> type_table_;
98
+ std::vector<std::function<void(std::vector<IValue>&)>>
99
+ profile_function_table_;
100
+
101
+ int register_size_ = 0;
102
+ size_t n_outputs;
103
+ size_t n_inputs;
104
+ TypePtr return_type_;
105
+ std::string function_name_;
106
+
107
+ // We MUST hold onto graph here because some Operators stored in the
108
+ // instruction lists have dependencies on meta-data stored in the graph
109
+ // that would be dead otherwise.
110
+ // It is also very useful for debugging interpreter problems to
111
+ // keep this around.
112
+ std::shared_ptr<Graph> graph_;
113
+ std::optional<std::vector<GraphExecutor*>> grad_executors_;
114
+ std::optional<std::vector<GraphExecutor*>> forward_executors_;
115
+ PreprocessGraph preprocess_;
116
+
117
+ // map from unique of nodes to register in register table
118
+ std::unordered_map<Value*, int> value_to_reg_;
119
+
120
+ // map from operator name to specified arguments
121
+ // Example: for a schema of aten::foo.str
122
+ // aten::foo.str(arg0: str="default", arg1: int=0,
123
+ // arg2: bool=False, arg3: float=0.0)
124
+ // If the usages in a graph is:
125
+ // aten::foo("somestr", arg1=0, arg2=True, arg3=0.0)
126
+ // aten::foo("somestr", arg1=1, arg2=False, arg3=0.0)
127
+ // op_to_num_specified_args_["aten::foo.str"] = 3
128
+ // This is because for all usages, at most 3 args are used.
129
+ std::unordered_map<std::string, size_t> op_to_num_specified_args_;
130
+
131
+ std::unordered_map<std::string, size_t> op_to_num_out_args_;
132
+
133
+ // running count of uses as we emit. When we reach use_count_[v] =
134
+ // v.uses().size() we know it is the final use and we can move rather than
135
+ // load.
136
+ std::unordered_map<Value*, size_t> use_count_;
137
+
138
+ Node* current_node_; // used in creation of code to keep track
139
+ // of node being emitted
140
+ Node* last_inserted_op_ = nullptr;
141
+
142
+ // out-of-line jumps for bailouts that are patched in at the end
143
+ std::vector<BailoutBlock> bailout_blocks_;
144
+ std::vector<std::unique_ptr<Function>> bailout_functions_;
145
+ size_t remaining_bailout_depth_;
146
+
147
+ CodeImpl(
148
+ const std::shared_ptr<Graph>& graph,
149
+ std::string function_name,
150
+ size_t remaining_bailout_depth,
151
+ bool emit_instructions = true)
152
+ : operator_table_inv_(
153
+ 0,
154
+ [](const std::pair<std::string, int>& p) {
155
+ return std::hash<std::string>()(p.first) ^
156
+ std::hash<int>()(p.second);
157
+ }),
158
+ function_name_(std::move(function_name)),
159
+ preprocess_(*graph),
160
+ current_node_(preprocess_.graph->return_node()),
161
+ remaining_bailout_depth_(remaining_bailout_depth) {
162
+ graph_ = preprocess_.graph;
163
+ n_outputs = graph_->outputs().size();
164
+ if (n_outputs == 1) {
165
+ return_type_ = graph->outputs().at(0)->type();
166
+ } else {
167
+ return_type_ = TupleType::create(
168
+ fmap(graph->outputs(), [](const Value* v) { return v->type(); }));
169
+ }
170
+ n_inputs = graph_->inputs().size();
171
+ if (emit_instructions) {
172
+ // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.VirtualCall)
173
+ run();
174
+ }
175
+ }
176
+
177
+ virtual ~CodeImpl() = default;
178
+
179
+ // since subclass of CodeImpl needs to populate
180
+ // op_to_num_specified_args, we separate the calls
181
+ // that changes internals of CodeImpl into a separate
182
+ // function.
183
+ virtual void run() {
184
+ emitCodeForBlock(graph_->block());
185
+ insertInstruction(RET);
186
+ // we deferred the emission of bailout blocks so they appear at the end
187
+ // emit them now and patch up the jumps
188
+ insertBailoutBlocks();
189
+ }
190
+
191
+ const std::vector<c10::IValue>& constant_table() const {
192
+ return constant_table_;
193
+ }
194
+
195
+ void request_bailout(size_t index) {
196
+ auto count = index;
197
+ for (const auto instr_index : c10::irange(instructions_.size())) {
198
+ if (instructions_[instr_index].op == GUARD ||
199
+ instructions_[instr_index].op == FAIL_GUARD) {
200
+ if (count-- == 0) {
201
+ // patching GUARD to FAIL_GUARD
202
+ instructions_[instr_index].op = FAIL_GUARD;
203
+ GRAPH_DEBUG(
204
+ "Added a bailout request for ",
205
+ index,
206
+ " at instruction ",
207
+ instr_index);
208
+ break;
209
+ }
210
+ }
211
+ }
212
+ }
213
+
214
+ const std::vector<Instruction>& instructions() const {
215
+ return instructions_;
216
+ }
217
+
218
+ const std::unordered_map<std::string, size_t>& op_to_num_specified_args()
219
+ const {
220
+ return op_to_num_specified_args_;
221
+ }
222
+
223
+ const std::vector<Node*>& instructions_source() const {
224
+ return instructions_source_;
225
+ }
226
+
227
+ NodeSourceInfo getSourceInfoFromSourceRange(const SourceRange& range) {
228
+ NodeSourceInfo nodeSource;
229
+ SourceRange r = range;
230
+ if (!FLAGS_torch_jit_expanded_stacks_mangled && range.source()) {
231
+ if (auto orig = range.source()->findSourceRangeThatGenerated(r)) {
232
+ r = *orig;
233
+ }
234
+ }
235
+ if (r.source()) {
236
+ auto lineno = r.source()->lineno_for_offset(r.start());
237
+ nodeSource.line_ = r.source()->lineno_to_source_lineno(lineno);
238
+ if (r.source()->filename()) {
239
+ nodeSource.file_name_ = r.source()->filename().value().c_str();
240
+ }
241
+ }
242
+ return nodeSource;
243
+ }
244
+
245
+ void expandInlinedNodeStack(
246
+ const InlinedCallStackPtr& cs,
247
+ std::vector<NodeSourceInfo>* expandedstack) {
248
+ auto nodeSourceInfo = getSourceInfoFromSourceRange(cs->source_range());
249
+ nodeSourceInfo.func_name_ = cs->function_name().c_str();
250
+ expandedstack->emplace_back(nodeSourceInfo);
251
+
252
+ if (cs->callee()) {
253
+ expandInlinedNodeStack(cs->callee().value(), expandedstack);
254
+ }
255
+ }
256
+
257
+ void getNodeStack(
258
+ const Node* node,
259
+ std::vector<NodeSourceInfo>* expandedstack) {
260
+ if (current_node_->callstack()) {
261
+ expandInlinedNodeStack(current_node_->callstack().value(), expandedstack);
262
+ }
263
+ auto nodeSourceInfo = getSourceInfoFromSourceRange(node->sourceRange());
264
+ expandedstack->emplace_back(nodeSourceInfo);
265
+ }
266
+
267
+ void insertInstruction(OpCode op, int64_t X = 0, uint64_t N = 0) {
268
+ instructions_.emplace_back(
269
+ op,
270
+ safe_narrow_cast<int32_t, int64_t>(X),
271
+ safe_narrow_cast<uint16_t, uint64_t>(N));
272
+ instructions_source_.emplace_back(current_node_);
273
+
274
+ if (FLAGS_torch_jit_enable_expanded_stacks &&
275
+ !current_node_->hasAttribute(attr::node_stack_idx)) {
276
+ std::vector<NodeSourceInfo> expandedStack;
277
+ getNodeStack(current_node_, &expandedStack);
278
+ auto insertIdx = expanded_node_stacks_.size();
279
+ expanded_node_stacks_.emplace_back(expandedStack);
280
+ current_node_->i_(attr::node_stack_idx, insertIdx);
281
+ }
282
+
283
+ // check that we didn't accidentally emit nodes out of topological order
284
+ if (op == OP) {
285
+ if (last_inserted_op_ != nullptr && current_node_ != last_inserted_op_ &&
286
+ current_node_->owningBlock() == last_inserted_op_->owningBlock()) {
287
+ TORCH_INTERNAL_ASSERT(
288
+ current_node_->isAfter(last_inserted_op_),
289
+ *current_node_,
290
+ " is not after ",
291
+ *last_inserted_op_);
292
+ }
293
+ last_inserted_op_ = current_node_;
294
+ }
295
+ }
296
+
297
+ void truncateInstructions(size_t size) {
298
+ while (instructions_.size() > size) {
299
+ instructions_.pop_back();
300
+ instructions_source_.pop_back();
301
+ }
302
+ }
303
+
304
+ void createBailoutBlock(size_t jf_index) {
305
+ bailout_blocks_.emplace_back(jf_index);
306
+ auto& bailout_instructions = bailout_blocks_.back().instructions;
307
+
308
+ bailout_instructions.insert(
309
+ bailout_instructions.end(),
310
+ instructions_.begin() + jf_index + 1,
311
+ instructions_.end());
312
+ truncateInstructions(jf_index + 1);
313
+ }
314
+
315
+ int allocRegs(at::ArrayRef<Value*> vs) {
316
+ int result = register_size_ + 1;
317
+ for (Value* v : vs) {
318
+ AT_ASSERT(value_to_reg_.count(v) == 0);
319
+ value_to_reg_[v] = ++register_size_;
320
+ }
321
+ return result;
322
+ }
323
+
324
+ int registerFor(Value* v) {
325
+ return value_to_reg_.at(v);
326
+ }
327
+
328
+ void emitUse(Value* input, bool drop) {
329
+ // drop - if true, we are not actually going to use this thing
330
+ // and we can short circuit doing many instructions here
331
+ // by either clearing the register (DROPR) or just popping the stack
332
+ // (DROP)
333
+ if (preprocess_.can_emit_inline[input->node()]) {
334
+ emitNode(input->node());
335
+ if (drop) {
336
+ insertInstruction(DROP);
337
+ }
338
+ } else {
339
+ int reg = registerFor(input);
340
+ bool moved = input->uses().size() == ++use_count_[input];
341
+
342
+ OpCode op{};
343
+ if (input->node()->kind() == prim::Constant) {
344
+ op = LOADC;
345
+ } else if (moved) {
346
+ op = MOVE;
347
+ } else {
348
+ op = LOAD;
349
+ }
350
+
351
+ if (drop) {
352
+ op = DROPR;
353
+ }
354
+ insertInstruction(op, reg);
355
+ }
356
+ }
357
+
358
+ void emitLoadInputs(at::ArrayRef<Value*> inputs) {
359
+ for (Value* input : inputs) {
360
+ emitUse(input, false);
361
+ }
362
+ }
363
+
364
+ void emitLoadInputs(at::ArrayRef<Value*> inputs, int num_include) {
365
+ int count = 0;
366
+ for (Value* input : inputs) {
367
+ if (count < num_include) {
368
+ emitUse(input, false);
369
+ count++;
370
+ }
371
+ }
372
+ }
373
+
374
+ void emitLoadInputs(at::ArrayRef<Value*> inputs, size_t start, size_t end) {
375
+ for (size_t i = start; i < end; i++) {
376
+ emitUse(inputs[i], false);
377
+ }
378
+ }
379
+
380
+ virtual void emitOperator(Node* node) {
381
+ emitLoadInputs(node->inputs());
382
+ const Operator& op = node->getOperator();
383
+ int num_inputs = node->inputs().size();
384
+ bool is_vararg = op.schema().is_vararg();
385
+
386
+ int operation_index = add_to_operator_table(
387
+ op,
388
+ node,
389
+ c10::toString(op.schema().operator_name()),
390
+ num_inputs,
391
+ is_vararg);
392
+
393
+ if (op.hasOperation() && is_vararg) {
394
+ insertInstruction(OPN, operation_index, num_inputs);
395
+ } else {
396
+ insertInstruction(OP, operation_index);
397
+ }
398
+ }
399
+
400
+ void emitWait(Node* node) {
401
+ emitLoadInputs(node->inputs());
402
+ insertInstruction(WAIT);
403
+ }
404
+
405
+ void emitDrop(at::ArrayRef<Value*> to_drop) {
406
+ for (Value* input : to_drop) {
407
+ emitUse(input, true);
408
+ }
409
+ }
410
+
411
+ void emitStoreOutputs(Node* node) {
412
+ size_t N = node->outputs().size();
413
+ if (N == 0) {
414
+ return;
415
+ }
416
+ int regs = allocRegs(node->outputs());
417
+ if (N == 1) {
418
+ insertInstruction(STORE, regs);
419
+ } else {
420
+ insertInstruction(STOREN, regs, node->outputs().size());
421
+ }
422
+ }
423
+
424
+ int insertConstant(IValue value) {
425
+ int result = constant_table_.size();
426
+ constant_table_.emplace_back(std::move(value));
427
+ return result;
428
+ }
429
+
430
+ virtual void emitOperatorOrInstruction(
431
+ Node* node,
432
+ OpCode op,
433
+ int64_t X = 0,
434
+ uint64_t N = 0,
435
+ bool emit_inputs = true) {
436
+ if (emit_inputs) {
437
+ emitLoadInputs(node->inputs());
438
+ }
439
+ insertInstruction(op, X, N);
440
+ }
441
+
442
+ void emitFormat(Node* node) {
443
+ emitOperatorOrInstruction(node, FORMAT, node->inputs().size(), 0);
444
+ }
445
+
446
+ void checkNodeAndEmit(Node* node) {
447
+ // check if the node should be emitted as instruction or operator
448
+ const Operator& op = node->getOperator();
449
+ std::string unique_op_name = c10::toString(op.schema().operator_name());
450
+ if (unique_op_name.find("aten::__getitem__.Dict") == 0) {
451
+ // __get_item__ overloaded operator for Dict
452
+ // needs to be emitted an instruction
453
+ emitOperatorOrInstruction(node, DICT_INDEX);
454
+ } else {
455
+ emitOperator(node);
456
+ }
457
+ }
458
+
459
+ void emitConstant(Node* node) {
460
+ if (node->output()->type()->kind() == FunctionType::Kind) {
461
+ return;
462
+ }
463
+ // constants are just put in the constant table
464
+ value_to_reg_[node->output()] =
465
+ insertConstant(toIValue(node->output()).value());
466
+ }
467
+
468
+ void emitIf(Node* node) {
469
+ emitLoadInputs(node->inputs());
470
+ size_t start_if = instructions_.size();
471
+ insertInstruction(JF, 0); // dummy offset to be filled in
472
+ emitCodeForBlock(node->blocks().at(0));
473
+ insertInstruction(JMP, 0); // dummy offset
474
+ size_t start_else = instructions_.size();
475
+ instructions_[start_if].X = start_else - start_if;
476
+ emitCodeForBlock(node->blocks().at(1));
477
+ instructions_[start_else - 1].X = instructions_.size() - (start_else - 1);
478
+ }
479
+
480
+ void emitLoop(Node* loop) {
481
+ insertInstruction(LOADC, insertConstant(0));
482
+ emitLoadInputs(loop->inputs());
483
+ size_t start = instructions_.size();
484
+ insertInstruction(LOOP, 0, loop->inputs().size()); // dummy offset
485
+ emitCodeForBlock(loop->blocks().at(0));
486
+ insertInstruction(JMP, start - instructions_.size());
487
+ instructions_[start].X = instructions_.size() - start;
488
+ }
489
+
490
+ void emitCall(Function* func, at::ArrayRef<Value*> inputs) {
491
+ emitLoadInputs(inputs);
492
+ insertInstruction(CALL, function_table_.size());
493
+ function_table_.emplace_back(func);
494
+ }
495
+
496
+ void emitNodeAtBlockLevel(Node* node) {
497
+ WithCurrentNode guard(&current_node_, node);
498
+ switch (node->kind()) {
499
+ case prim::Constant:
500
+ emitConstant(node);
501
+ break;
502
+ case prim::Return:
503
+ emitLoadInputs(node->inputs());
504
+ break;
505
+ default:
506
+ if (!preprocess_.can_emit_inline[node]) {
507
+ emitNode(node);
508
+ emitStoreOutputs(node);
509
+ }
510
+ break;
511
+ }
512
+ }
513
+
514
+ size_t emitType(TypePtr t) {
515
+ size_t r = type_table_.size();
516
+ type_table_.emplace_back(std::move(t));
517
+ return r;
518
+ }
519
+
520
+ void emitTypeCheck(Node* node) {
521
+ auto num_inputs = node->inputs().size();
522
+
523
+ // Check that TypeCheck has at least one input.
524
+ TORCH_INTERNAL_ASSERT(
525
+ num_inputs && num_inputs + 1 == node->outputs().size());
526
+ emitLoadInputs(node->inputs());
527
+
528
+ // Emit the expected type.
529
+ size_t types_start = type_table_.size();
530
+ auto types = node->tys(attr::types);
531
+ for (const auto i : c10::irange(num_inputs)) {
532
+ emitType(types[i]);
533
+ }
534
+ insertInstruction(TYPECHECK, types_start, num_inputs);
535
+ }
536
+
537
+ size_t emitGuard(Node* node) {
538
+ // unoptimized graph is at index 0
539
+ // guarded input is at index 1
540
+ // the rest of args follow
541
+ emitLoadInputs(node->inputs().slice(1, 1));
542
+ insertInstruction(GUARD, emitType(node->outputs().at(0)->type()));
543
+ insertInstruction(JF, 0 /* to be patched */);
544
+ return instructions_.size() - 1;
545
+ }
546
+
547
+ void emitBailOut(Node* node) {
548
+ auto jf_index = emitGuard(node);
549
+ auto unoptimized_graph = node->inputs().at(0)->node()->g(attr::Subgraph);
550
+ // note, guaded input is already loaded onto the stack
551
+ // for GUARD instruction
552
+ emitLoadInputs(node->inputs().slice(2));
553
+ insertInstruction(TAIL_CALL, function_table_.size());
554
+ TORCH_INTERNAL_ASSERT(node->kind() == prim::BailOut);
555
+ auto bailout_index = node->i(attr::index);
556
+ TORCH_INTERNAL_ASSERT(bailout_index >= 0);
557
+
558
+ auto build_bailout_graph = [bailout_index,
559
+ unoptimized_graph](GraphFunction& func) {
560
+ BuildBailOutGraphFrom(bailout_index, unoptimized_graph, func.graph());
561
+ };
562
+
563
+ auto empty_graph = std::make_shared<Graph>();
564
+ auto func = std::make_unique<GraphFunction>(
565
+ "bailout", empty_graph, build_bailout_graph);
566
+ function_table_.emplace_back(func.get());
567
+ bailout_functions_.emplace_back(std::move(func));
568
+ createBailoutBlock(jf_index);
569
+ }
570
+
571
+ void emitProfile(Node* node) {
572
+ emitLoadInputs(node->inputs());
573
+ insertInstruction(PROFILE_OP, profile_function_table_.size());
574
+ if (node->cast<ProfileOp>()) {
575
+ profile_function_table_.push_back(node->cast<ProfileOp>()->getCallback());
576
+ } else if (node->cast<ProfileIValueOp>()) {
577
+ profile_function_table_.push_back(
578
+ node->cast<ProfileIValueOp>()->getCallback());
579
+ } else {
580
+ TORCH_INTERNAL_ASSERT(false);
581
+ }
582
+ }
583
+
584
+ void emitGetAttr(Node* node) {
585
+ emitLoadInputs(node->inputs());
586
+ const auto type = node->input()->type()->expect<ClassType>();
587
+ const auto& field = node->s(attr::name);
588
+ const auto slot = type->getAttributeSlot(field);
589
+ insertInstruction(GET_ATTR, slot);
590
+ }
591
+
592
+ void emitSetAttr(Node* node) {
593
+ emitLoadInputs(node->inputs());
594
+ const auto type = node->inputs().at(0)->type()->expect<ClassType>();
595
+ const auto& field = node->s(attr::name);
596
+ const auto slot = type->getAttributeSlot(field);
597
+ insertInstruction(SET_ATTR, slot);
598
+ }
599
+
600
+ void insertBailoutBlocks() {
601
+ for (const BailoutBlock& block : bailout_blocks_) {
602
+ TORCH_INTERNAL_ASSERT(instructions_[block.jf_instruction_index].op == JF)
603
+ instructions_[block.jf_instruction_index].X =
604
+ instructions_.size() - block.jf_instruction_index;
605
+ instructions_.insert(
606
+ instructions_.end(),
607
+ block.instructions.begin(),
608
+ block.instructions.end());
609
+ instructions_source_.insert(
610
+ instructions_source_.end(),
611
+ block.instructions.size(),
612
+ instructions_source_[block.jf_instruction_index]);
613
+ }
614
+ }
615
+ void emitInterfaceCall(
616
+ std::string method_name_str,
617
+ c10::ArrayRef<Value*> inputs) {
618
+ emitLoadInputs(inputs);
619
+ auto method_name = insertConstant(std::move(method_name_str));
620
+ insertInstruction(INTERFACE_CALL, method_name, inputs.size());
621
+ }
622
+
623
+ void emitListUnpack(Node* node) {
624
+ emitLoadInputs(node->inputs());
625
+ insertInstruction(LIST_UNPACK, node->outputs().size());
626
+ }
627
+
628
+ void emitTupleConstruct(Node* node) {
629
+ bool named =
630
+ node->output()->type()->expectRef<TupleType>().name().has_value();
631
+ if (named) {
632
+ emitContainerConstruct(NAMED_TUPLE_CONSTRUCT, node);
633
+ } else {
634
+ emitLoadInputs(node->inputs());
635
+ insertInstruction(TUPLE_CONSTRUCT, node->inputs().size());
636
+ }
637
+ }
638
+
639
+ void emitContainerConstruct(OpCode op, Node* node) {
640
+ emitLoadInputs(node->inputs());
641
+ insertInstruction(
642
+ op, emitType(node->output()->type()), node->inputs().size());
643
+ }
644
+
645
+ void emitCreateObject(Node* node) {
646
+ insertInstruction(CREATE_OBJECT, emitType(node->output()->type()));
647
+ }
648
+ void emitIsinstance(Node* node) {
649
+ emitLoadInputs(node->inputs());
650
+ std::vector<TypePtr> types = node->tys(attr::types);
651
+ size_t types_start = type_table_.size();
652
+ for (const auto& typ : types) {
653
+ emitType(typ);
654
+ }
655
+ insertInstruction(ISINSTANCE, types_start, types.size());
656
+ }
657
+
658
+ void emitTupleSlice(Node* node) {
659
+ emitLoadInputs(node->inputs());
660
+ int64_t beg_ind = node->i(attr::beg);
661
+ int64_t end_ind = node->i(attr::end);
662
+ insertInstruction(TUPLE_SLICE, beg_ind, end_ind - beg_ind);
663
+ }
664
+
665
+ void emitFork(Node* node) {
666
+ emitLoadInputs(node->inputs());
667
+ auto forked_fn = std::make_unique<GraphFunction>(
668
+ "<forked function>", node->g(attr::Subgraph), nullptr);
669
+ forked_functions_.emplace_back(std::move(forked_fn));
670
+ function_table_.emplace_back(forked_functions_.back().get());
671
+ insertInstruction(FORK, function_table_.size() - 1, node->inputs().size());
672
+ }
673
+
674
+ void emitAwaitable(Node* node) {
675
+ emitLoadInputs(node->inputs());
676
+ auto await_fn = std::make_unique<GraphFunction>(
677
+ "<awaitable function>", node->g(attr::Subgraph), nullptr);
678
+ awaited_functions_.emplace_back(std::move(await_fn));
679
+ function_table_.emplace_back(awaited_functions_.back().get());
680
+ insertInstruction(
681
+ AWAITABLE, function_table_.size() - 1, node->inputs().size());
682
+ }
683
+
684
+ void emitWarn(Node* node) {
685
+ if (FLAGS_torch_jit_disable_warning_prints) {
686
+ return;
687
+ }
688
+
689
+ emitLoadInputs(node->inputs());
690
+ int32_t idx = -1;
691
+ if (node->hasAttribute(attr::warn_id)) {
692
+ idx = static_cast<int32_t>(node->i(attr::warn_id));
693
+ }
694
+ insertInstruction(WARN, idx);
695
+ }
696
+
697
+ void emitEnter(Node* node) {
698
+ emitLoadInputs(node->inputs());
699
+ insertInstruction(ENTER);
700
+ }
701
+
702
+ void emitExit(Node* /* node */) {
703
+ insertInstruction(EXIT);
704
+ }
705
+
706
+ void emitNode(Node* node) {
707
+ WithCurrentNode guard(&current_node_, node);
708
+ switch (node->kind()) {
709
+ default:
710
+ // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.VirtualCall)
711
+ checkNodeAndEmit(node);
712
+ // emitOperator(node);
713
+ break;
714
+ case prim::RaiseException:
715
+ emitOperatorOrInstruction(node, RAISE_EXCEPTION);
716
+ break;
717
+ case prim::TupleIndex:
718
+ emitOperatorOrInstruction(node, TUPLE_INDEX);
719
+ break;
720
+ case prim::Drop:
721
+ emitDrop(node->inputs());
722
+ break;
723
+ case prim::Constant:
724
+ emitConstant(node);
725
+ break;
726
+ case prim::If:
727
+ emitIf(node);
728
+ break;
729
+ case prim::Loop:
730
+ emitLoop(node);
731
+ break;
732
+ case aten::wait:
733
+ emitWait(node);
734
+ break;
735
+ case prim::Param:
736
+ break;
737
+ case prim::CallFunction:
738
+ emitCall(
739
+ node->inputs().at(0)->type()->expectRef<FunctionType>().function(),
740
+ node->inputs().slice(1));
741
+ break;
742
+ case prim::CallMethod:
743
+ if (auto class_type = node->inputs().at(0)->type()->cast<ClassType>()) {
744
+ emitCall(&class_type->getMethod(node->s(attr::name)), node->inputs());
745
+ } else {
746
+ emitInterfaceCall(node->s(attr::name), node->inputs());
747
+ }
748
+ break;
749
+ case prim::TypeCheck:
750
+ emitTypeCheck(node);
751
+ break;
752
+ case prim::BailOut:
753
+ emitBailOut(node);
754
+ break;
755
+ case prim::profile_ivalue:
756
+ case prim::profile:
757
+ emitProfile(node);
758
+ break;
759
+ case prim::GetAttr:
760
+ emitGetAttr(node);
761
+ break;
762
+ case prim::SetAttr:
763
+ emitSetAttr(node);
764
+ break;
765
+ case prim::ListUnpack:
766
+ emitListUnpack(node);
767
+ break;
768
+ case prim::TupleConstruct:
769
+ emitTupleConstruct(node);
770
+ break;
771
+ case prim::ListConstruct:
772
+ emitContainerConstruct(LIST_CONSTRUCT, node);
773
+ break;
774
+ case prim::DictConstruct:
775
+ emitContainerConstruct(DICT_CONSTRUCT, node);
776
+ break;
777
+ case prim::CreateObject:
778
+ emitCreateObject(node);
779
+ break;
780
+ case prim::isinstance:
781
+ emitIsinstance(node);
782
+ break;
783
+ case prim::TupleSlice:
784
+ emitTupleSlice(node);
785
+ break;
786
+ case prim::fork:
787
+ emitFork(node);
788
+ break;
789
+ case prim::awaitable:
790
+ emitAwaitable(node);
791
+ break;
792
+ case aten::warn:
793
+ emitWarn(node);
794
+ break;
795
+ case prim::Enter:
796
+ emitEnter(node);
797
+ break;
798
+ case prim::Exit:
799
+ emitExit(node);
800
+ break;
801
+ case prim::Uninitialized:
802
+ emitOperatorOrInstruction(node, UN_INITIALIZED, 0, 0, false);
803
+ break;
804
+ case prim::dtype:
805
+ emitOperatorOrInstruction(node, DTYPE);
806
+ break;
807
+ case prim::device:
808
+ emitOperatorOrInstruction(node, DEVICE);
809
+ break;
810
+ case aten::dim:
811
+ emitOperatorOrInstruction(node, DIM);
812
+ break;
813
+ case prim::is_cuda:
814
+ emitOperatorOrInstruction(node, IS_CUDA);
815
+ break;
816
+ case aten::__not__:
817
+ emitOperatorOrInstruction(node, __NOT__);
818
+ break;
819
+ case aten::format:
820
+ emitFormat(node);
821
+ break;
822
+ case aten::__is__:
823
+ emitOperatorOrInstruction(node, __IS__);
824
+ break;
825
+ case aten::__isnot__:
826
+ emitOperatorOrInstruction(node, __ISNOT__);
827
+ break;
828
+ case prim::NumToTensor:
829
+ emitOperatorOrInstruction(node, NUM_TO_TENSOR);
830
+ break;
831
+ case prim::tolist:
832
+ emitOperatorOrInstruction(node, TO_LIST);
833
+ break;
834
+ }
835
+ }
836
+
837
+ void emitCodeForBlock(Block* block) {
838
+ emitNodeAtBlockLevel(block->param_node());
839
+ for (auto node : block->nodes()) {
840
+ emitNodeAtBlockLevel(node);
841
+ }
842
+ emitNodeAtBlockLevel(block->return_node());
843
+ }
844
+
845
+ const std::vector<GraphExecutor*>& grad_executors() {
846
+ if (!grad_executors_) {
847
+ grad_executors_.emplace();
848
+ for (Operation& op : operator_table_) {
849
+ if (auto executor = detail::getGradExecutor(op)) {
850
+ grad_executors_->push_back(executor);
851
+ }
852
+ }
853
+ }
854
+ return *grad_executors_;
855
+ }
856
+
857
+ const std::vector<GraphExecutor*>& diff_graph_op_executors() {
858
+ if (!forward_executors_) {
859
+ forward_executors_.emplace();
860
+ for (Operation& op : operator_table_) {
861
+ if (auto executor = detail::getDifferentiableGraphOpExecutor(op)) {
862
+ forward_executors_->push_back(executor);
863
+ }
864
+ }
865
+ }
866
+ return *forward_executors_;
867
+ }
868
+
869
+ void dump(std::ostream& out, size_t i) const {
870
+ out << i << ' ' << instructions_[i];
871
+ if (instructions_[i].op == OP || instructions_[i].op == CALL ||
872
+ instructions_[i].op == OPN) {
873
+ out << " # " << *instructions_source_[i];
874
+ } else {
875
+ out << '\n';
876
+ }
877
+ }
878
+
879
+ void dump(std::ostream& out) const {
880
+ out << *graph_ << '\n';
881
+ for (const auto i : c10::irange(instructions_.size())) {
882
+ dump(out, i);
883
+ }
884
+ }
885
+
886
+ /**
887
+ * Add an operation to operator_table_ if not a duplicate and return its index
888
+ */
889
+ int add_to_operator_table(
890
+ const Operator& op,
891
+ const Node* node,
892
+ const std::string& op_name,
893
+ const int num_inputs,
894
+ const bool is_vararg) {
895
+ int size = operator_table_.size();
896
+
897
+ const Operation& oper = op.getOperation(node);
898
+
899
+ if (!is_vararg) {
900
+ std::pair<std::string, int> key(op_name, num_inputs);
901
+ auto found = operator_table_inv_.find(key);
902
+
903
+ if (found != operator_table_inv_.end()) {
904
+ return found->second;
905
+ }
906
+
907
+ operator_table_inv_.emplace(key, size);
908
+ }
909
+
910
+ operator_table_.emplace_back(oper);
911
+ #ifndef NDEBUG
912
+ full_operator_table_.emplace_back(op);
913
+ #endif
914
+ return size;
915
+ }
916
+
917
+ inline void assert_stack_size(
918
+ int32_t instruction_index,
919
+ size_t init_size,
920
+ size_t actual_size) const {
921
+ #ifndef NDEBUG
922
+ const auto& schema = full_operator_table_[instruction_index].schema();
923
+ int64_t expected_size = static_cast<int64_t>(init_size) -
924
+ static_cast<int64_t>(schema.arguments().size()) +
925
+ static_cast<int64_t>(schema.returns().size());
926
+ TORCH_INTERNAL_ASSERT_DEBUG_ONLY(
927
+ static_cast<size_t>(expected_size) == actual_size ||
928
+ schema.is_varret() || schema.is_vararg(),
929
+ "Expected to find ",
930
+ expected_size,
931
+ " values on the stack, but found ",
932
+ actual_size,
933
+ " on the stack after ",
934
+ toString(full_operator_table_[instruction_index].schema()));
935
+ #endif
936
+ }
937
+ };
938
+
939
+ struct MobileCodeImpl : CodeImpl {
940
+ MobileCodeImpl(
941
+ const std::shared_ptr<Graph>& graph,
942
+ std::string function_name,
943
+ bool emit_default_input_instructions,
944
+ bool support_default_args_before_out,
945
+ bool emit_promoted_ops,
946
+ size_t remaining_bailout_depth)
947
+ : CodeImpl(
948
+ graph,
949
+ std::move(function_name),
950
+ remaining_bailout_depth,
951
+ false),
952
+ emit_default_input_instructions_(emit_default_input_instructions),
953
+ support_default_args_before_out_(support_default_args_before_out),
954
+ emit_promoted_ops_(emit_promoted_ops) {
955
+ // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.VirtualCall)
956
+ run();
957
+ }
958
+
959
+ void run() override {
960
+ process_ops_for_mobile();
961
+ emitCodeForBlock(graph_->block());
962
+ insertInstruction(RET);
963
+ // we deferred the emission of bailout blocks so they appear at the end
964
+ // emit them now and patch up the jumps
965
+ insertBailoutBlocks();
966
+ }
967
+
968
+ void process_ops_for_mobile() {
969
+ DepthFirstGraphNodeIterator graph_it(graph_);
970
+ Node* node = graph_it.next();
971
+ while (node) {
972
+ if (node->maybeOperator()) {
973
+ auto op_schema = node->getOperator().schema();
974
+ // skip if schema has vararg
975
+ if (!op_schema.is_vararg()) {
976
+ auto specifiedArgs = CalculateNecessaryArgs(
977
+ op_schema.arguments(),
978
+ node->inputs(),
979
+ support_default_args_before_out_);
980
+
981
+ size_t numInclude = specifiedArgs.first +
982
+ (support_default_args_before_out_ ? specifiedArgs.second : 0);
983
+ auto unique_name = !op_schema.overload_name().empty()
984
+ ? op_schema.name() + "." + op_schema.overload_name()
985
+ : op_schema.name();
986
+ auto it = op_to_num_specified_args_.insert(
987
+ std::pair<std::string, size_t>(unique_name, 0));
988
+ op_to_num_out_args_.insert(std::pair<std::string, size_t>(
989
+ unique_name, specifiedArgs.second));
990
+ auto prev_value = it.first->second;
991
+ it.first->second = std::max(numInclude, prev_value);
992
+ }
993
+ }
994
+ node = graph_it.next();
995
+ }
996
+ }
997
+
998
+ private:
999
+ void emitOperator(Node* node) override {
1000
+ if (emit_default_input_instructions_) {
1001
+ CodeImpl::emitOperator(node);
1002
+ } else {
1003
+ const Operator& op = node->getOperator();
1004
+ std::string unique_op_name = c10::toString(op.schema().operator_name());
1005
+ int num_inputs = node->inputs().size();
1006
+ bool is_vararg = op.schema().is_vararg();
1007
+
1008
+ if (op.hasOperation() && is_vararg) {
1009
+ emitLoadInputs(node->inputs());
1010
+ int operation_index = add_to_operator_table(
1011
+ op,
1012
+ node,
1013
+ unique_op_name,
1014
+ num_inputs,
1015
+ /* is_vararg */ true);
1016
+ insertInstruction(OPN, operation_index, num_inputs);
1017
+ } else {
1018
+ auto num_include = num_inputs;
1019
+ auto it = op_to_num_specified_args_.find(unique_op_name);
1020
+ if (it != op_to_num_specified_args_.end()) {
1021
+ num_include = it->second;
1022
+ }
1023
+ if (support_default_args_before_out_) {
1024
+ auto num_out = op_to_num_out_args_.find(unique_op_name)->second;
1025
+ auto num_specified_before_out = num_include - num_out;
1026
+ emitLoadInputs(node->inputs(), 0, num_specified_before_out);
1027
+ emitLoadInputs(
1028
+ node->inputs(),
1029
+ node->inputs().size() - num_out,
1030
+ node->inputs().size());
1031
+ } else {
1032
+ emitLoadInputs(node->inputs(), num_include);
1033
+ }
1034
+ int operation_index = add_to_operator_table(
1035
+ op, node, unique_op_name, num_inputs, is_vararg);
1036
+ insertInstruction(OP, operation_index);
1037
+ }
1038
+ }
1039
+ }
1040
+
1041
+ void emitOperatorOrInstruction(
1042
+ Node* node,
1043
+ OpCode op,
1044
+ int64_t X = 0,
1045
+ uint64_t N = 0,
1046
+ bool emit_inputs = true) override {
1047
+ if (emit_promoted_ops_) {
1048
+ CodeImpl::emitOperatorOrInstruction(node, op, X, N, emit_inputs);
1049
+ } else {
1050
+ CodeImpl::emitOperator(node);
1051
+ }
1052
+ }
1053
+
1054
+ // To support forward compatibility for bytecode version bump from v5 to v6
1055
+ bool emit_default_input_instructions_;
1056
+ // To support forward compatibility for bytecode version bump from v6 to v7
1057
+ bool support_default_args_before_out_;
1058
+ // To support forward compatibility for bytecode version bump from v7 to v8
1059
+ bool emit_promoted_ops_;
1060
+ };
1061
+
1062
+ } // namespace torch::jit::interpreter
1063
+
1064
+ #else
1065
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
1066
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/frame.h ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <atomic>
5
+ #include <memory>
6
+
7
+ #include <torch/csrc/jit/runtime/interpreter/code_impl.h>
8
+ #include <torch/csrc/jit/runtime/profiling_record.h>
9
+
10
+ namespace torch::jit::interpreter {
11
+
12
+ // A Frame captures function's state
13
+ // (e.g. `pc` and `base_pointer`)
14
+ // Each Frame corresponds to a call to a `Frame::function`
15
+ // which has not yet returned
16
+ // The arguments for `Frame::function`
17
+ // are located at [base_pointer + arg_number]
18
+ struct Frame {
19
+ std::shared_ptr<CodeImpl> function;
20
+ // program counter corresponds to the index
21
+ // of the currently executed instruction
22
+ size_t pc;
23
+ // marks the start index of the frame
24
+ // base_pointer is used by TAIL_CALL
25
+ // to replace the current frame
26
+ // with a frame of a bailout graph
27
+ size_t base_pointer;
28
+
29
+ // unique to every frame with prim::profile across all threads
30
+ std::optional<size_t> id;
31
+
32
+ // RecordFunction object associated with this frame
33
+ std::unique_ptr<at::RecordFunction> record_function;
34
+
35
+ // symbol table for a frame
36
+ ShapeSymbolTable symbols2dims;
37
+
38
+ static size_t genId();
39
+ };
40
+
41
+ } // namespace torch::jit::interpreter
42
+
43
+ #else
44
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
45
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/preprocess_graph.h ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <memory>
5
+ #include <unordered_map>
6
+
7
+ #include <torch/csrc/jit/ir/ir.h>
8
+
9
+ namespace torch::jit::interpreter {
10
+
11
+ // pre-processing that happens once per graph
12
+ struct PreprocessGraph {
13
+ explicit PreprocessGraph(Graph& g);
14
+
15
+ // Outputs of the preprocessing:
16
+ std::shared_ptr<Graph> graph;
17
+ std::unordered_map<Node*, bool> can_emit_inline;
18
+ };
19
+
20
+ } // namespace torch::jit::interpreter
21
+
22
+ #else
23
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
24
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/jit_exception.h ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <stdexcept>
5
+
6
+ #include <torch/csrc/Export.h>
7
+ #include <optional>
8
+ #include <string>
9
+
10
+ namespace torch::jit {
11
+
12
+ struct TORCH_API JITException : public std::runtime_error {
13
+ explicit JITException(
14
+ const std::string& msg,
15
+ std::optional<std::string> python_class_name = std::nullopt,
16
+ std::optional<std::string> original_msg = std::nullopt);
17
+
18
+ std::optional<std::string> getPythonClassName() const {
19
+ return python_class_name_;
20
+ }
21
+
22
+ // the original msg if this is from a python exception. The interpreter has
23
+ // changed the original message by adding "The following operation failed in
24
+ // the TorchScript interpreter." in front of it in the handleError function.
25
+ std::optional<std::string> getOriginalMsg() const {
26
+ return original_msg_;
27
+ }
28
+
29
+ static const std::string& getCaughtOriginalMsg();
30
+ static const std::string& getCaughtPythonClassName();
31
+ static void setCaughtOriginalMsg(const std::string& msg);
32
+ static void setCaughtPythonClassName(const std::string& pythonClassName);
33
+
34
+ private:
35
+ std::optional<std::string> python_class_name_;
36
+ std::optional<std::string> original_msg_;
37
+ };
38
+
39
+ } // namespace torch::jit
40
+
41
+ #else
42
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
43
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/jit_trace.h ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #include <torch/csrc/jit/ir/ir.h>
3
+ #include <memory>
4
+
5
+ namespace torch::jit {
6
+ TORCH_API std::shared_ptr<Graph> TraceGraph(
7
+ const std::shared_ptr<Graph>& graph,
8
+ Stack& stack);
9
+ } // namespace torch::jit
10
+
11
+ #else
12
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
13
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/logging.h ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <chrono>
5
+ #include <mutex>
6
+ #include <string>
7
+ #include <unordered_map>
8
+ #include <vector>
9
+
10
+ #include <torch/csrc/Export.h>
11
+
12
+ namespace torch::jit::logging {
13
+
14
+ class LoggerBase {
15
+ public:
16
+ TORCH_API virtual void addStatValue(
17
+ const std::string& stat_name,
18
+ int64_t val) = 0;
19
+ virtual ~LoggerBase() = default;
20
+ };
21
+
22
+ TORCH_API LoggerBase* getLogger();
23
+ TORCH_API LoggerBase* setLogger(LoggerBase* logger);
24
+
25
+ // No-op logger. This is the default and is meant to incur almost no runtime
26
+ // overhead.
27
+
28
+ class NoopLogger : public LoggerBase {
29
+ public:
30
+ void addStatValue(
31
+ const std::string& stat_name [[maybe_unused]],
32
+ int64_t val [[maybe_unused]]) override {}
33
+ ~NoopLogger() override = default;
34
+ };
35
+
36
+ // Trivial locking logger. Pass in an instance of this to setLogger() to use it.
37
+ // This keeps track of the sum of all statistics.
38
+ //
39
+ // NOTE: this is not written in a scalable way and should probably only be used
40
+ // in the single-threaded case or for testing.
41
+ class TORCH_API LockingLogger : public LoggerBase {
42
+ public:
43
+ void addStatValue(const std::string& stat_name, int64_t val) override;
44
+ virtual int64_t getCounterValue(const std::string& name) const;
45
+ enum class AggregationType { SUM = 0, AVG = 1 };
46
+ void setAggregationType(const std::string& stat_name, AggregationType type);
47
+ ~LockingLogger() override = default;
48
+
49
+ private:
50
+ mutable std::mutex m;
51
+ struct RawCounter {
52
+ RawCounter() = default;
53
+ int64_t sum{0};
54
+ size_t count{0};
55
+ };
56
+ std::unordered_map<std::string, RawCounter> raw_counters;
57
+ std::unordered_map<std::string, AggregationType> agg_types;
58
+ };
59
+
60
+ // Make this struct so the timer internals are opaque to the user.
61
+ struct JITTimePoint {
62
+ std::chrono::time_point<std::chrono::high_resolution_clock> point;
63
+ };
64
+
65
+ TORCH_API JITTimePoint timePoint();
66
+ TORCH_API void recordDurationSince(
67
+ const std::string& name,
68
+ const JITTimePoint& tp);
69
+
70
+ namespace runtime_counters {
71
+ constexpr const char* GRAPH_EXECUTORS_CONSTRUCTED =
72
+ "pytorch_runtime.graph_executors_constructed";
73
+ constexpr const char* GRAPH_EXECUTOR_INVOCATIONS =
74
+ "pytorch_runtime.graph_executor_invocations";
75
+ constexpr const char* EXECUTION_PLAN_CACHE_HIT =
76
+ "pytorch_runtime.execution_plan_cache_hit";
77
+ constexpr const char* EXECUTION_PLAN_CACHE_MISS =
78
+ "pytorch_runtime.execution_plan_cache_miss";
79
+
80
+ inline std::vector<const char*> allRuntimeCounters() {
81
+ return {
82
+ GRAPH_EXECUTORS_CONSTRUCTED,
83
+ GRAPH_EXECUTOR_INVOCATIONS,
84
+ EXECUTION_PLAN_CACHE_HIT,
85
+ EXECUTION_PLAN_CACHE_MISS};
86
+ }
87
+
88
+ } // namespace runtime_counters
89
+
90
+ } // namespace torch::jit::logging
91
+
92
+ #else
93
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
94
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/operator.h ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ // in memory description of all ATen Ops similar to Caffe2 schema
3
+ // once C10 exists this can be removed, or stubbed out, but we need
4
+ // it now to implement correct semantic checking for script
5
+ #pragma once
6
+
7
+ #include <ATen/core/dispatch/Dispatcher.h>
8
+ #include <ATen/core/dispatch/OperatorOptions.h>
9
+ #include <ATen/core/op_registration/op_allowlist.h>
10
+ #include <ATen/core/stack.h>
11
+ #include <c10/util/Exception.h>
12
+ #include <c10/util/overloaded.h>
13
+ #include <torch/csrc/jit/frontend/function_schema_parser.h>
14
+ #include <torch/csrc/jit/runtime/operator_options.h>
15
+ #include <torch/library.h>
16
+
17
+ #include <ATen/core/function_schema.h>
18
+ #include <ATen/core/symbol.h>
19
+
20
+ #include <functional>
21
+ #include <initializer_list>
22
+ #include <memory>
23
+ #include <string>
24
+ #include <unordered_map>
25
+ #include <utility>
26
+ #include <variant>
27
+ #include <vector>
28
+
29
+ namespace torch::jit {
30
+
31
+ struct Node;
32
+ using ::c10::Argument;
33
+ using ::c10::FunctionSchema;
34
+ using ::c10::Symbol;
35
+
36
+ using OperationCreator = Operation (*)(const Node*);
37
+
38
+ namespace {
39
+ const std::array<at::Tag, 1> kJitOnlyOperatorTags = {
40
+ at::Tag::pt2_compliant_tag};
41
+ }
42
+
43
+ /*
44
+ * Note: JIT relies on Operator instances having static lifetime, because
45
+ * it for example stores a non-owning FunctionSchema* pointer in the Node class,
46
+ * which points to the function schema stored in the Operator instance.
47
+ * Also, jit::Operator is meant to store more operator related information like
48
+ * symbolic derivatives, which also requires them to have static lifetime
49
+ * so that changes to symbolic derivatives are remembered.
50
+ *
51
+ * Currently, the JIT operator library contains a jit::Operator instance
52
+ * with a wrapper for each c10 operator. The c10 operator library registers
53
+ * those wrappers using listeners in register_c10_ops.cpp.
54
+ * TODO Instead of doing it this way, we should only have pure-jit ops in
55
+ * the jit library but have the JIT operator lookup look into the c10 library
56
+ * too.
57
+ */
58
+
59
+ // An Operator is a thin wrapper around either a pure JIT operator (e.g. prim
60
+ // ops) or a c10 operator, allowing some common operations and abstracting away
61
+ // the concrete operator nature.
62
+ struct TORCH_API Operator {
63
+ private:
64
+ struct C10Operator final {
65
+ c10::OperatorHandle handle_;
66
+ Operation op_;
67
+ };
68
+ struct UnparsedFunctionSchema final {
69
+ std::string schema_string_;
70
+ mutable std::optional<c10::AliasAnalysisKind> alias_analysis_;
71
+ };
72
+ struct JitOnlyOperator final {
73
+ // The only valid transition for schema_ is from right->left, i.e.
74
+ // when the schema gets parsed.
75
+ mutable std::variant<FunctionSchema, UnparsedFunctionSchema> schema_;
76
+
77
+ std::variant<Operation, OperationCreator> op_;
78
+ };
79
+
80
+ public:
81
+ Operator(c10::OperatorHandle opHandle, Operation operation)
82
+ : op_(C10Operator{std::move(opHandle), std::move(operation)}) {}
83
+
84
+ Operator(
85
+ std::string schema,
86
+ Operation op,
87
+ c10::AliasAnalysisKind alias_analysis)
88
+ : op_(JitOnlyOperator{
89
+ UnparsedFunctionSchema{std::move(schema), alias_analysis},
90
+ Operation(std::move(op))}) {}
91
+
92
+ Operator(
93
+ std::string name,
94
+ std::string overload_name,
95
+ std::vector<Argument> arguments,
96
+ std::vector<Argument> returns,
97
+ Operation op,
98
+ c10::AliasAnalysisKind alias_analysis)
99
+ : op_(JitOnlyOperator{
100
+ FunctionSchema(varArgSchemaWithName(
101
+ std::move(name),
102
+ std::move(overload_name),
103
+ std::move(arguments),
104
+ std::move(returns),
105
+ alias_analysis)),
106
+ std::move(op)}) {}
107
+
108
+ Operator(
109
+ std::string schema,
110
+ OperationCreator op_creator,
111
+ c10::AliasAnalysisKind alias_analysis)
112
+ : op_(JitOnlyOperator{
113
+ UnparsedFunctionSchema{std::move(schema), alias_analysis},
114
+ op_creator}) {}
115
+
116
+ // Helper constructor to register `op` to run
117
+ // run for _every_ IR Node where n.kind() == name, regardless of arguments.
118
+ // This is accomplished by marking the schema varargs and having no required
119
+ // arguments.
120
+ Operator(
121
+ Symbol name,
122
+ OperationCreator op_creator,
123
+ c10::AliasAnalysisKind alias_analysis)
124
+ : op_(JitOnlyOperator{
125
+ FunctionSchema(varArgSchemaWithName(name, alias_analysis)),
126
+ op_creator}) {}
127
+
128
+ Operation getOperation(const Node* node = nullptr) const {
129
+ return std::visit(
130
+ c10::overloaded(
131
+ [](const C10Operator& op) { return op.op_; },
132
+ [node](const JitOnlyOperator& op) {
133
+ return std::visit(
134
+ c10::overloaded(
135
+ [](const Operation& op) { return op; },
136
+ [node](const OperationCreator& op_creator) {
137
+ return op_creator(node);
138
+ }),
139
+ op.op_);
140
+ }),
141
+ op_);
142
+ }
143
+
144
+ Operation getOperationForDispatchKey(c10::DispatchKey dk) const {
145
+ // TODO: some sort of caching mechanism?
146
+ return std::visit(
147
+ c10::overloaded(
148
+ [dk](const C10Operator& op) {
149
+ return Operation([op, dk](Stack& stack) {
150
+ op.handle_.callBoxedForDispatchKey(dk, stack);
151
+ });
152
+ },
153
+ [](const JitOnlyOperator& op) {
154
+ TORCH_CHECK(
155
+ false,
156
+ "calling a JIT operator for dispatch key is not supported");
157
+ return Operation(nullptr);
158
+ }),
159
+ op_);
160
+ }
161
+
162
+ const FunctionSchema& schema() const {
163
+ return std::visit(
164
+ c10::overloaded(
165
+ [](const C10Operator& op) -> const FunctionSchema& {
166
+ return op.handle_.schema();
167
+ },
168
+ [](const JitOnlyOperator& op) -> const FunctionSchema& {
169
+ // we lazily parse schema initialized from strings so that
170
+ // we do less work during static operator registration
171
+ if (op.schema_.index() == 1) {
172
+ auto& unmaterializedSchema =
173
+ std::get<UnparsedFunctionSchema>(op.schema_);
174
+ FunctionSchema schema =
175
+ parseSchema(unmaterializedSchema.schema_string_);
176
+ if (unmaterializedSchema.alias_analysis_.has_value()) {
177
+ // TODO What if it gets set later?
178
+ schema.setAliasAnalysis(
179
+ *unmaterializedSchema.alias_analysis_);
180
+ }
181
+ op.schema_ = std::move(schema);
182
+ }
183
+ return std::get<FunctionSchema>(op.schema_);
184
+ }),
185
+ op_);
186
+ }
187
+
188
+ c10::ArrayRef<at::Tag> getTags() const {
189
+ return std::visit(
190
+ c10::overloaded(
191
+ [](const C10Operator& op) { return op.handle_.getTags(); },
192
+ [](const JitOnlyOperator& op) {
193
+ // JitOnlyOperators don't have an c10::OperatorHandle or a way to
194
+ // specify tags. We're grandfathering them all into
195
+ // pt2_compliant_tag, but for anything else, please just stop
196
+ // using JitOnlyOperator.
197
+ return c10::ArrayRef<at::Tag>(kJitOnlyOperatorTags);
198
+ }),
199
+ op_);
200
+ }
201
+
202
+ bool isC10Op() const {
203
+ return op_.index() == 0;
204
+ }
205
+
206
+ c10::AliasAnalysisKind aliasAnalysisKind() const {
207
+ const FunctionSchema& schemaRef = schema();
208
+ c10::AliasAnalysisKind alias_analysis = schemaRef.aliasAnalysis();
209
+
210
+ TORCH_CHECK(
211
+ alias_analysis == AliasAnalysisKind::FROM_SCHEMA ||
212
+ !schemaRef.hasAnyAliasInfo(),
213
+ "In operator registration: Tried to register operator ",
214
+ schemaRef,
215
+ " with aliasing information in the schema but without AliasAnalysisKind::FROM_SCHEMA.");
216
+ return alias_analysis;
217
+ }
218
+
219
+ bool hasOperation() const {
220
+ return std::visit(
221
+ c10::overloaded(
222
+ [](const C10Operator&) { return true; },
223
+ [](const JitOnlyOperator& op) { return op.op_.index() == 0; }),
224
+ op_);
225
+ }
226
+
227
+ private:
228
+ static FunctionSchema varArgSchemaWithName(
229
+ Symbol name,
230
+ AliasAnalysisKind alias_analysis) {
231
+ auto result = FunctionSchema(
232
+ name,
233
+ "",
234
+ {},
235
+ {},
236
+ /*is_vararg*/ true,
237
+ /*is_varret*/ true);
238
+ result.setAliasAnalysis(alias_analysis);
239
+ return result;
240
+ }
241
+
242
+ static FunctionSchema varArgSchemaWithName(
243
+ std::string name,
244
+ std::string overload_name,
245
+ std::vector<Argument> arguments,
246
+ std::vector<Argument> returns,
247
+ AliasAnalysisKind alias_analysis) {
248
+ auto result = FunctionSchema(
249
+ std::move(name),
250
+ std::move(overload_name),
251
+ std::move(arguments),
252
+ std::move(returns),
253
+ /*is_vararg*/ false,
254
+ /*is_varret*/ false);
255
+ result.setAliasAnalysis(alias_analysis);
256
+ return result;
257
+ }
258
+
259
+ std::variant<C10Operator, JitOnlyOperator> op_;
260
+ };
261
+
262
+ TORCH_API std::string canonicalSchemaString(const FunctionSchema& schema);
263
+
264
+ TORCH_API const std::vector<std::shared_ptr<Operator>> getAllOperators();
265
+ TORCH_API const std::vector<std::shared_ptr<Operator>>& getAllOperatorsFor(
266
+ Symbol name);
267
+ // Returns operators in the order which OpOverloadPacket resolves them.
268
+ TORCH_API std::vector<std::shared_ptr<Operator>> getAllSortedOperatorsFor(
269
+ Symbol name);
270
+
271
+ // given a operator with an overload name, find the specific operator related to
272
+ // it, may return nullptr if no operator exists.
273
+ TORCH_API std::shared_ptr<Operator> findOperatorFor(
274
+ const c10::OperatorName& full_name);
275
+
276
+ TORCH_API std::vector<Symbol> findSimilarOperators(Symbol input_op);
277
+
278
+ TORCH_API void registerOperator(Operator&& op);
279
+ TORCH_API void deregisterOperator(const FunctionSchema& schema);
280
+
281
+ // XXX: this function is meant to be used with string literals only!
282
+ TORCH_API std::shared_ptr<Operator> getOperatorForLiteral(
283
+ const char* signature);
284
+
285
+ // Ensure the thing that registers c10 ops is defined.
286
+ // Otherwise, our registry will not have c10 ops. You can run into this
287
+ // scenario if you're querying registered ops during static init.
288
+ //
289
+ // This fn is defined in register_c10_ops.cpp
290
+ TORCH_API void ensure_c10_registerer_defined();
291
+
292
+ // Used to assert that unschematized operators have an analysis method written
293
+ TORCH_API bool aliasAnalysisHasSpecialCaseFor(c10::Symbol sym);
294
+
295
+ // A factory function to generate an optional operator. It has two
296
+ // instantiations depending on the template bool arg value. The arg can be a
297
+ // compile-time function for the selective op registration based on schema
298
+ // string.
299
+ template <typename Func>
300
+ std::optional<Operator> OperatorGenerator(
301
+ const char* schema_str,
302
+ Func&& op,
303
+ AliasAnalysisKind alias_analysis) {
304
+ return std::optional<Operator>(Operator(
305
+ std::string(schema_str), std::forward<Func>(op), alias_analysis));
306
+ }
307
+
308
+ template <typename Func>
309
+ std::optional<Operator> OperatorGenerator(
310
+ torch::detail::SelectiveStr<true> schema_str,
311
+ Func&& op,
312
+ AliasAnalysisKind alias_analysis) {
313
+ return OperatorGenerator(
314
+ static_cast<const char*>(schema_str),
315
+ std::forward<Func>(op),
316
+ alias_analysis);
317
+ }
318
+
319
+ template <typename Func>
320
+ std::optional<Operator> OperatorGenerator(
321
+ torch::detail::SelectiveStr<false> schema_str,
322
+ Func&& op,
323
+ AliasAnalysisKind alias_analysis) {
324
+ return std::nullopt;
325
+ }
326
+
327
+ template <typename Func>
328
+ std::optional<Operator> OperatorGenerator(
329
+ const std::string name,
330
+ const std::string overload_name,
331
+ const std::vector<c10::Argument> arguments,
332
+ const std::vector<c10::Argument> returns,
333
+ Func&& op,
334
+ AliasAnalysisKind alias_analysis) {
335
+ return std::optional<Operator>(Operator(
336
+ name,
337
+ overload_name,
338
+ arguments,
339
+ returns,
340
+ std::forward<Func>(op),
341
+ alias_analysis));
342
+ }
343
+
344
+ } // namespace torch::jit
345
+
346
+ #else
347
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
348
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/operator_options.h ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <ATen/core/dispatch/OperatorOptions.h>
5
+
6
+ namespace torch::jit {
7
+
8
+ using AliasAnalysisKind = c10::AliasAnalysisKind;
9
+
10
+ } // namespace torch::jit
11
+
12
+ #else
13
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
14
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/print_handler.h ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/Export.h>
5
+
6
+ #include <string>
7
+
8
+ namespace torch::jit {
9
+
10
+ using PrintHandler = void (*)(const std::string&);
11
+
12
+ TORCH_API PrintHandler getDefaultPrintHandler();
13
+ TORCH_API PrintHandler getPrintHandler();
14
+ TORCH_API void setPrintHandler(PrintHandler ph);
15
+
16
+ } // namespace torch::jit
17
+
18
+ #else
19
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
20
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/profiling_graph_executor_impl.h ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <c10/util/Flags.h>
4
+ #include <torch/csrc/jit/api/module.h>
5
+ #include <torch/csrc/jit/runtime/graph_executor_impl.h>
6
+
7
+ TORCH_DECLARE_bool(torch_jit_static_then_dynamic);
8
+
9
+ TORCH_DECLARE_bool(torch_jit_always_dynamic);
10
+
11
+ C10_DECLARE_bool(torch_jit_input_independent_optimization);
12
+ C10_DECLARE_bool(torch_jit_release_profiling_graph_after_optimization);
13
+ C10_DECLARE_int32(torch_jit_release_profiling_graph_delay_in_seconds);
14
+ C10_DECLARE_int64(torch_jit_num_profiled_runs);
15
+ C10_DECLARE_int64(torch_jit_bailout_depth);
16
+
17
+ namespace torch::jit {
18
+
19
+ TORCH_API void runNooptPassPipeline(std::shared_ptr<Graph>& graph);
20
+
21
+ struct TORCH_API ProfilingGraphExecutorImpl : public GraphExecutorImplBase {
22
+ ProfilingGraphExecutorImpl(
23
+ const std::shared_ptr<Graph>& graph,
24
+ std::string function_name);
25
+
26
+ const ExecutionPlan& getPlanFor(
27
+ Stack& stack,
28
+ std::optional<size_t> remaining_bailout_depth) override;
29
+ const ExecutionPlan& getInputIndependentPlan() override;
30
+ GraphExecutorState getDebugState() override;
31
+ ~ProfilingGraphExecutorImpl() override = default;
32
+
33
+ void debugFlushCompilationCache();
34
+
35
+ bool isOptimized() const override {
36
+ return optimized_plan_.has_value();
37
+ }
38
+
39
+ private:
40
+ const ExecutionPlan& getOptimizedPlanFor(
41
+ Stack& stack,
42
+ std::optional<size_t> remaining_bailout_depth);
43
+ // Input-independent optimization, assumes compile_mutex is held.
44
+ const ExecutionPlan& getInputIndependentPlanImpl();
45
+ void runProfilingInsensitiveOptimizations(std::shared_ptr<Graph>& graph);
46
+ void runProfilingOptimizations(
47
+ std::shared_ptr<Graph>& graph,
48
+ size_t remaining_depth);
49
+ void replaceFallbackGraphWithFallbackFunction(Block* b);
50
+ FusionBehavior getCurrentBehavior(size_t remaining_depth);
51
+ size_t getInstantiatedBailoutDepth();
52
+ void runNoGradOptimizations(
53
+ std::shared_ptr<Graph>& graph,
54
+ size_t remaining_bailout_depth);
55
+ void runFinalOptimizations(std::shared_ptr<Graph>& graph);
56
+
57
+ void clearTheGraphCompilationIntermediateGraphs();
58
+
59
+ std::unique_ptr<ProfilingRecord> pr_;
60
+ std::optional<ExecutionPlan>
61
+ profiling_plan_; // plan to run in order to profiling the code
62
+ std::optional<ExecutionPlan> optimized_plan_;
63
+ FusionStrategy fusion_strategy_;
64
+
65
+ // this plan is used if getGraphExecutorOptimize is unset
66
+ std::optional<ExecutionPlan> fallback_plan_;
67
+ // fallback functions are inserted for tensorexpr fusion groups
68
+ // and by specialize_autogradzero. Whenever, at runtime, input
69
+ // tensor don't match profiled properties, fallback functions are called
70
+ // They are the deoptimized version of the logic in fusion groups
71
+ // and/or autograd.
72
+ // The fallback functions are owned by a GraphExecutor instance
73
+ // They only exist in the optimized graph which is a private property
74
+ // of the GraphExecutor and only shared with InterpreterState
75
+ std::vector<std::unique_ptr<Function>> fallback_functions_;
76
+ std::optional<size_t> remaining_bailout_depth_;
77
+ // The time the optimized_plan_ is created.
78
+ int32_t time_optimized_plan_created_ = 0;
79
+ // Has the extra memory used by the graph for profiling is released?
80
+ bool is_graph_extra_memory_released_ = false;
81
+ };
82
+
83
+ } // namespace torch::jit
84
+
85
+ #else
86
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
87
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/profiling_record.h ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <ATen/ATen.h>
5
+ #include <ATen/core/ivalue.h>
6
+ #include <ATen/core/jit_type.h>
7
+ #include <ATen/core/stack.h>
8
+ #include <torch/csrc/Export.h>
9
+ #include <torch/csrc/jit/ir/ir.h>
10
+
11
+ #include <list>
12
+ #include <map>
13
+ #include <unordered_map>
14
+ #include <vector>
15
+
16
+ // We would like to assign each position/axis of a tensor an abstract size
17
+ // * For each `tensor` we have a profiled `Value` of a `TensorType` describing
18
+ // the properties of the `tensor`.
19
+ // * `TensorType` has a property called `symbolic_sizes_` to describe observed
20
+ // `tensor.sizes()`
21
+ // * `symbolic_sizes_` is a vector of abstract sizes (or
22
+ // `std::vector<ShapeSymbol>`) where
23
+ // * `ShapeSymbol`at `symbolic_sizes_[i]` describes the size value
24
+ // (`Dimension`) at `tensor.sizes()[i]`
25
+ // * We may see the same `Dimension` at different positions `i` in
26
+ // `tensor.sizes()` or even in different `tensor`
27
+ // * First, we would like associate the same `ShapeSymbol` to the same
28
+ // `Dimension` across **one** profiling execution or run of a TorchScript
29
+ // function.
30
+ // * The same `ShapeSymbol`s in different positions of `symbolic_shapes_` in
31
+ // possibly different `TensorType`s (i.e. `TensorType`s for different
32
+ // profiled values) form an implicit set. The elements of such a set are
33
+ // called *dimension locations*.
34
+ // * These sets allow us to track how the shapes of input arguments of some
35
+ // operation relate to operation's output shapes as the input and output
36
+ // shapes might share the same `ShapeSymbol`s
37
+ // * For **every** profiling run, we would like to maintain the invariant that
38
+ // *the same `ShapeSymbol` is always associated with the same `Dimension`*.
39
+ // * To maintain this invariant we merge the profiling information from all
40
+ // profiling runs,
41
+ // * For every two runs, we iterate over all `symbic_shapes_` and compare
42
+ // their `ShapeSymbol`s in the same position.
43
+ // * if we observe that for every dimension location that has
44
+ // the`ShapeSymbol S1` in run #1 there is **only one** `ShapeSymbol S2` in
45
+ // the same dimension location in run #2, we conclude that the invariant
46
+ // holds.
47
+ // * However, if we observe some dimension locations in run #2 have
48
+ // `ShapeSymbol S2` and the other ones have `ShapeSymbol S3` we would like
49
+ // to partition the virtual set of dimension locations associated with
50
+ // `ShapeSymbol S1` into two new subsets, so the invariant holds.
51
+ // * The partitioning works by assigning a new symbol to the dimension
52
+ // locations (associated with `ShapeSymbol S1`) that have `ShapeSymbol S2`
53
+ // and another new symbol to the dimension locations that have `ShapeSymbol
54
+ // S3`. In other words,
55
+ // * Subset #1 will consist of the dimension locations that in run #2 have
56
+ // `ShapeSymbol S2` and will have `ShapeSymbol S4` in those dimension
57
+ // locations
58
+ // * Subset #2 will consist of the dimension locations that in run #2 have
59
+ // `ShapeSymbol S4` and will have `ShapeSymbol S5` in those dimension
60
+ // locations
61
+ // * The effective result of merging the profiling information from two runs
62
+ // is new `TensorTypes` whose `symbolic_sizes_` /dimension locations have
63
+ // either `ShapeSymbol S4` or `ShapeSymbol S5`.
64
+ // * Partitioning can be done even before we have seen all the dimension
65
+ // locations associated with `ShapeSymbol S1`
66
+ // * We use `getSymbolInSet` of `ShapeSymbolTable` to remember all
67
+ // `ShapeSymbols` from run #2 we observed in the dimension locations
68
+ // associated with `ShapeSymbol S1` .
69
+ // * For every `ShapeSymbol` from run #2 in the dimension location
70
+ // associated with `ShapeSymbol S1` `getSymbolInSet` returns a symbol
71
+ // that we assign to the dimension location in a new TensorType.
72
+ // * It's important to point out that the same `ShapeSymbol S2` from run
73
+ // #2 in two dimension locations that have different `ShapeSymbol`s in
74
+ // run #1 are different! These dimension locations will belong to
75
+ // different subsets and have different `ShapeSymbol`s after merge.
76
+ // * On the other hand, for the same `ShapeSymbol S2` in two dimension
77
+ // locations that have `ShapeSymbol S1` in run #1`getSymbolInSet` will
78
+ // return the same symbol.
79
+
80
+ namespace torch::jit {
81
+
82
+ using ::c10::TensorTypePtr;
83
+ using Dimension = int64_t;
84
+
85
+ TORCH_API void RegisterProfilingNode(
86
+ const std::function<bool(const Node*)>& /*func*/);
87
+
88
+ struct ProfilingRecord;
89
+
90
+ // `SetPartitioningHelper` is used to maintain the following invariant:
91
+ // For **every** profiling run, *the same `ShapeSymbol` is always associated
92
+ // with the same `Dimension`*.
93
+ // while merging the profiling information from multiple runs.
94
+ struct SetPartitioningHelper {
95
+ std::map<c10::ShapeSymbol, std::map<Dimension, c10::ShapeSymbol>>
96
+ sets2subsets_;
97
+
98
+ // `partitionSetByDimension` partitions a virtual set
99
+ // of dimension locations associated with ShapeSymbol `symbol` into subsets.
100
+ // Partitioning is equivalent to giving (or renaming) a particular
101
+ // dimension location a new `ShapeSymbol`.
102
+ // The same `Dimension` value in different dimension locations
103
+ // that used to have `symbol` will receive the same
104
+ // new `ShapeSymbol`, effectively forming a new set.
105
+ c10::ShapeSymbol partitionSetByDimension(
106
+ Dimension new_size,
107
+ c10::ShapeSymbol symbol) {
108
+ auto& dims2symbols = getSetForSymbol(symbol);
109
+
110
+ if (dims2symbols.count(new_size) == 0) {
111
+ auto new_sym = c10::ShapeSymbol::newSymbol();
112
+ dims2symbols[new_size] = new_sym;
113
+ return new_sym;
114
+ }
115
+
116
+ return dims2symbols[new_size];
117
+ }
118
+
119
+ private:
120
+ std::map<Dimension, c10::ShapeSymbol>& getSetForSymbol(c10::ShapeSymbol s) {
121
+ auto& set = sets2subsets_[s];
122
+ // N.B. adding a mapping { s.static_size(), s }
123
+ // makes sure we preserve the fact that
124
+ // some dimension values remain the same
125
+ // across all profiled runs
126
+ if (s.is_static()) {
127
+ set.insert({s.static_size(), s});
128
+ }
129
+ return set;
130
+ }
131
+ };
132
+
133
+ // ShapeSymbolTable is used by Interpreter
134
+ // to assign dimension values to ShapeSymbols
135
+ // and fail a guard if the same symbol
136
+ // is assigned more than one dimension value.
137
+ struct ShapeSymbolTable {
138
+ // N.B. we treat static symbols as always assigned
139
+ // to themselves
140
+ bool isBound(c10::ShapeSymbol s) {
141
+ if (s.is_static()) {
142
+ return true;
143
+ }
144
+ return data_.count(s) != 0;
145
+ }
146
+
147
+ // N.B. we treat static symbols as always assigned
148
+ // to themselves
149
+ Dimension getValue(c10::ShapeSymbol s) {
150
+ if (s.is_static()) {
151
+ return s.static_size();
152
+ }
153
+ return data_[s];
154
+ }
155
+ void assign(c10::ShapeSymbol s, Dimension v) {
156
+ TORCH_INTERNAL_ASSERT(!s.is_static());
157
+ data_[s] = v;
158
+ }
159
+ std::map<c10::ShapeSymbol, Dimension> data_;
160
+ // Tries to assign dimension values from `new_sizes` to
161
+ // `ShapeSymbol`s `sym_shapes`.
162
+ // Returns `true` if every dimension value from `new_sizes`
163
+ // can be assigned to the corresponding `ShapeSymbol` from
164
+ // `sym_shapes`
165
+ // A dimension value can be assigned to a `ShapeSymbol`
166
+ // * if the symbol isn't assigned yet any dimension value
167
+ // * if the symbol is assigned and its value is equal to
168
+ // the dimension value from `new_sizes`
169
+ bool bindSymbolicShapes(
170
+ at::IntArrayRef new_sizes,
171
+ const c10::SymbolicShape& sym_shapes);
172
+ };
173
+
174
+ struct ProfilingRecord {
175
+ // N.B. ProfilingRecord's copy and move c-tor are disabled, so we won't
176
+ // end up accidentally copying or moving ProfilingRecords whose addresses
177
+ // are captured in callbacks_
178
+ ProfilingRecord(const ProfilingRecord&) = delete;
179
+ ProfilingRecord(ProfilingRecord&&) noexcept = delete;
180
+ TORCH_API static std::unique_ptr<ProfilingRecord> instrumentGraph(
181
+ const std::shared_ptr<Graph>& graph);
182
+ TORCH_API static void removeProfilingNodes(Block* b);
183
+ TORCH_API static void removeProfileCounter(Block* b);
184
+
185
+ std::shared_ptr<Graph> profiled_graph_;
186
+ mutable std::mutex mutex_;
187
+ size_t profiling_count_;
188
+
189
+ bool ready() const;
190
+
191
+ std::shared_ptr<Graph> graph() const {
192
+ return profiled_graph_;
193
+ }
194
+
195
+ TORCH_API ProfileIValueOp* createProfileIValueNode(Value* in_val);
196
+ TORCH_API ProfileIValueOp* createProfileIValueNode(ArrayRef<Value*> inputs);
197
+
198
+ private:
199
+ ProfileOp* createProfileNode(
200
+ const std::function<void(Stack&)>& fp,
201
+ at::ArrayRef<Value*> inputs);
202
+ void instrumentBlock(Block* block);
203
+ void insertShapeProfile(Node* n, size_t offset, const TypePtr& input_type);
204
+ ProfilingRecord(std::shared_ptr<Graph> g);
205
+ };
206
+
207
+ } // namespace torch::jit
208
+
209
+ #else
210
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
211
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/register_ops_utils.h ADDED
@@ -0,0 +1,888 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <ATen/Context.h>
5
+ #include <c10/core/DeviceType.h>
6
+ #include <torch/csrc/autograd/autograd.h>
7
+ #include <torch/csrc/autograd/edge.h>
8
+ #include <torch/csrc/autograd/function.h>
9
+ #include <torch/csrc/autograd/generated/variable_factories.h>
10
+ #include <torch/csrc/autograd/variable.h>
11
+ #include <torch/csrc/jit/api/compilation_unit.h>
12
+ #include <torch/csrc/jit/api/module.h>
13
+ #include <torch/csrc/jit/frontend/error_report.h>
14
+ #include <torch/csrc/jit/ir/ir.h>
15
+ #include <torch/csrc/jit/mobile/register_ops_common_utils.h>
16
+ #include <torch/csrc/jit/runtime/custom_operator.h>
17
+ #include <torch/csrc/jit/runtime/graph_executor.h>
18
+ #include <torch/csrc/jit/runtime/jit_exception.h>
19
+ #include <torch/csrc/jit/runtime/logging.h>
20
+ #include <torch/csrc/jit/runtime/operator.h>
21
+ #include <torch/csrc/jit/runtime/print_handler.h>
22
+ #include <torch/csrc/jit/runtime/profiling_record.h>
23
+ #include <torch/csrc/jit/runtime/vararg_functions.h>
24
+ #include <torch/csrc/jit/serialization/pickle.h>
25
+
26
+ #include <ATen/ExpandUtils.h>
27
+ #include <ATen/Parallel.h>
28
+ #include <ATen/WrapDimUtils.h>
29
+ #include <ATen/core/Dict.h>
30
+ #include <ATen/core/Generator.h>
31
+ #include <ATen/core/ivalue.h>
32
+ #include <c10/core/Device.h>
33
+ #include <c10/core/thread_pool.h>
34
+ #include <c10/util/SmallVector.h>
35
+ #include <c10/util/irange.h>
36
+
37
+ namespace torch::jit {
38
+ constexpr inline c10::AliasAnalysisKind aliasAnalysisFromSchema() {
39
+ return c10::AliasAnalysisKind::FROM_SCHEMA;
40
+ }
41
+
42
+ constexpr inline c10::AliasAnalysisKind aliasAnalysisConservative() {
43
+ return c10::AliasAnalysisKind::CONSERVATIVE;
44
+ }
45
+
46
+ constexpr inline c10::AliasAnalysisKind aliasAnalysisSpecialCase() {
47
+ return c10::AliasAnalysisKind::INTERNAL_SPECIAL_CASE;
48
+ }
49
+
50
+ template <class T>
51
+ c10::List<T> make_result_list(const TypePtr& elemType) {
52
+ return c10::List<T>();
53
+ }
54
+
55
+ template <>
56
+ c10::impl::GenericList make_result_list<IValue>(const TypePtr& elemType);
57
+
58
+ // As described in https://docs.python.org/3/library/functions.html#round
59
+ // When a number is exactly halfway between two integers, python builtin round
60
+ // function will round to even number. We use round(x/2)*2 to handle the
61
+ // special halfway case. For positive 'x', round(x/2)*2 =
62
+ // round((x_e + x_r)/2)*2 = x_e + round(x_r/2)*2, where x_e is an even integer,
63
+ // x_r is either 0.5 of 1.5, round(x_r/2)*2 results a 0 or 2, so the final
64
+ // result will always be a even number. Due to symmetricity, it also applies to
65
+ // negative cases.
66
+ inline double round_to_even(double a) {
67
+ return a - std::floor(a) == 0.5 ? (std::round(a * 0.5) * 2.0) : std::round(a);
68
+ }
69
+
70
+ // using the rules from python_arg_parser FunctionParameter::check
71
+ // tensor cannot have grad set, tensor must be 0 dim,
72
+ // and if the dest is an int the source must be integral type
73
+ void checkImplicitTensorToNum(const at::Tensor& t, bool toInt);
74
+
75
+ [[maybe_unused]] static int64_t floordiv(int64_t a, int64_t b) {
76
+ if (b == 0) {
77
+ throw std::runtime_error("division by 0");
78
+ }
79
+ if ((a > 0) == (b > 0)) {
80
+ // simple case, both have same sign
81
+ return a / b;
82
+ } else {
83
+ // in python division rounds down, it doesn't not truncate like in c++
84
+ auto r = lldiv(a, b);
85
+ return (r.rem) ? r.quot - 1 : r.quot;
86
+ }
87
+ }
88
+ TORCH_API void checkDoubleInRange(double a);
89
+ [[maybe_unused]] static int64_t floor(double a) {
90
+ checkDoubleInRange(a);
91
+ return std::floor(a);
92
+ }
93
+ [[maybe_unused]] static int64_t ceil(double a) {
94
+ checkDoubleInRange(a);
95
+ return std::ceil(a);
96
+ }
97
+
98
+ [[maybe_unused]] static int64_t gcd(int64_t a, int64_t b) {
99
+ while (b != 0) {
100
+ int64_t r = a % b;
101
+ a = b;
102
+ b = r;
103
+ }
104
+ // in python gcd returns non-negative values
105
+ return std::abs(a);
106
+ }
107
+
108
+ int64_t partProduct(int n, int m);
109
+
110
+ void loop(int n, int64_t& p, int64_t& r);
111
+
112
+ int nminussumofbits(int v);
113
+
114
+ int64_t factorial(int n);
115
+ static const double degToRad = std::acos(-1.0) / 180.0;
116
+ static const double radToDeg = 180.0 / std::acos(-1.0);
117
+ double degrees(double x);
118
+ double radians(double x);
119
+
120
+ // Convert an python index (which may be negative) into an index usable for a
121
+ // C++ container
122
+
123
+ // Equivalent to list.at(idx)
124
+ template <typename T>
125
+ auto getItem(const c10::List<T>& list, int64_t idx) {
126
+ const int64_t list_size = list.size();
127
+ const int64_t normalized_idx = normalizeIndex(idx, list_size);
128
+ if (normalized_idx < 0 || normalized_idx >= list_size) {
129
+ throw std::out_of_range("list index out of range");
130
+ }
131
+ return list.get(normalized_idx);
132
+ }
133
+
134
+ template <typename T>
135
+ void setItem(const c10::List<T>& list, int64_t idx, T&& value) {
136
+ const int64_t list_size = list.size();
137
+ const int64_t normalized_idx = normalizeIndex(idx, list_size);
138
+ if (normalized_idx < 0 || normalized_idx >= list_size) {
139
+ throw std::out_of_range("list index out of range");
140
+ }
141
+ list.set(normalized_idx, std::forward<T>(value));
142
+ }
143
+
144
+ void listAppend(Stack& stack);
145
+
146
+ void listReverse(Stack& stack);
147
+
148
+ template <typename T>
149
+ void minList(Stack& stack) {
150
+ c10::List<T> a = pop(stack).to<c10::List<T>>();
151
+ c10::List<T> b = pop(stack).to<c10::List<T>>();
152
+
153
+ size_t min_size = std::min(a.size(), b.size());
154
+ for (const auto i : c10::irange(min_size)) {
155
+ if (a[i] == b[i]) {
156
+ continue;
157
+ }
158
+
159
+ push(stack, a[i] < b[i] ? a : b);
160
+ return;
161
+ }
162
+
163
+ push(stack, b.size() < a.size() ? b : a);
164
+ }
165
+
166
+ template <typename T>
167
+ void maxList(Stack& stack) {
168
+ c10::List<T> a = pop(stack).to<c10::List<T>>();
169
+ c10::List<T> b = pop(stack).to<c10::List<T>>();
170
+
171
+ size_t min_size = std::min(a.size(), b.size());
172
+ for (const auto i : c10::irange(min_size)) {
173
+ if (a[i] == b[i]) {
174
+ continue;
175
+ }
176
+
177
+ push(stack, a[i] > b[i] ? a : b);
178
+ return;
179
+ }
180
+
181
+ push(stack, b.size() > a.size() ? b : a);
182
+ }
183
+
184
+ void listPopImpl(Stack& stack, const char* empty_message);
185
+
186
+ void listPop(Stack& stack);
187
+
188
+ void listClear(Stack& stack);
189
+
190
+ void listDelete(Stack& stack);
191
+
192
+ void listInsert(Stack& stack);
193
+
194
+ template <typename T>
195
+ void listRemove(Stack& stack) {
196
+ T elem = pop(stack).to<T>();
197
+ c10::List<T> list = pop(stack).to<c10::List<T>>();
198
+
199
+ auto pos = std::find(list.begin(), list.end(), elem);
200
+
201
+ if (pos != list.end()) {
202
+ list.erase(pos);
203
+ } else {
204
+ TORCH_CHECK(false, "list.remove(x): x not in list");
205
+ }
206
+ }
207
+
208
+ template <typename T>
209
+ void listMin(Stack& stack) {
210
+ c10::List<T> list = pop(stack).to<c10::List<T>>();
211
+ size_t list_size = list.size();
212
+ if (list_size == 0) {
213
+ throw std::runtime_error("min() arg is an empty sequence");
214
+ }
215
+
216
+ T min_elem = list[0];
217
+ for (const auto i : c10::irange(1, list_size)) {
218
+ T elem = list[i];
219
+ min_elem = elem < min_elem ? elem : min_elem;
220
+ }
221
+
222
+ stack.push_back(min_elem);
223
+ }
224
+
225
+ template <typename T>
226
+ void listMax(Stack& stack) {
227
+ c10::List<T> list = pop(stack).to<c10::List<T>>();
228
+ size_t list_size = list.size();
229
+ if (list_size == 0) {
230
+ throw std::runtime_error("max() arg is an empty sequence");
231
+ }
232
+
233
+ T max_elem = list[0];
234
+ for (const auto i : c10::irange(1, list_size)) {
235
+ T elem = list[i];
236
+ max_elem = elem > max_elem ? elem : max_elem;
237
+ }
238
+
239
+ stack.push_back(max_elem);
240
+ }
241
+
242
+ template <>
243
+ void listRemove<at::Tensor>(Stack& stack);
244
+
245
+ template <typename T>
246
+ void listIndex(Stack& stack) {
247
+ T elem = pop(stack).to<T>();
248
+ c10::List<T> list = pop(stack).to<c10::List<T>>();
249
+
250
+ auto pos = std::find(list.begin(), list.end(), elem);
251
+
252
+ if (pos != list.end()) {
253
+ push(stack, static_cast<int64_t>(std::distance(list.begin(), pos)));
254
+ } else {
255
+ TORCH_CHECK(false, "'", elem, "' is not in list");
256
+ }
257
+ }
258
+
259
+ template <>
260
+ void listIndex<at::Tensor>(Stack& stack);
261
+
262
+ template <typename T>
263
+ void listCount(Stack& stack) {
264
+ T elem = pop(stack).to<T>();
265
+ c10::List<T> list = pop(stack).to<c10::List<T>>();
266
+
267
+ const int64_t count = std::count(list.begin(), list.end(), elem);
268
+ push(stack, count);
269
+ }
270
+
271
+ template <>
272
+ void listCount<at::Tensor>(Stack& stack);
273
+
274
+ void listExtend(Stack& stack);
275
+
276
+ void listCopy(Stack& stack);
277
+
278
+ void listSelect(Stack& stack);
279
+
280
+ void listLen(Stack& stack);
281
+
282
+ template <typename T>
283
+ void listEq(Stack& stack) {
284
+ c10::List<T> b = pop(stack).to<c10::List<T>>();
285
+ c10::List<T> a = pop(stack).to<c10::List<T>>();
286
+ push(stack, a == b);
287
+ }
288
+
289
+ template <typename T>
290
+ void listNe(Stack& stack) {
291
+ c10::List<T> b = pop(stack).to<c10::List<T>>();
292
+ c10::List<T> a = pop(stack).to<c10::List<T>>();
293
+ push(stack, a != b);
294
+ }
295
+
296
+ inline bool tensor_list_equal(
297
+ const c10::List<at::Tensor>& a,
298
+ const c10::List<at::Tensor>& b) {
299
+ if (a.size() != b.size()) {
300
+ return false;
301
+ }
302
+
303
+ for (const auto i : c10::irange(a.size())) {
304
+ const at::Tensor& a_element = a[i];
305
+ const at::Tensor& b_element = b[i];
306
+ // This preserves Python's semantics, which uses eq() to compare two
307
+ // elements, then passes the result to bool().
308
+ // see: https://docs.python.org/3.4/reference/datamodel.html#object.__ge__
309
+ const auto cmp_result = a_element.eq(b_element);
310
+ if (!at::native::is_nonzero(cmp_result)) {
311
+ return false;
312
+ }
313
+ }
314
+
315
+ return true;
316
+ }
317
+
318
+ // Specialization for at::Tensor, since it doesn't define operator==
319
+ template <>
320
+ void listEq<at::Tensor>(Stack& stack);
321
+
322
+ // Specialization for at::Tensor, since it doesn't define operator==
323
+ template <>
324
+ void listNe<at::Tensor>(Stack& stack);
325
+
326
+ void listList(Stack& stack);
327
+
328
+ template <typename T>
329
+ void listContains(Stack& stack) {
330
+ auto key = pop(stack).to<T>();
331
+ auto list = pop(stack).to<c10::List<T>>();
332
+ // NOLINTNEXTLINE(performance-implicit-conversion-in-loop)
333
+ for (const T& item : list) {
334
+ if (item == key) {
335
+ push(stack, true);
336
+ return;
337
+ }
338
+ }
339
+ push(stack, false);
340
+ }
341
+
342
+ void listAdd(Stack& stack);
343
+
344
+ void listInplaceAdd(Stack& stack);
345
+
346
+ void listMulIntLeftInPlace(Stack& stack);
347
+
348
+ void listMulIntLeft(Stack& stack);
349
+
350
+ void listMulIntRight(Stack& stack);
351
+
352
+ void listSlice(Stack& stack);
353
+
354
+ template <typename T>
355
+ void listSort(Stack& stack) {
356
+ bool reverse = pop(stack).toBool();
357
+ c10::List<T> list = pop(stack).to<c10::List<T>>();
358
+ std::sort(list.begin(), list.end(), [reverse](const T& a, const T& b) {
359
+ // FBCode errors without this check - "strict weak ordering"
360
+ // TODO: remove when possible, since it just slows down
361
+ // sorting and doesn't do anything useful
362
+ if (a == b) {
363
+ return false;
364
+ }
365
+ return (a < b) != reverse;
366
+ });
367
+ }
368
+
369
+ // Specialization for at::Tensor
370
+ template <>
371
+ void listSort<at::Tensor>(Stack& stack);
372
+
373
+ template <typename T>
374
+ void listCopyAndSort(Stack& stack) {
375
+ c10::List<T> list = pop(stack).to<c10::List<T>>();
376
+ auto list_copied = list.copy();
377
+ std::sort(list_copied.begin(), list_copied.end(), [](const T& a, const T& b) {
378
+ // "strict weak ordering" issue - see other sort
379
+ if (a == b) {
380
+ return false;
381
+ }
382
+ return a < b;
383
+ });
384
+ push(stack, list_copied);
385
+ }
386
+
387
+ // Specialization for at::Tensor
388
+ template <>
389
+ void listCopyAndSort<at::Tensor>(Stack& stack);
390
+
391
+ void listSetItem(Stack& stack);
392
+
393
+ struct OperatorGeneratorArgs {
394
+ const char* schema_str;
395
+ bool isOperationCreator;
396
+ union {
397
+ void (*operation)(Stack&);
398
+ OperationCreator operationCreator;
399
+ };
400
+ AliasAnalysisKind aliasAnalysis;
401
+
402
+ explicit constexpr OperatorGeneratorArgs(
403
+ torch::detail::SelectiveStr<true> schema_str,
404
+ void (*op)(Stack&),
405
+ AliasAnalysisKind aa)
406
+ : schema_str(schema_str),
407
+ isOperationCreator(false),
408
+ operation(op),
409
+ aliasAnalysis(aa) {}
410
+
411
+ explicit constexpr OperatorGeneratorArgs(
412
+ torch::detail::SelectiveStr<true> schema_str,
413
+ OperationCreator opCreator,
414
+ AliasAnalysisKind aa)
415
+ : schema_str(schema_str),
416
+ isOperationCreator(true),
417
+ operationCreator(opCreator),
418
+ aliasAnalysis(aa) {}
419
+
420
+ template <typename... Args>
421
+ explicit constexpr OperatorGeneratorArgs(
422
+ torch::detail::SelectiveStr<false> /*unused*/,
423
+ Args... /*unused*/)
424
+ : schema_str(nullptr),
425
+ isOperationCreator(false),
426
+ operation(nullptr),
427
+ aliasAnalysis(AliasAnalysisKind::INTERNAL_SPECIAL_CASE) {}
428
+ };
429
+
430
+ #define DEFINE_GENERIC_BINARY_OP( \
431
+ aten_op, op, int_float_result, complex_result) \
432
+ OperatorGeneratorArgs( \
433
+ TORCH_SELECTIVE_SCHEMA(#aten_op \
434
+ ".int_int(int a, int b) -> " #int_float_result), \
435
+ [](Stack& stack) { \
436
+ int64_t a, b; \
437
+ pop(stack, a, b); \
438
+ push(stack, op); \
439
+ }, \
440
+ aliasAnalysisFromSchema()), \
441
+ OperatorGeneratorArgs( \
442
+ TORCH_SELECTIVE_SCHEMA( \
443
+ #aten_op \
444
+ ".float_float(float a, float b) -> " #int_float_result), \
445
+ [](Stack& stack) { \
446
+ double a, b; \
447
+ pop(stack, a, b); \
448
+ push(stack, op); \
449
+ }, \
450
+ aliasAnalysisFromSchema()), \
451
+ OperatorGeneratorArgs( \
452
+ TORCH_SELECTIVE_SCHEMA( \
453
+ #aten_op \
454
+ ".complex_complex(complex a, complex b) -> " #complex_result), \
455
+ [](Stack& stack) { \
456
+ c10::complex<double> a, b; \
457
+ pop(stack, a, b); \
458
+ push(stack, op); \
459
+ }, \
460
+ aliasAnalysisFromSchema())
461
+
462
+ // define implementations for primitive number ops
463
+ #define DEFINE_GENERIC_OP(aten_op, int_op, float_op, int_result, float_result) \
464
+ OperatorGeneratorArgs( \
465
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".int(int a, int b) -> " #int_result), \
466
+ [](Stack& stack) { \
467
+ int64_t a, b; \
468
+ pop(stack, a, b); \
469
+ push(stack, int_op); \
470
+ }, \
471
+ aliasAnalysisFromSchema()), \
472
+ OperatorGeneratorArgs( \
473
+ TORCH_SELECTIVE_SCHEMA( \
474
+ #aten_op ".float(float a, float b) -> " #float_result), \
475
+ [](Stack& stack) { \
476
+ double a, b; \
477
+ pop(stack, a, b); \
478
+ push(stack, float_op); \
479
+ }, \
480
+ aliasAnalysisFromSchema())
481
+
482
+ #define DEFINE_INT_FLOAT_OP(aten_op, op, result) \
483
+ OperatorGeneratorArgs( \
484
+ TORCH_SELECTIVE_SCHEMA(#aten_op \
485
+ ".int_float(int a, float b) -> " #result), \
486
+ [](Stack& stack) { \
487
+ int64_t a; \
488
+ double b; \
489
+ pop(stack, a, b); \
490
+ push(stack, op); \
491
+ }, \
492
+ aliasAnalysisFromSchema()), \
493
+ OperatorGeneratorArgs( \
494
+ TORCH_SELECTIVE_SCHEMA(#aten_op \
495
+ ".float_int(float a, int b) -> " #result), \
496
+ [](Stack& stack) { \
497
+ double a; \
498
+ int64_t b; \
499
+ pop(stack, a, b); \
500
+ push(stack, op); \
501
+ }, \
502
+ aliasAnalysisFromSchema())
503
+
504
+ #define DEFINE_INT_OP(aten_op, op) \
505
+ OperatorGeneratorArgs( \
506
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".int(int a, int b) -> int"), \
507
+ [](Stack& stack) { \
508
+ int64_t a, b; \
509
+ pop(stack, a, b); \
510
+ push(stack, op); /* NOLINT(hicpp-signed-bitwise) */ \
511
+ }, \
512
+ aliasAnalysisFromSchema())
513
+
514
+ #define DEFINE_STR_CMP_OP(aten_op, op) \
515
+ OperatorGeneratorArgs( \
516
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".str(str a, str b) -> bool"), \
517
+ [](Stack& stack) { \
518
+ auto b = pop(stack).toStringRef(); \
519
+ auto a = pop(stack).toStringRef(); \
520
+ push(stack, op); \
521
+ }, \
522
+ aliasAnalysisFromSchema())
523
+
524
+ // define a primitive op over Scalar operands.
525
+ // it's necessary to register this overload following
526
+ // int/float variations to avoid trapping Scalar args
527
+ // in unintended implicit conversions
528
+ #define DEFINE_SCALAR_BINARY_OP_AVOID_COLLISION_GENERIC( \
529
+ aten_op, int_op, float_op, result, string_val) \
530
+ OperatorGeneratorArgs( \
531
+ TORCH_SELECTIVE_SCHEMA(#aten_op string_val \
532
+ "(Scalar a, Scalar b) -> " #result), \
533
+ [](Stack& stack) { \
534
+ IValue x, y; \
535
+ pop(stack, x, y); \
536
+ if (x.isDouble()) { \
537
+ if (y.isDouble()) { \
538
+ double a = x.toDouble(); \
539
+ double b = y.toDouble(); \
540
+ push(stack, float_op); \
541
+ } else { \
542
+ double a = x.toDouble(); \
543
+ int64_t b = y.toInt(); \
544
+ push(stack, float_op); \
545
+ } \
546
+ } else { \
547
+ if (y.isDouble()) { \
548
+ int64_t a = x.toInt(); \
549
+ double b = y.toDouble(); \
550
+ push(stack, float_op); \
551
+ } else { \
552
+ int64_t a = x.toInt(); \
553
+ int64_t b = y.toInt(); \
554
+ push(stack, int_op); \
555
+ } \
556
+ } \
557
+ }, \
558
+ aliasAnalysisFromSchema())
559
+
560
+ #define DEFINE_SCALAR_BINARY_OP(aten_op, int_op, float_op, result) \
561
+ DEFINE_SCALAR_BINARY_OP_AVOID_COLLISION_GENERIC( \
562
+ aten_op, int_op, float_op, result, "")
563
+
564
+ #define DEFINE_SCALAR_BINARY_OP_AVOID_COLLISION( \
565
+ aten_op, int_op, float_op, result) \
566
+ DEFINE_SCALAR_BINARY_OP_AVOID_COLLISION_GENERIC( \
567
+ aten_op, int_op, float_op, result, ".Scalar_Scalar")
568
+
569
+ #define DEFINE_BINARY_OP(aten_op, op) \
570
+ DEFINE_GENERIC_OP(aten_op, op, op, int, float), \
571
+ DEFINE_INT_FLOAT_OP(aten_op, op, float), \
572
+ DEFINE_SCALAR_BINARY_OP(aten_op, op, op, Scalar)
573
+
574
+ #define DEFINE_BINARY_FLOAT_OP(aten_op, op) \
575
+ DEFINE_GENERIC_OP(aten_op, op, op, float, float), \
576
+ DEFINE_INT_FLOAT_OP(aten_op, op, float), \
577
+ DEFINE_SCALAR_BINARY_OP(aten_op, op, op, float)
578
+
579
+ #define DEFINE_COMPARISON_OP(aten_op, op) \
580
+ DEFINE_GENERIC_OP(aten_op, op, op, bool, bool), \
581
+ DEFINE_INT_FLOAT_OP(aten_op, op, bool), \
582
+ DEFINE_SCALAR_BINARY_OP(aten_op, op, op, bool), \
583
+ DEFINE_STR_CMP_OP(aten_op, op)
584
+
585
+ #define DEFINE_UNARY_INT_OP(aten_op, op, result) \
586
+ OperatorGeneratorArgs( \
587
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".int(int a) -> " #result), \
588
+ [](Stack& stack) { \
589
+ int64_t a; \
590
+ pop(stack, a); \
591
+ push(stack, op); \
592
+ }, \
593
+ aliasAnalysisFromSchema())
594
+
595
+ #define DEFINE_UNARY_FLOAT_OP(aten_op, op, result) \
596
+ OperatorGeneratorArgs( \
597
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".float(float a) -> " #result), \
598
+ [](Stack& stack) { \
599
+ double a; \
600
+ pop(stack, a); \
601
+ push(stack, op); \
602
+ }, \
603
+ aliasAnalysisFromSchema())
604
+
605
+ #define DEFINE_UNARY_OP(aten_op, op, int_result, float_result) \
606
+ DEFINE_UNARY_INT_OP(aten_op, op, int_result), \
607
+ DEFINE_UNARY_FLOAT_OP(aten_op, op, float_result), \
608
+ OperatorGeneratorArgs( \
609
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".Scalar(Scalar a) -> Scalar"), \
610
+ [](Stack& stack) { \
611
+ IValue x; \
612
+ pop(stack, x); \
613
+ if (x.isDouble()) { \
614
+ double a = x.toDouble(); \
615
+ push(stack, static_cast<float_result>(op)); \
616
+ } else { \
617
+ int64_t a = x.toInt(); \
618
+ push(stack, static_cast<int_result>(op)); \
619
+ } \
620
+ }, \
621
+ aliasAnalysisFromSchema())
622
+ #define DEFINE_BOOL_OP(aten_op, op) \
623
+ OperatorGeneratorArgs( \
624
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".bool(bool a, bool b) -> bool"), \
625
+ [](Stack& stack) { \
626
+ bool a, b; \
627
+ pop(stack, a, b); \
628
+ push(stack, op); \
629
+ }, \
630
+ aliasAnalysisFromSchema())
631
+ #define DEFINE_STRING_OP(op_name, string_op, result) \
632
+ OperatorGeneratorArgs( \
633
+ TORCH_SELECTIVE_SCHEMA(#op_name ".str(str a, str b) ->" #result), \
634
+ [](Stack& stack) { \
635
+ auto b = pop(stack).toStringRef(); \
636
+ auto a = pop(stack).toStringRef(); \
637
+ push(stack, string_op); \
638
+ }, \
639
+ aliasAnalysisFromSchema())
640
+
641
+ //-----------------------------------------------------------------------------
642
+ //-----------------------------------------------------------------------------
643
+ //-----------------------------------------------------------------------------
644
+ //-----------------------------------------------------------------------------
645
+ #define DEFINE_UNARY_COMPLEX_OP(aten_op, op, result) \
646
+ OperatorGeneratorArgs( \
647
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".complex(complex a) -> " #result), \
648
+ [](Stack& stack) { \
649
+ c10::complex<double> a; \
650
+ pop(stack, a); \
651
+ push(stack, op); \
652
+ }, \
653
+ aliasAnalysisFromSchema())
654
+
655
+ // Some complex unary ops (like abs, angle) return real valued output, but most
656
+ // other unary ops return complex valued output. So, this macro is used in the
657
+ // former case where we can explicitly pass complex_result_cast argument, which
658
+ // is set to c10::complex<float> in the macro `DEFINE_UNARY_OP_WITH_COMPLEX`
659
+ // defined below.
660
+ #define DEFINE_UNARY_OP_WITH_COMPLEX_CAST( \
661
+ aten_op, \
662
+ op, \
663
+ int_result, \
664
+ float_result, \
665
+ complex_result, \
666
+ complex_result_cast) \
667
+ DEFINE_UNARY_INT_OP(aten_op, op, int_result), \
668
+ DEFINE_UNARY_FLOAT_OP(aten_op, op, float_result), \
669
+ DEFINE_UNARY_COMPLEX_OP(aten_op, op, complex_result), \
670
+ OperatorGeneratorArgs( \
671
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".Scalar(Scalar a) -> Scalar"), \
672
+ [](Stack& stack) { \
673
+ IValue x; \
674
+ pop(stack, x); \
675
+ if (x.isDouble()) { \
676
+ double a = x.toDouble(); \
677
+ push(stack, static_cast<float_result>(op)); \
678
+ } else if (x.isComplexDouble()) { \
679
+ c10::complex<double> a = x.toComplexDouble(); \
680
+ push(stack, static_cast<complex_result_cast>(op)); \
681
+ } else { \
682
+ int64_t a = x.toInt(); \
683
+ push(stack, static_cast<int_result>(op)); \
684
+ } \
685
+ }, \
686
+ aliasAnalysisFromSchema())
687
+
688
+ #define DEFINE_UNARY_OP_WITH_COMPLEX(aten_op, op, int_result, float_result) \
689
+ DEFINE_UNARY_OP_WITH_COMPLEX_CAST( \
690
+ aten_op, op, int_result, float_result, complex, c10::complex<double>)
691
+
692
+ #define DEFINE_GENERIC_OP_WITH_COMPLEX( \
693
+ aten_op, \
694
+ int_op, \
695
+ float_op, \
696
+ complex_op, \
697
+ int_result, \
698
+ float_result, \
699
+ complex_result) \
700
+ OperatorGeneratorArgs( \
701
+ TORCH_SELECTIVE_SCHEMA(#aten_op ".int(int a, int b) -> " #int_result), \
702
+ [](Stack& stack) { \
703
+ int64_t a, b; \
704
+ pop(stack, a, b); \
705
+ push(stack, int_op); \
706
+ }, \
707
+ aliasAnalysisFromSchema()), \
708
+ OperatorGeneratorArgs( \
709
+ TORCH_SELECTIVE_SCHEMA( \
710
+ #aten_op ".complex(complex a, complex b) -> " #complex_result), \
711
+ [](Stack& stack) { \
712
+ c10::complex<double> a, b; \
713
+ pop(stack, a, b); \
714
+ push(stack, complex_op); \
715
+ }, \
716
+ aliasAnalysisFromSchema()), \
717
+ OperatorGeneratorArgs( \
718
+ TORCH_SELECTIVE_SCHEMA( \
719
+ #aten_op ".float(float a, float b) -> " #float_result), \
720
+ [](Stack& stack) { \
721
+ double a, b; \
722
+ pop(stack, a, b); \
723
+ push(stack, float_op); \
724
+ }, \
725
+ aliasAnalysisFromSchema())
726
+
727
+ #define DEFINE_INT_COMPLEX_OP(aten_op, op, result) \
728
+ OperatorGeneratorArgs( \
729
+ TORCH_SELECTIVE_SCHEMA(#aten_op \
730
+ ".int_complex(int a, complex b) -> " #result), \
731
+ [](Stack& stack) { \
732
+ int64_t a; \
733
+ c10::complex<double> b; \
734
+ pop(stack, a, b); \
735
+ push(stack, op); \
736
+ }, \
737
+ aliasAnalysisFromSchema()), \
738
+ OperatorGeneratorArgs( \
739
+ TORCH_SELECTIVE_SCHEMA( \
740
+ #aten_op ".complex_int(complex a, int b) -> " #result), \
741
+ [](Stack& stack) { \
742
+ c10::complex<double> a; \
743
+ int64_t b; \
744
+ pop(stack, a, b); \
745
+ push(stack, op); \
746
+ }, \
747
+ aliasAnalysisFromSchema())
748
+
749
+ #define DEFINE_FLOAT_COMPLEX_OP(aten_op, op, result) \
750
+ OperatorGeneratorArgs( \
751
+ TORCH_SELECTIVE_SCHEMA( \
752
+ #aten_op ".float_complex(float a, complex b) -> " #result), \
753
+ [](Stack& stack) { \
754
+ double a; \
755
+ c10::complex<double> b; \
756
+ pop(stack, a, b); \
757
+ push(stack, op); \
758
+ }, \
759
+ aliasAnalysisFromSchema()), \
760
+ OperatorGeneratorArgs( \
761
+ TORCH_SELECTIVE_SCHEMA( \
762
+ #aten_op ".complex_float(complex a, float b) -> " #result), \
763
+ [](Stack& stack) { \
764
+ c10::complex<double> a; \
765
+ double b; \
766
+ pop(stack, a, b); \
767
+ push(stack, op); \
768
+ }, \
769
+ aliasAnalysisFromSchema())
770
+
771
+ #define DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX_AVOID_COLLISION_GENERIC( \
772
+ aten_op, int_op, float_op, complex_op, result, string_val) \
773
+ OperatorGeneratorArgs( \
774
+ TORCH_SELECTIVE_SCHEMA(#aten_op string_val \
775
+ "(Scalar a, Scalar b) -> " #result), \
776
+ [](Stack& stack) { \
777
+ IValue x, y; \
778
+ pop(stack, x, y); \
779
+ if (x.isComplexDouble()) { \
780
+ c10::complex<double> a = x.toComplexDouble(); \
781
+ if (y.isComplexDouble()) { \
782
+ c10::complex<double> b = y.toComplexDouble(); \
783
+ push(stack, complex_op); \
784
+ } else if (y.isDouble()) { \
785
+ double b = y.toDouble(); \
786
+ push(stack, complex_op); \
787
+ } else { \
788
+ int64_t b = y.toInt(); \
789
+ push(stack, complex_op); \
790
+ } \
791
+ } else if (x.isDouble()) { \
792
+ double a = x.toDouble(); \
793
+ if (y.isComplexDouble()) { \
794
+ c10::complex<double> b = y.toComplexDouble(); \
795
+ push(stack, complex_op); \
796
+ } else if (y.isDouble()) { \
797
+ double b = y.toDouble(); \
798
+ push(stack, float_op); \
799
+ } else { \
800
+ int64_t b = y.toInt(); \
801
+ push(stack, float_op); \
802
+ } \
803
+ } else { \
804
+ int64_t a = x.toInt(); \
805
+ if (y.isComplexDouble()) { \
806
+ c10::complex<double> b = y.toComplexDouble(); \
807
+ push(stack, complex_op); \
808
+ } else if (y.isDouble()) { \
809
+ double b = y.toDouble(); \
810
+ push(stack, float_op); \
811
+ } else { \
812
+ int64_t b = y.toInt(); \
813
+ push(stack, int_op); \
814
+ } \
815
+ } \
816
+ }, \
817
+ aliasAnalysisFromSchema())
818
+
819
+ #define DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX_WITHOUT_INT_COMPLEX_PAIR( \
820
+ aten_op, int_op, float_op, complex_op, result) \
821
+ OperatorGeneratorArgs( \
822
+ TORCH_SELECTIVE_SCHEMA(#aten_op "(Scalar a, Scalar b) -> " #result), \
823
+ [](Stack& stack) { \
824
+ IValue x, y; \
825
+ pop(stack, x, y); \
826
+ if (x.isComplexDouble()) { \
827
+ c10::complex<double> a = x.toComplexDouble(); \
828
+ if (y.isComplexDouble()) { \
829
+ c10::complex<double> b = y.toComplexDouble(); \
830
+ push(stack, complex_op); \
831
+ } else if (y.isDouble()) { \
832
+ double b = y.toDouble(); \
833
+ push(stack, complex_op); \
834
+ } \
835
+ } else if (x.isDouble()) { \
836
+ double a = x.toDouble(); \
837
+ if (y.isComplexDouble()) { \
838
+ c10::complex<double> b = y.toComplexDouble(); \
839
+ push(stack, complex_op); \
840
+ } else if (y.isDouble()) { \
841
+ double b = y.toDouble(); \
842
+ push(stack, float_op); \
843
+ } else { \
844
+ int64_t b = y.toInt(); \
845
+ push(stack, float_op); \
846
+ } \
847
+ } else { \
848
+ int64_t a = x.toInt(); \
849
+ if (y.isDouble()) { \
850
+ double b = y.toDouble(); \
851
+ push(stack, float_op); \
852
+ } else if (y.isInt()) { \
853
+ int64_t b = y.toInt(); \
854
+ push(stack, int_op); \
855
+ } \
856
+ } \
857
+ }, \
858
+ aliasAnalysisFromSchema())
859
+
860
+ #define DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX( \
861
+ aten_op, int_op, float_op, complex_op, result) \
862
+ DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX_AVOID_COLLISION_GENERIC( \
863
+ aten_op, int_op, float_op, complex_op, result, "")
864
+
865
+ #define DEFINE_BINARY_OP_WITH_COMPLEX(aten_op, op) \
866
+ DEFINE_GENERIC_OP_WITH_COMPLEX(aten_op, op, op, op, int, float, complex), \
867
+ DEFINE_INT_COMPLEX_OP(aten_op, op, complex), \
868
+ DEFINE_FLOAT_COMPLEX_OP(aten_op, op, complex), \
869
+ DEFINE_INT_FLOAT_OP(aten_op, op, float), \
870
+ DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX(aten_op, op, op, op, Scalar)
871
+
872
+ #define DEFINE_COMPARISON_OP_WITH_COMPLEX(aten_op, op) \
873
+ DEFINE_GENERIC_OP_WITH_COMPLEX(aten_op, op, op, op, bool, bool, bool), \
874
+ DEFINE_INT_FLOAT_OP(aten_op, op, bool), \
875
+ DEFINE_FLOAT_COMPLEX_OP(aten_op, op, bool), \
876
+ DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX_WITHOUT_INT_COMPLEX_PAIR( \
877
+ aten_op, op, op, op, bool), \
878
+ DEFINE_STR_CMP_OP(aten_op, op)
879
+
880
+ TORCH_API at::Generator make_generator_for_device(
881
+ c10::Device device,
882
+ std::optional<int64_t> seed = std::nullopt);
883
+
884
+ } // namespace torch::jit
885
+
886
+ #else
887
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
888
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/script_profile.h ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <chrono>
5
+ #include <map>
6
+ #include <string>
7
+
8
+ #include <ATen/core/ivalue.h>
9
+ #include <c10/macros/Macros.h>
10
+ #include <torch/csrc/jit/frontend/source_ref.h>
11
+ #include <torch/csrc/jit/ir/ir.h>
12
+
13
+ namespace torch::jit {
14
+ namespace profiling {
15
+
16
+ struct Datapoint {
17
+ using Timepoint = std::chrono::time_point<std::chrono::steady_clock>;
18
+ SourceRange sourceRange;
19
+ Timepoint start;
20
+ Timepoint end;
21
+
22
+ explicit Datapoint(SourceRange sr)
23
+ : sourceRange(std::move(sr)), start(std::chrono::steady_clock::now()) {}
24
+ };
25
+
26
+ class TORCH_API InstructionSpan {
27
+ public:
28
+ explicit InstructionSpan(Node& /*node*/);
29
+ ~InstructionSpan();
30
+ InstructionSpan(InstructionSpan&&) = delete;
31
+ InstructionSpan& operator=(InstructionSpan&&) = delete;
32
+
33
+ private:
34
+ std::unique_ptr<Datapoint> datapoint_;
35
+ };
36
+
37
+ bool TORCH_API isProfilingOngoing();
38
+
39
+ } // namespace profiling
40
+
41
+ struct TORCH_API InstructionStats : public CustomClassHolder {
42
+ int64_t count{0};
43
+ std::chrono::nanoseconds duration{0};
44
+ };
45
+
46
+ class TORCH_API SourceStats : public CustomClassHolder {
47
+ public:
48
+ using LineMap = c10::Dict<int64_t, c10::intrusive_ptr<InstructionStats>>;
49
+
50
+ SourceStats(SourceRef source, const LineMap& lineMap)
51
+ : source_(std::move(source)), lineMap_(lineMap) {}
52
+
53
+ const SourceRef& getSourceRef() const {
54
+ return source_;
55
+ }
56
+
57
+ const LineMap& getLineMap() const {
58
+ return lineMap_;
59
+ }
60
+
61
+ private:
62
+ SourceRef source_;
63
+ LineMap lineMap_;
64
+ };
65
+
66
+ /**
67
+ * ScriptProfile is an underlying C++ implementation for TorchScript profiling.
68
+ * The profiling section is specified by calling enable() and disable():
69
+ *
70
+ * ...
71
+ * scriptProfile.enable();
72
+ * ...
73
+ * (scripts)
74
+ * ...
75
+ * scriptProfile.disable();
76
+ * ...
77
+ *
78
+ * NOTE: you cannot attach the profiler while the script is running.
79
+ *
80
+ * To retrieve collected runtime data, users may call dumpStats() and do
81
+ * arbitrary filtering on the data they want. Note that dumpStats() should
82
+ * not be called inside a profiling section.
83
+ * In general, stats are aggregated per source function body, and then by line
84
+ * number.
85
+ */
86
+ class TORCH_API ScriptProfile : public CustomClassHolder {
87
+ // Aggregates datapoints by function source id, then by line number.
88
+ using LineMap = std::map<int64_t, InstructionStats>;
89
+ using SourceMap = std::map<SourceRef, LineMap, std::less<>>;
90
+
91
+ public:
92
+ void enable();
93
+ void disable();
94
+ const SourceMap& dumpStats();
95
+ void addDatapoint(std::shared_ptr<profiling::Datapoint> /*datapoint*/);
96
+ ~ScriptProfile() override;
97
+
98
+ private:
99
+ bool enabled_{false};
100
+ std::vector<std::shared_ptr<profiling::Datapoint>> datapoints_;
101
+ SourceMap sourceMap_;
102
+ };
103
+
104
+ } // namespace torch::jit
105
+
106
+ #else
107
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
108
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/serialized_shape_function_registry.h ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/Export.h>
5
+ #include <torch/csrc/jit/ir/ir.h>
6
+
7
+ namespace torch::jit {
8
+
9
+ TORCH_API const std::string& GetSerializedShapeFunctions();
10
+
11
+ TORCH_API const OperatorMap<std::string>& GetShapeFunctionMappings();
12
+
13
+ TORCH_API const OperatorMap<std::pair<std::string, std::string>>&
14
+ GetBoundedShapeMappings();
15
+
16
+ } // namespace torch::jit
17
+
18
+ #else
19
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
20
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/shape_function_registry.h ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/Export.h>
5
+ #include <torch/csrc/jit/ir/ir.h>
6
+
7
+ namespace torch::jit {
8
+
9
+ TORCH_API const std::string& GetSerializedFuncs();
10
+
11
+ TORCH_API const OperatorMap<std::string>& GetFuncMapping();
12
+
13
+ } // namespace torch::jit
14
+
15
+ #else
16
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
17
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/simple_graph_executor_impl.h ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <c10/util/Flags.h>
4
+ #include <torch/csrc/jit/api/module.h>
5
+ #include <torch/csrc/jit/runtime/graph_executor_impl.h>
6
+
7
+ namespace torch::jit {
8
+
9
+ struct TORCH_API SimpleGraphExecutorImpl : public GraphExecutorImplBase {
10
+ SimpleGraphExecutorImpl(
11
+ const std::shared_ptr<Graph>& graph,
12
+ std::string function_name);
13
+
14
+ const ExecutionPlan& getPlanFor(
15
+ Stack& stack,
16
+ std::optional<size_t> remaining_bailout_depth) override;
17
+ const ExecutionPlan& getInputIndependentPlan() override;
18
+ GraphExecutorState getDebugState() override;
19
+ ~SimpleGraphExecutorImpl() override = default;
20
+
21
+ private:
22
+ const ExecutionPlan& getInputIndependentPlanImpl();
23
+
24
+ std::optional<ExecutionPlan> execution_plan_;
25
+ };
26
+
27
+ } // namespace torch::jit
28
+
29
+ #else
30
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
31
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/slice_indices_adjust.h ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/Export.h>
5
+ #include <cstddef>
6
+ #include <cstdint>
7
+
8
+ namespace torch::jit {
9
+
10
+ // Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
11
+ // 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software
12
+ // Foundation; All Rights Reserved
13
+ //
14
+ // Stolen (with appropriate modifications) by @agolynski
15
+ // (https://github.com/pytorch/pytorch/pull/33019) from cpython repo
16
+ // Objects/sliceobject.c with comment: this is harder to get right than you
17
+ // might think
18
+ //
19
+ // This adjusts indexes according to python list semantics and returns number
20
+ // of elements in the resulting list.
21
+ TORCH_API int64_t slice_indices_adjust(
22
+ int64_t length,
23
+ int64_t* start,
24
+ int64_t* stop,
25
+ int64_t step);
26
+
27
+ } // namespace torch::jit
28
+
29
+ #else
30
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
31
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/ProcessedNodeInputs.h ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <cstddef>
5
+ #include <cstdint>
6
+ #include <cstring>
7
+
8
+ #include <memory>
9
+
10
+ #include <c10/macros/Macros.h>
11
+ #include <c10/util/Logging.h>
12
+
13
+ /**
14
+ * Packed representation of input indices for ProcessedNode.
15
+ */
16
+ class ProcessedNodeInputs {
17
+ private:
18
+ // This keeps the size usage for inputs + outputs down to 16 bytes;
19
+ // we use 12 bytes, and then two 2-byte integers are used to store
20
+ // the outputs.
21
+ static constexpr size_t kMaxInlineInputs = 5;
22
+
23
+ public:
24
+ ProcessedNodeInputs() : ProcessedNodeInputs(0) {}
25
+
26
+ explicit ProcessedNodeInputs(size_t size) {
27
+ TORCH_DCHECK_LT(size, (1 << 16));
28
+ if (size <= kMaxInlineInputs) {
29
+ repr_.inline_repr_.size = size;
30
+ } else {
31
+ new (&repr_.outline_repr_) HeapArrayPtr(size);
32
+ }
33
+ }
34
+
35
+ uint16_t operator[](uint16_t idx) const {
36
+ // NOLINTNEXTLINE(*const-cast*)
37
+ return (*const_cast<ProcessedNodeInputs*>(this))[idx];
38
+ }
39
+
40
+ uint16_t& operator[](uint16_t idx) {
41
+ if (C10_LIKELY(repr_.is_inline())) {
42
+ TORCH_DCHECK_LT(idx, repr_.inline_repr_.size);
43
+ return repr_.inline_repr_.inputs[idx];
44
+ } else {
45
+ return repr_.outline_repr_[idx];
46
+ }
47
+ }
48
+
49
+ [[nodiscard]] uint16_t size() const {
50
+ if (C10_LIKELY(repr_.is_inline())) {
51
+ return repr_.inline_repr_.size;
52
+ } else {
53
+ return repr_.outline_repr_.size();
54
+ }
55
+ }
56
+
57
+ [[nodiscard]] bool empty() const {
58
+ return size() == 0;
59
+ }
60
+
61
+ private:
62
+ class HeapArrayPtr {
63
+ public:
64
+ HeapArrayPtr() = default;
65
+ ~HeapArrayPtr() = default;
66
+
67
+ explicit HeapArrayPtr(uint16_t size) : array_(alloc(size)) {}
68
+
69
+ HeapArrayPtr(const HeapArrayPtr& rhs) : array_(alloc(rhs.size())) {
70
+ if (rhs.array_) {
71
+ std::memcpy(
72
+ array_.get(),
73
+ rhs.array_.get(),
74
+ (rhs.size() + 1) * sizeof(uint16_t));
75
+ }
76
+ }
77
+
78
+ HeapArrayPtr& operator=(const HeapArrayPtr& rhs) {
79
+ if (&rhs == this) {
80
+ return *this;
81
+ }
82
+
83
+ if (size() != rhs.size()) {
84
+ array_ = alloc(rhs.size());
85
+ }
86
+
87
+ if (rhs.array_) {
88
+ std::memcpy(
89
+ array_.get(),
90
+ rhs.array_.get(),
91
+ (rhs.size() + 1) * sizeof(uint16_t));
92
+ }
93
+ return *this;
94
+ }
95
+
96
+ HeapArrayPtr(HeapArrayPtr&&) noexcept = default;
97
+ HeapArrayPtr& operator=(HeapArrayPtr&&) noexcept = default;
98
+
99
+ [[nodiscard]] bool empty() const {
100
+ return size() != 0;
101
+ }
102
+
103
+ [[nodiscard]] uint16_t size() const {
104
+ return array_ ? array_[0] : 0;
105
+ }
106
+
107
+ uint16_t operator[](uint16_t idx) const {
108
+ TORCH_DCHECK_LT(idx, size());
109
+ return array_[idx + 1];
110
+ }
111
+
112
+ uint16_t& operator[](uint16_t idx) {
113
+ TORCH_DCHECK_LT(idx, size());
114
+ return array_[idx + 1];
115
+ }
116
+
117
+ private:
118
+ // NOLINTNEXTLINE(modernize-avoid-c-arrays)
119
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
120
+ std::unique_ptr<uint16_t[]> array_;
121
+
122
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
123
+ // NOLINTNEXTLINE(modernize-avoid-c-arrays)
124
+ static std::unique_ptr<uint16_t[]> alloc(uint16_t num_elts) {
125
+ if (num_elts) {
126
+ auto result = std::make_unique<uint16_t[]>(num_elts + 1);
127
+ result[0] = num_elts;
128
+ return result;
129
+ } else {
130
+ return nullptr;
131
+ }
132
+ }
133
+ };
134
+
135
+ // We want ProcessedNode to be able to pack two more `uint16_t`
136
+ // fields after its ProcessedNodeInputs, and we'll end up being
137
+ // aligned to an 8-byte boundary anyway. We could avoid this pragma
138
+ // at the cost of having to move ProcessedNode::outputs_offset_ and
139
+ // ProcessedNode::num_outputs_ into this class, which would be
140
+ // awkward.
141
+ #pragma pack(push, 2)
142
+ union Repr {
143
+ [[nodiscard]] bool is_inline() const {
144
+ uint8_t tag = 0;
145
+ // Use of reinterpret_cast to pointer to char or unsigned char
146
+ // is defined behavior; see
147
+ // https://en.cppreference.com/w/cpp/language/reinterpret_cast .
148
+ std::memcpy(&tag, reinterpret_cast<const uint8_t*>(this), 1);
149
+ // HeapArrayPtr will be represented as a plain old pointer,
150
+ // which will have alignment to at least a 2-byte boundary
151
+ // (because it's uint16_t*) and more likely an 8- or 16-byte
152
+ // boundary because malloc will tend to just align everything to
153
+ // one of those. So, we just set tag to 1 when inline_repr_ is
154
+ // active so as to be able to differentiate the two.
155
+ return (tag & 1) != 0;
156
+ }
157
+
158
+ // NOLINTNEXTLINE(modernize-use-equals-default)
159
+ Repr() {}
160
+
161
+ ~Repr() {
162
+ destroyIfOutline();
163
+ }
164
+
165
+ Repr(const Repr& rhs) {
166
+ if (rhs.is_inline()) {
167
+ std::memcpy(&inline_repr_, &rhs.inline_repr_, sizeof(inline_repr_));
168
+ } else {
169
+ new (&outline_repr_) OutlineRepr(rhs.outline_repr_);
170
+ }
171
+ }
172
+
173
+ Repr& operator=(const Repr& rhs) {
174
+ if (&rhs == this) {
175
+ return *this;
176
+ }
177
+ if (rhs.is_inline()) {
178
+ destroyIfOutline();
179
+ new (&inline_repr_) InlineRepr();
180
+ std::memcpy(&inline_repr_, &rhs.inline_repr_, sizeof(inline_repr_));
181
+ } else {
182
+ if (is_inline()) {
183
+ new (&outline_repr_) OutlineRepr(rhs.outline_repr_);
184
+ } else {
185
+ outline_repr_ = rhs.outline_repr_;
186
+ }
187
+ }
188
+ return *this;
189
+ }
190
+
191
+ Repr(Repr&& rhs) noexcept {
192
+ if (rhs.is_inline()) {
193
+ std::memcpy(&inline_repr_, &rhs.inline_repr_, sizeof(inline_repr_));
194
+ } else {
195
+ new (&outline_repr_) OutlineRepr(std::move(rhs.outline_repr_));
196
+ }
197
+ }
198
+
199
+ Repr& operator=(Repr&& rhs) noexcept {
200
+ if (&rhs == this) {
201
+ return *this;
202
+ }
203
+
204
+ if (rhs.is_inline()) {
205
+ destroyIfOutline();
206
+ new (&inline_repr_) InlineRepr();
207
+ std::memcpy(&inline_repr_, &rhs.inline_repr_, sizeof(inline_repr_));
208
+ } else {
209
+ if (is_inline()) {
210
+ new (&outline_repr_) OutlineRepr(std::move(rhs.outline_repr_));
211
+ } else {
212
+ outline_repr_ = std::move(rhs.outline_repr_);
213
+ }
214
+ }
215
+
216
+ return *this;
217
+ }
218
+
219
+ struct InlineRepr {
220
+ uint8_t tag = 0x1;
221
+ uint8_t size{};
222
+ uint16_t inputs[kMaxInlineInputs]{};
223
+ };
224
+
225
+ using OutlineRepr = HeapArrayPtr;
226
+
227
+ InlineRepr inline_repr_{};
228
+ OutlineRepr outline_repr_;
229
+
230
+ private:
231
+ void destroyIfOutline() {
232
+ if (!is_inline()) {
233
+ outline_repr_.~OutlineRepr();
234
+ }
235
+ }
236
+ } repr_;
237
+ #pragma pack(pop)
238
+ };
239
+
240
+ static_assert(
241
+ sizeof(ProcessedNodeInputs) == 12,
242
+ "ProcessedNodeInputs has the wrong size!");
243
+
244
+ #else
245
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
246
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/fusion.h ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+
6
+ namespace torch::jit {
7
+
8
+ TORCH_API void fuseStaticSubgraphs(
9
+ std::shared_ptr<Graph> graph,
10
+ size_t min_size);
11
+
12
+ TORCH_API void performTensorExprFusion(
13
+ std::shared_ptr<Graph> graph,
14
+ std::vector<IValue> sample_inputs);
15
+
16
+ } // namespace torch::jit
17
+
18
+ #else
19
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
20
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/impl.h ADDED
@@ -0,0 +1,1152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <ATen/core/ivalue.h>
4
+ #include <ATen/core/symbol.h>
5
+ #include <c10/core/CPUAllocator.h>
6
+ #include <c10/macros/Macros.h>
7
+ #include <c10/util/ArrayRef.h>
8
+ #include <c10/util/FbcodeMaps.h>
9
+ #include <torch/csrc/jit/api/module.h>
10
+ #include <torch/csrc/jit/ir/graph_node_list.h>
11
+ #include <torch/csrc/jit/ir/ir.h>
12
+ #include <torch/csrc/jit/passes/constant_propagation.h>
13
+ #include <torch/csrc/jit/passes/freeze_module.h>
14
+ #include <torch/csrc/jit/passes/inliner.h>
15
+ #include <torch/csrc/jit/runtime/static/ProcessedNodeInputs.h>
16
+ #include <torch/custom_class.h>
17
+ #include <limits>
18
+
19
+ #ifdef FBCODE_CAFFE2
20
+ #include <folly/container/F14Map.h>
21
+ #include <folly/container/F14Set.h>
22
+ #endif
23
+
24
+ namespace torch::jit {
25
+
26
+ TORCH_API bool canEnableStaticRuntime(
27
+ const std::shared_ptr<torch::jit::Graph>& graph);
28
+
29
+ TORCH_API std::string dumpValueSet(
30
+ const c10::FastSet<const Value*>& value_set,
31
+ const char* set_name = "");
32
+
33
+ inline bool doesNotHeapAllocateWhenStoredInIValue(const Type& type) {
34
+ switch (type.kind()) {
35
+ // NOTE: NumberType may allocate because it includes complex.
36
+ case TypeKind::NoneType:
37
+ case TypeKind::IntType:
38
+ case TypeKind::FloatType:
39
+ case TypeKind::BoolType:
40
+ case TypeKind::DeviceObjType:
41
+ case TypeKind::StreamObjType:
42
+ return true;
43
+ default:
44
+ return false;
45
+ }
46
+ }
47
+
48
+ inline c10::Symbol getStaticRuntimeMetadataSymbol() {
49
+ return Symbol::attr("static_runtime::metadata");
50
+ }
51
+
52
+ inline bool borrowsOutputs(c10::Symbol kind) {
53
+ static const std::array<c10::Symbol, 4> symbols_with_borrowed_outputs = {
54
+ c10::Symbol::fromQualString("static_runtime::select_tensor"),
55
+ c10::Symbol::fromQualString("static_runtime::dict_unpack"),
56
+ c10::Symbol::fromQualString("static_runtime::VarTupleUnpack"),
57
+ c10::Symbol::fromQualString("prim::IfThenElse"),
58
+ };
59
+ return std::find(
60
+ symbols_with_borrowed_outputs.begin(),
61
+ symbols_with_borrowed_outputs.end(),
62
+ kind) != symbols_with_borrowed_outputs.end();
63
+ }
64
+
65
+ // Group values used by `graph` into three categories:
66
+ //
67
+ // - output_aliases:
68
+ // values that are either outputs or contain aliases of outputs
69
+ // - external_aliases:
70
+ // values that are inputs, constants, or their aliases.
71
+ // The output aliases that end up here are as a result of aliasDb failing to
72
+ // recognize them as outputs due to collection object (e.g., Tuple) aliasing
73
+ // inputs.
74
+ // Values that don't show up in output_aliases or external_aliases are created
75
+ // and consumed within the graph.
76
+ class ValueGroup {
77
+ public:
78
+ explicit ValueGroup() = default;
79
+ void init(const Block& block, const AliasDb& db);
80
+
81
+ bool isExternalAlias(const Value* value) const {
82
+ return external_aliases_.find(value) != external_aliases_.end();
83
+ }
84
+
85
+ bool isOutputAlias(const Value* value) const {
86
+ return output_aliases_.find(value) != output_aliases_.end();
87
+ }
88
+
89
+ bool isAlwaysAlive(const Value* value) const {
90
+ return isExternalAlias(value) || isOutputAlias(value);
91
+ }
92
+
93
+ std::string toString() const {
94
+ return c10::str(
95
+ dumpValueSet(output_aliases_, "ValueGroup::output_aliases_"),
96
+ "\n",
97
+ dumpValueSet(external_aliases_, "ValueGroup::external_aliases_"));
98
+ }
99
+
100
+ private:
101
+ c10::FastSet<const Value*> output_aliases_;
102
+ c10::FastSet<const Value*> external_aliases_;
103
+ };
104
+
105
+ class TORCH_API ManagedTensorRanges {
106
+ public:
107
+ ManagedTensorRanges() = default;
108
+ ManagedTensorRanges(
109
+ Block& block,
110
+ const AliasDb& alias_db,
111
+ const c10::FastSet<const Value*>& managed_tensor_values);
112
+
113
+ // If true, then this node is the last use of at least one
114
+ // managed tensor. availableTensorValuesAfterNode(node) will return a vector
115
+ // of the managed tensors that are available for reuse
116
+ // in the nodes following this one.
117
+ bool nodeFreesManagedTensors(Node* node) const;
118
+ const std::vector<const Value*>& availableTensorValuesAfterNode(
119
+ Node* node) const;
120
+
121
+ // For testing. True if v1 and v2 are both mutable types and have lifetimes
122
+ // that overlap.
123
+ bool lifetimesOverlap(const Value* v1, const Value* v2) const;
124
+
125
+ private:
126
+ struct Lifetime {
127
+ Lifetime(size_t start_, size_t end_) : start(start_), end(end_) {}
128
+ size_t start;
129
+ size_t end;
130
+ };
131
+
132
+ // Returns nullptr if we are not tracking the lifetime of value
133
+ Lifetime* getLifetime(const Value* value);
134
+ const Lifetime* getLifetime(const Value* value) const;
135
+ // Collect all values in the input that have tracked lifetimes.
136
+ // A value's lifetime may not be tracked if it is a graph input
137
+ // or immutable type (containers with at least one mutable
138
+ // type are mutable)
139
+ std::vector<const Value*> collectValuesWithTrackedLifetimes(
140
+ at::ArrayRef<const Value*> values);
141
+ void extendLifetime(Value* input, size_t new_end);
142
+ void extendInputLifetime(Node* node, size_t new_end);
143
+
144
+ // Maps Node* to the set of managed tensors that are now available
145
+ // for reuse after this node.
146
+ c10::FastMap<Node*, std::vector<const Value*>> node_to_newly_free_tensors_;
147
+ // Maps each Value* to its lifetime (start node index, end node index)
148
+ c10::FastMap<const Value*, Lifetime> value_lifetimes_;
149
+ };
150
+
151
+ struct TORCH_API StaticModuleOptions {
152
+ // enabling out variant allows Static Runtime to do memory planning
153
+ bool enable_out_variant{true};
154
+ // to reuse tensor storage for tensors whose live-range do not overlap to
155
+ // reduce memory footprint (enable_out_variant must be true)
156
+ bool optimize_memory{true};
157
+ // to batch allocate tensor storage for output tensors of the
158
+ // graph, where storage is deallocated outside static runtime
159
+ // (enable_out_variant must be true)
160
+ bool manage_output_tensors{false};
161
+ // Gates the ReplaceWithCopy pass, which replaces ops that
162
+ // sometimes alias their outputs with out variants that
163
+ // always copy (so the output may participate in memory planning).
164
+ // Since replacing with copies is done after TensorExpr fusion, the
165
+ // resulting graph does not conform to the assumptions made in the fuser.
166
+ // So, even if this flag is turned on, the ReplaceWithCopy pass will not
167
+ // be executed if TensorExpr fusion is enabled.
168
+ bool use_copy_variants{true};
169
+ // Gates the ReplaceWithMaybeCopy pass, which replaces ops that
170
+ // sometimes alias their outputs with subgraphs that include an out
171
+ // variant.
172
+ // For the same reason as `use_copy_variants`, the ReplaceWithMaybeCopy pass
173
+ // will not be executed if TensorExpr fusion is enabled, even if this flag
174
+ // is turned on.
175
+ bool use_maybe_copy_variants{true};
176
+ // enable TensorExpr fusion of ops at model loading time
177
+ bool enable_tensorexpr_fusion{false};
178
+ };
179
+
180
+ /*
181
+ Responsible for plugging StaticRuntime metadata onto the
182
+ IR nodes. StaticRuntimeMetdata extends CustomClassHolder
183
+ which can be casted to IValue and attached to IR node.
184
+ This is needed to pass parent graph metadata to forked
185
+ graph in presence of prim::fork operator
186
+ */
187
+ class TORCH_API StaticRuntimeMetadata : public torch::CustomClassHolder {
188
+ public:
189
+ explicit StaticRuntimeMetadata(const StaticModuleOptions& opts)
190
+ : opts_(opts) {}
191
+
192
+ const StaticModuleOptions& get_opts() {
193
+ return opts_;
194
+ }
195
+
196
+ private:
197
+ StaticModuleOptions opts_;
198
+ };
199
+
200
+ /// The static runime supports two execution modes.
201
+ ///
202
+ /// Mode 1: single-threaded with no parallelism except for intra-op parallelism
203
+ /// For this mode, you can do either:
204
+ /// @code
205
+ /// // m is a TorchScript module
206
+ /// auto module = StaticModule(m, opts);
207
+ /// auto output = module(args, kwargs);
208
+ /// @endcode
209
+ ///
210
+ /// or
211
+ ///
212
+ /// @code
213
+ /// // g is the TorchScript graph
214
+ /// auto module = StaticModule(g, opts);
215
+ /// auto output = module(args, kwargs);
216
+ /// @endcode
217
+ ///
218
+ /// Mode 2: similar to data parallelism, run the same model for different inputs
219
+ /// on different threads at the same time.
220
+ /// You should have one StaticModule per model, and one StaticRuntime instance
221
+ /// per running thread. To avoiding creating StaticRuntimes on the fly, use a
222
+ /// synchronized stack (i.e. boost::lockfree::stack) to cache all the
223
+ /// StaticRuntime instances in your code.
224
+ /// @code
225
+ /// // initialization
226
+ /// auto module = std::make_shared<StaticModule>(m, opts);
227
+ ///
228
+ /// // 128 is good for most cases. Pick a number that works for you
229
+ /// boost::lockfree::stack<std::shared_ptr<StaticRuntime>,
230
+ /// boost::lockfree::fixed_sized<true>> pool(128);
231
+ ///
232
+ /// // inference
233
+ /// std::shared_ptr<StaticRuntime> runtime = nullptr;
234
+ /// pool.pop(runtime);
235
+ /// if (!runtime) {
236
+ /// // holds a reference to the underlying module
237
+ /// // but does its own memory management
238
+ /// runtime = std::make_shared<StaticRuntime>(*module);
239
+ /// }
240
+ /// auto output = runtime(args, kwargs);
241
+ /// pool.push(runtime);
242
+ /// @endcode
243
+ ///
244
+ class MemoryPlanner;
245
+ class ProcessedNode;
246
+ class StaticRuntime;
247
+
248
+ using SROperator = std::function<void(ProcessedNode*)>;
249
+
250
+ #ifdef FBCODE_CAFFE2
251
+ struct TORCH_API SROperatorObserver {
252
+ using OperatorCallback = void (*)(const Node*);
253
+ OperatorCallback startCb = nullptr;
254
+ OperatorCallback endCb = nullptr;
255
+
256
+ static void setCurrentThreadObserver(SROperatorObserver* observer);
257
+ static SROperatorObserver* getCurrentThreadObserver();
258
+ static void onStart(const Node* name);
259
+ static void onEnd(const Node* name);
260
+ };
261
+ #endif
262
+
263
+ class TORCH_API ProcessedFunction {
264
+ public:
265
+ ProcessedFunction(
266
+ Node* node,
267
+ bool enable_out_variant,
268
+ bool check_memory_overlap);
269
+
270
+ enum class Kind : uint8_t {
271
+ kOutVariant,
272
+ kNativeFunction,
273
+ kInterpreterFallback,
274
+ };
275
+
276
+ void run(ProcessedNode* pnode) const {
277
+ return f_(pnode);
278
+ }
279
+
280
+ Kind kind() const {
281
+ return kind_;
282
+ }
283
+
284
+ bool checkMemoryOverlap() const {
285
+ return check_memory_overlap_;
286
+ }
287
+
288
+ size_t num_outputs() const {
289
+ return num_outputs_;
290
+ }
291
+
292
+ private:
293
+ SROperator f_;
294
+ Kind kind_{ProcessedFunction::Kind::kOutVariant};
295
+ bool check_memory_overlap_{false};
296
+ size_t num_outputs_{0};
297
+ };
298
+
299
+ class TORCH_API StaticNodeInfo {
300
+ public:
301
+ StaticNodeInfo(
302
+ Node* n,
303
+ ProcessedFunction* fn,
304
+ ProcessedNodeInputs inputs,
305
+ uint16_t outputs_offset);
306
+
307
+ Node* node() const {
308
+ return node_;
309
+ }
310
+
311
+ size_t num_outputs() const {
312
+ DCHECK(fn_ != nullptr);
313
+ return fn_->num_outputs();
314
+ }
315
+
316
+ bool has_out_variant() const {
317
+ return fn_->kind() == ProcessedFunction::Kind::kOutVariant;
318
+ }
319
+
320
+ private:
321
+ friend class ProcessedNode;
322
+
323
+ Node* node_;
324
+ const ProcessedFunction* fn_;
325
+ ProcessedNodeInputs inputs_;
326
+ uint16_t outputs_offset_;
327
+ };
328
+
329
+ // A `BlockInfo` instance stores all of the shared state that each
330
+ // `BlockRunner` will need to access. Most of this information is
331
+ // read-only and shared between threads.
332
+ // - Each `BlockInfo` corresponds to one block in the graph.
333
+ // - Each `BlockInfo` may be used by multiple block runners (when there are many
334
+ // threads).
335
+ // - All of the `BlockInfo`s are stored in a vector in the `StaticModule` and
336
+ // are initialized during `StaticModule` construction.
337
+ // - Most of the information stored is used to initialize the block's memory
338
+ // planner.
339
+ class BlockInfo {
340
+ public:
341
+ BlockInfo(uint32_t input_idx, Block& block);
342
+
343
+ void set_nodes(
344
+ std::vector<StaticNodeInfo> nodes,
345
+ const c10::FastMap<Node*, bool>& node_has_out_variant);
346
+
347
+ const std::vector<StaticNodeInfo>& nodes() const {
348
+ return nodes_;
349
+ }
350
+
351
+ size_t num_nodes() const;
352
+
353
+ size_t num_inputs() const {
354
+ return block_.inputs().size();
355
+ }
356
+
357
+ size_t num_outputs() const {
358
+ return block_.outputs().size();
359
+ }
360
+
361
+ graph_node_list node_ptrs() const {
362
+ return block_.nodes();
363
+ }
364
+
365
+ void set_output_indices(std::vector<uint16_t> indices) {
366
+ output_indices_ = std::move(indices);
367
+ }
368
+
369
+ const std::vector<uint16_t>& block_output_indices() const {
370
+ return output_indices_;
371
+ }
372
+
373
+ auto block_inputs_idx() const {
374
+ return input_idx_;
375
+ }
376
+
377
+ bool node_is_optimizable_container_type(const Node* node) const {
378
+ return node_is_optimizable_container_type_.find(node) !=
379
+ node_is_optimizable_container_type_.end();
380
+ }
381
+
382
+ bool value_is_managed_tensor(const Value* value) const {
383
+ return managed_tensor_values_.find(value) != managed_tensor_values_.end();
384
+ }
385
+
386
+ bool value_is_leaked_container(const Value* value) const {
387
+ return leaked_values_.find(value) != leaked_values_.end();
388
+ }
389
+
390
+ const ValueGroup& value_group() const {
391
+ return value_group_;
392
+ }
393
+
394
+ const ManagedTensorRanges& managed_tensor_ranges() const {
395
+ return managed_tensor_ranges_;
396
+ }
397
+
398
+ void init_value_group(const AliasDb& alias_db) {
399
+ value_group_.init(block_, alias_db);
400
+ }
401
+
402
+ void prepare_for_memory_planner(
403
+ const AliasDb& alias_db,
404
+ const StaticModuleOptions& opt);
405
+
406
+ const auto& managed_output_tensor_values() const {
407
+ return managed_output_tensor_values_;
408
+ }
409
+
410
+ const auto& managed_tensor_values() const {
411
+ return managed_tensor_values_;
412
+ }
413
+
414
+ const auto& leaked_values() const {
415
+ return leaked_values_;
416
+ }
417
+
418
+ private:
419
+ std::vector<StaticNodeInfo> nodes_;
420
+
421
+ ValueGroup value_group_;
422
+
423
+ c10::FastSet<const Node*> node_is_optimizable_container_type_;
424
+ c10::FastSet<const Value*> managed_tensor_values_;
425
+ c10::FastSet<const Value*> managed_output_tensor_values_;
426
+ c10::FastSet<const Value*> leaked_values_;
427
+
428
+ ManagedTensorRanges managed_tensor_ranges_;
429
+
430
+ // The index of this block's inputs in the shared values_ array.
431
+ const uint16_t input_idx_;
432
+ // The indices of this block's outputs in the shared values_ array.
433
+ std::vector<uint16_t> output_indices_;
434
+ Block& block_;
435
+ };
436
+
437
+ class TORCH_API StaticModule {
438
+ public:
439
+ explicit StaticModule(
440
+ const std::shared_ptr<torch::jit::Graph>& g,
441
+ const StaticModuleOptions& opts = StaticModuleOptions(),
442
+ std::vector<IValue> sample_inputs = {});
443
+
444
+ explicit StaticModule(
445
+ const torch::jit::Module& m,
446
+ bool is_frozen = false,
447
+ const StaticModuleOptions& opts = StaticModuleOptions(),
448
+ std::vector<IValue> sample_inputs = {});
449
+
450
+ private:
451
+ explicit StaticModule(
452
+ std::pair<std::shared_ptr<torch::jit::Graph>, std::optional<Module>>
453
+ graph_and_module,
454
+ const StaticModuleOptions& opts);
455
+
456
+ public:
457
+ using KeywordArgs = std::unordered_map<std::string, c10::IValue>;
458
+ c10::IValue operator()(
459
+ const std::vector<c10::IValue>& args,
460
+ const KeywordArgs& kwargs = KeywordArgs());
461
+ c10::IValue operator()(
462
+ std::vector<c10::IValue>&& args,
463
+ const KeywordArgs& kwargs = KeywordArgs());
464
+
465
+ const Graph& graph() const {
466
+ return *graph_;
467
+ }
468
+
469
+ const Module& module() const {
470
+ DCHECK(module_.has_value());
471
+ return *module_;
472
+ }
473
+
474
+ const StaticModuleOptions& opts() const;
475
+
476
+ size_t num_inputs() const;
477
+ size_t num_outputs() const;
478
+
479
+ size_t num_constants() const {
480
+ return constants_.size();
481
+ }
482
+
483
+ size_t num_intermediate_values() const {
484
+ return num_intermediate_values_;
485
+ }
486
+
487
+ size_t total_num_values() const {
488
+ return num_inputs() + num_constants() + num_intermediate_values();
489
+ }
490
+
491
+ [[nodiscard]] const std::vector<uint16_t>& output_indices() const {
492
+ return output_indices_;
493
+ }
494
+
495
+ const std::vector<IValue>& constants() const {
496
+ return constants_;
497
+ }
498
+
499
+ const BlockInfo& block_info(Block* block) const {
500
+ return block_infos_.at(block);
501
+ }
502
+
503
+ Block* root_block() const {
504
+ return graph_->block();
505
+ }
506
+
507
+ private:
508
+ friend class StaticRuntime;
509
+ friend class BlockRunner;
510
+
511
+ public:
512
+ auto num_nodes() const {
513
+ return std::accumulate(
514
+ block_infos_.begin(),
515
+ block_infos_.end(),
516
+ 0,
517
+ [](size_t sum, const auto& block_and_info) {
518
+ auto& block_info = block_and_info.second;
519
+ return sum + block_info.num_nodes();
520
+ });
521
+ }
522
+
523
+ [[nodiscard]] Node* findNodeWithKindForTesting(const std::string& kind) const;
524
+
525
+ const std::optional<c10::FunctionSchema>& schema() const {
526
+ return schema_;
527
+ }
528
+
529
+ bool first_input_is_self() const {
530
+ return module_.has_value();
531
+ }
532
+
533
+ StaticRuntime& runtime();
534
+
535
+ // See [Shared values array]
536
+ size_t value_buffer_size() const {
537
+ return value_buffer_size_;
538
+ }
539
+
540
+ private:
541
+ // Recursively prepares the BlockInfo array.
542
+ // - Populates `value_to_index` with the indices of each intermediate value
543
+ // - Returns the number of Value* processed, including sub-blocks.
544
+ size_t prepareBlockInfo(
545
+ Block* block,
546
+ const size_t start_idx,
547
+ c10::FastMap<const Value*, uint32_t>& value_to_index);
548
+
549
+ void prepareFunctionsAndConstants(
550
+ Block* block,
551
+ const AliasDb& alias_db,
552
+ c10::FastMap<const Value*, uint32_t>& value_to_index);
553
+
554
+ // Recursively traverse the graph and attach SR metadata
555
+ // to the prim::fork nodes as additional attributes
556
+ void attachNodeMetadata(Block* block);
557
+
558
+ // Recurses on sub-blocks and populates the array of ProcessedNodes
559
+ // Returns (number of nodes processed, number of blocks processed)
560
+ size_t prepareStaticNodeInfos(
561
+ Block* block,
562
+ const c10::FastMap<const Value*, uint32_t>& value_to_index,
563
+ const AliasDb& alias_db,
564
+ size_t node_idx = 0);
565
+
566
+ // Initialize various attributes that the memory planner will need.
567
+ // To be called at the tail of the ctor.
568
+ void prepareForMemoryPlanner();
569
+
570
+ StaticModuleOptions opts_;
571
+ // metadata that is stored in IR nodes as attribute
572
+ at::intrusive_ptr<jit::StaticRuntimeMetadata> sr_metadata_;
573
+ std::shared_ptr<torch::jit::Graph> graph_;
574
+ std::optional<torch::jit::Module> module_;
575
+ std::optional<c10::FunctionSchema> schema_;
576
+ std::unique_ptr<StaticRuntime> cached_runtime_;
577
+
578
+ // Bookkeeping for creating new StaticRuntime instances
579
+ // IValue table (defined by prim::Constant nodes)
580
+ std::vector<IValue> constants_;
581
+ // The functions to be called by corresponding ProcessedNode.
582
+ std::vector<ProcessedFunction> functions_;
583
+ // A list of pre-processed nodes from which ProcessedNode are created per
584
+ // StaticRuntime instance.
585
+ std::vector<StaticNodeInfo> nodes_;
586
+ // Indices of graph outputs in the single values array.
587
+ std::vector<uint16_t> output_indices_;
588
+
589
+ size_t num_intermediate_values_ = 0;
590
+
591
+ // Includes self if module_ != std::nullopt.
592
+ // Note that we might have num_inputs_ == 0 even if the schema has a `self`
593
+ // argument. In this case, `self` isn't used in the graph, but the schema
594
+ // includes it anyways to be consistent with the JIT interpreter.
595
+ size_t num_inputs_;
596
+ // See `BlockInfo` definition. The blocks are stored in depth-first order.
597
+ c10::FastMap<Block*, BlockInfo> block_infos_;
598
+ size_t value_buffer_size_ = 0;
599
+ };
600
+
601
+ // `BlockRunner` contains the core runtime logic. Each block runner
602
+ // corresponds to one block in the graph and has its own memory planner.
603
+ // `StaticRuntime` will initialize all `BlockRunner`s
604
+ // upon construction. Each block runner only directly executes nodes from its
605
+ // block. Special ops with sub-blocks like `prim::If` may have
606
+ // `BlockRunner`s stored in their `ProcessedNode`s; these
607
+ // sub-blocks get executed in the op's implementation.
608
+ // `StaticRuntime` stores a vector of IValues that all
609
+ // `BlockRunner`s share. This vector is used to store all
610
+ // constants, inputs, and intermediate tensors.
611
+ class TORCH_API BlockRunner {
612
+ public:
613
+ BlockRunner(
614
+ const StaticModule& sm,
615
+ IValue* values,
616
+ Block* block,
617
+ torch::jit::TaskLauncher* launcher,
618
+ bool is_root_block = false);
619
+ BlockRunner(BlockRunner&&) noexcept;
620
+ BlockRunner& operator=(BlockRunner&&) = delete;
621
+ ~BlockRunner();
622
+
623
+ C10_DISABLE_COPY_AND_ASSIGN(BlockRunner);
624
+
625
+ using KeywordArgs = std::unordered_map<std::string, c10::IValue>;
626
+ c10::IValue operator()(
627
+ const std::vector<c10::IValue>& args,
628
+ const KeywordArgs& kwargs = KeywordArgs());
629
+ c10::IValue operator()(
630
+ std::vector<c10::IValue>&& args,
631
+ const KeywordArgs& kwargs = KeywordArgs());
632
+
633
+ c10::intrusive_ptr<c10::ivalue::Future> runAsync(
634
+ const std::vector<c10::IValue>& args,
635
+ const KeywordArgs& kwargs);
636
+
637
+ c10::intrusive_ptr<c10::ivalue::Future> runAsync(
638
+ std::vector<c10::IValue>&& args,
639
+ const KeywordArgs& kwargs);
640
+
641
+ void benchmark(
642
+ const std::vector<std::vector<c10::IValue>>& args_list,
643
+ const std::vector<KeywordArgs>& kwargs_list,
644
+ const uint32_t warmup_runs,
645
+ const uint32_t main_runs,
646
+ bool print_per_node_time = false,
647
+ bool generate_ai_pep_output = false);
648
+
649
+ struct IndividualMetrics {
650
+ float setup_time{0.0};
651
+ float memory_alloc_time{0.0};
652
+ float memory_dealloc_time{0.0};
653
+ float output_dealloc_time{0.0};
654
+ float first_iter_time{0.0};
655
+ float total_time{0.0};
656
+ size_t out_nodes_count{0};
657
+ size_t total_nodes_count{0};
658
+ std::vector<float> time_per_node;
659
+ std::unordered_map<std::string, float> time_per_node_type;
660
+ std::unordered_map<std::string, float> percent_per_node_type;
661
+ std::unordered_map<std::string, int> instances_per_node_type;
662
+ std::unordered_set<std::string> out_nodes;
663
+ std::unordered_set<std::string> native_nodes;
664
+ };
665
+
666
+ IndividualMetrics benchmark_individual_ops(
667
+ const std::vector<std::vector<c10::IValue>>& args_list,
668
+ const std::vector<KeywordArgs>& kwargs_list,
669
+ const uint32_t warmup_runs,
670
+ const uint32_t main_runs);
671
+
672
+ // Input is readwrite
673
+ IValue& Input(uint32_t i) {
674
+ TORCH_DCHECK_LT(i, block_info_.num_inputs());
675
+ return values_[i + block_info_.block_inputs_idx()];
676
+ }
677
+
678
+ // Output is readonly. The writing process happens inside ProcessedNodes
679
+ [[nodiscard]] const IValue& Output(uint32_t i) const {
680
+ DCHECK(i < outputs_.size());
681
+ return *outputs_[i];
682
+ }
683
+
684
+ const std::vector<IValue*> outputs() const {
685
+ return outputs_;
686
+ }
687
+
688
+ const std::vector<ProcessedNode>& nodes() const {
689
+ return nodes_;
690
+ }
691
+
692
+ std::vector<ProcessedNode>& nodes() {
693
+ return nodes_;
694
+ }
695
+
696
+ graph_node_list node_ptrs() const {
697
+ return block_info_.node_ptrs();
698
+ }
699
+
700
+ const Graph& graph() const {
701
+ return static_module_.graph();
702
+ }
703
+
704
+ const MemoryPlanner* get_memory_planner() const {
705
+ return planner_.get();
706
+ }
707
+
708
+ bool check_for_memory_leak(
709
+ bool output_returned = true,
710
+ bool recurse_on_sub_blocks = false);
711
+
712
+ // WARNING: Deallocate managed output tensors. A client receiving Static
713
+ // Runtime-managed Tensors needs to be very careful to call
714
+ // `StaticRuntime::deallocateOutputTensors` after all references of output
715
+ // Tensors are gone.
716
+ void deallocateOutputTensors();
717
+
718
+ bool checkOutputTensorMemoryLeaks();
719
+
720
+ bool isManagedOutputTensor(const IValue& ivalue) const;
721
+ bool isManagedOutputTensorValue(const Value* value) const;
722
+
723
+ void disableManageOutputTensors();
724
+
725
+ // This is the fallback path taken if we can't construct the memory planner
726
+ // on the first iteration.
727
+ // IMPORTANT: Nothing here should be able to throw!!!
728
+ // This function can be called from the (implicitly) `noexcept` destructor
729
+ // of Deallocator, meaning that std::terminate will be called
730
+ // if any exception escapes. Even if resetMemory and ~Deallocator were
731
+ // `noexcept(false)`, it's possible that when ~Deallocator is called, the
732
+ // stack is already unwinding, so there's still danger of calling
733
+ // std::terminate.
734
+ void resetMemory() noexcept;
735
+
736
+ private:
737
+ // A helper object that invokes memory planner deallocation code
738
+ // when destructed.
739
+ class Deallocator {
740
+ public:
741
+ explicit Deallocator(BlockRunner& block_runner)
742
+ : block_runner_(block_runner) {}
743
+
744
+ Deallocator(Deallocator&&) = default;
745
+ Deallocator(const Deallocator&) = default;
746
+ Deallocator& operator=(const Deallocator&) = delete;
747
+ Deallocator& operator=(Deallocator&&) = delete;
748
+ ~Deallocator();
749
+
750
+ void setFinished() {
751
+ finished_ = true;
752
+ }
753
+
754
+ private:
755
+ void cleanupImpl();
756
+
757
+ bool finished_ = false;
758
+ BlockRunner& block_runner_;
759
+ };
760
+
761
+ template <typename IValueList>
762
+ c10::IValue run_impl(IValueList&& args, const KeywordArgs& kwargs);
763
+
764
+ template <typename IValueList>
765
+ c10::IValue run_impl_record_functions(
766
+ IValueList&& args,
767
+ const KeywordArgs& kwargs);
768
+
769
+ template <typename IValueList>
770
+ c10::intrusive_ptr<c10::ivalue::Future> run_impl_async(
771
+ IValueList&& args,
772
+ const KeywordArgs& kwargs);
773
+
774
+ template <typename IValueList>
775
+ c10::intrusive_ptr<c10::ivalue::Future> run_impl_record_functions_async(
776
+ IValueList&& args,
777
+ const KeywordArgs& kwargs);
778
+
779
+ // helper method for copying input args/kwargs into inputs_
780
+ template <typename IValueList>
781
+ void set_inputs(IValueList&& args, const KeywordArgs& kwargs);
782
+
783
+ // Set Input(idx) to args[idx]. Invoked by set_inputs. Copies or moves
784
+ // depending on overload.
785
+ void set_arg(const size_t idx, std::vector<IValue>&& args);
786
+ void set_arg(const size_t idx, const std::vector<IValue>& args);
787
+
788
+ // Set Input(idx) to arg. Always copies. Used for kwargs.
789
+ void set_arg(const size_t idx, const IValue& arg);
790
+
791
+ bool fast_check_and_correct_overlap_with(
792
+ ProcessedNode& n,
793
+ c10::IValue& tensor_ival);
794
+ void verify_and_correct_memory_overlap(ProcessedNode& n);
795
+
796
+ // clean up owning refs of input IValues
797
+ void clean_up_input_ivalues() noexcept {
798
+ for (const auto idx : c10::irange(block_info_.num_inputs())) {
799
+ values_[idx + inputs_begin_] = IValue();
800
+ }
801
+ }
802
+
803
+ void clean_up_intermediate_ivalues() noexcept;
804
+
805
+ IValue move_outputs_to_tuple(uint32_t num_outputs);
806
+
807
+ void create_memory_planner();
808
+
809
+ float benchmark_model(
810
+ const std::vector<std::vector<c10::IValue>>& args_list,
811
+ const std::vector<KeywordArgs>& kwargs_list,
812
+ const uint32_t warmup_runs,
813
+ const uint32_t main_runs);
814
+
815
+ void display_nodes(
816
+ const std::vector<c10::IValue>& args,
817
+ const KeywordArgs& kwargs);
818
+
819
+ const StaticModule& static_module_;
820
+ const BlockInfo& block_info_;
821
+
822
+ const bool is_root_block_;
823
+ // Cache this so we don't have to call static_module_.first_input_is_self()
824
+ const bool first_input_is_self_;
825
+ // Index of the start of this blocks inputs in the shared values_ array.
826
+ const uint16_t inputs_begin_;
827
+
828
+ bool manage_output_tensors_enabled_ = false;
829
+ std::unique_ptr<MemoryPlanner> planner_;
830
+ // [Shared values array]
831
+ // ProcessedNodes reference their inputs and outputs with
832
+ // offsets into this array, which saves memory.
833
+ // All BlockRunners share the same array. The layout is as
834
+ // follows:
835
+ // [constants][block_0][block_1]...[block_N]
836
+ // Note that constants from all blocks are pooled together at the start.
837
+ // The block ordering is depth-first.
838
+ // Each block is further divided into inputs and intermediates:
839
+ // [block_i] = [inputs_i][intermediates_i]
840
+ // Each BlockRunner knows where its inputs start. Each ProcessedNode
841
+ // knows how to find the indices of its outputs/inputs in this array.
842
+ IValue* values_;
843
+
844
+ std::vector<IValue*> outputs_;
845
+ std::vector<ProcessedNode> nodes_;
846
+ };
847
+
848
+ inline size_t BlockInfo::num_nodes() const {
849
+ return nodes_.size();
850
+ }
851
+
852
+ /*
853
+ ProcessedNodeMetadata class wraps the possible metadata
854
+ for ProcessedNode. Depending upon the nature of op, processedNode
855
+ can have one of the below possibilities of metadata:
856
+ - prim::If/prim::Loop ops contains block_runners_ as their metadata
857
+ - prim::fork op contains TaskLauncher (std::function) responsible for
858
+ execution of forked subgraph
859
+ */
860
+ class TORCH_API ProcessedNodeMetadata {
861
+ public:
862
+ ProcessedNodeMetadata(
863
+ std::vector<BlockRunner> runners,
864
+ torch::jit::TaskLauncher* launcher)
865
+ : block_runners_(std::move(runners)), launcher_(launcher) {}
866
+
867
+ ProcessedNodeMetadata() : launcher_(nullptr) {}
868
+
869
+ // deleted copy ctor/assignment as standard containers (vector) always
870
+ // have copy constructors, but their instantiation is not well-formed
871
+ // if the contained type (BlockRunner) is not copyable
872
+ ProcessedNodeMetadata(const ProcessedNodeMetadata&) = delete;
873
+ ProcessedNodeMetadata& operator=(const ProcessedNodeMetadata&) = delete;
874
+ ProcessedNodeMetadata(ProcessedNodeMetadata&&) = delete;
875
+ ProcessedNodeMetadata&& operator=(ProcessedNodeMetadata&&) = delete;
876
+ ~ProcessedNodeMetadata() = default;
877
+
878
+ std::vector<BlockRunner>& block_runners() {
879
+ return block_runners_;
880
+ }
881
+
882
+ void set_block_runners(std::vector<BlockRunner> runners) {
883
+ block_runners_ = std::move(runners);
884
+ }
885
+
886
+ void set_launcher(torch::jit::TaskLauncher* launcher) {
887
+ launcher_ = launcher;
888
+ }
889
+
890
+ torch::jit::TaskLauncher* launcher() {
891
+ return launcher_;
892
+ }
893
+
894
+ private:
895
+ std::vector<BlockRunner> block_runners_;
896
+ torch::jit::TaskLauncher* launcher_;
897
+ };
898
+
899
+ class TORCH_API ProcessedNode {
900
+ public:
901
+ ProcessedNode() = default;
902
+
903
+ ProcessedNode(const StaticNodeInfo& other, IValue* values)
904
+ : node_(other.node_),
905
+ fn_(other.fn_),
906
+ inputs_(other.inputs_),
907
+ outputs_offset_(other.outputs_offset_),
908
+ values_(values),
909
+ metadata_(nullptr) {}
910
+
911
+ // These should be noexcept, but some Android build is failing
912
+ // saying the noexcept specification doesn't match the calculated
913
+ // one. Maybe std::variant is throwing it off?
914
+ ProcessedNode(ProcessedNode&&) = default;
915
+
916
+ ProcessedNode(const ProcessedNode&) = delete;
917
+ ProcessedNode& operator=(const ProcessedNode& other) = delete;
918
+ ProcessedNode& operator=(ProcessedNode&&) = default;
919
+ ~ProcessedNode() = default;
920
+
921
+ void run();
922
+
923
+ Node* node() const {
924
+ return node_;
925
+ }
926
+
927
+ // Input is readonly
928
+ [[nodiscard]] const IValue& Input(uint32_t i) const {
929
+ return values_[inputs_[i]];
930
+ }
931
+
932
+ // Output is readwrite
933
+ IValue& Output(uint32_t i) {
934
+ DCHECK(i < num_outputs());
935
+ return values_[outputs_offset_ + i];
936
+ }
937
+
938
+ [[nodiscard]] const IValue& Output(uint32_t i) const {
939
+ DCHECK(i < num_outputs());
940
+ return values_[outputs_offset_ + i];
941
+ }
942
+
943
+ uint32_t num_outputs() const {
944
+ DCHECK(fn_ != nullptr);
945
+ return static_cast<uint32_t>(fn_->num_outputs());
946
+ }
947
+
948
+ [[nodiscard]] c10::ArrayRef<const IValue> outputs() const {
949
+ return c10::ArrayRef<const IValue>(
950
+ values_ + outputs_offset_, num_outputs());
951
+ }
952
+
953
+ [[nodiscard]] uint16_t num_inputs() const {
954
+ return inputs_.size();
955
+ }
956
+
957
+ std::vector<IValue> inputs_ivalue_vec() const;
958
+
959
+ bool has_out_variant() const {
960
+ return fn_->kind() == ProcessedFunction::Kind::kOutVariant;
961
+ }
962
+
963
+ bool has_native() const {
964
+ return fn_->kind() == ProcessedFunction::Kind::kNativeFunction;
965
+ }
966
+
967
+ #ifndef PYTORCH_DISABLE_PER_OP_PROFILING
968
+ const char* get_op_name() const {
969
+ return node_->kind().toQualString();
970
+ }
971
+ #endif
972
+
973
+ bool check_outputs_for_memory_overlap() const {
974
+ return fn_->checkMemoryOverlap();
975
+ }
976
+
977
+ void set_outputs_memory_overlap_detected() {
978
+ overlap_detected_ = true;
979
+ }
980
+
981
+ bool outputs_memory_overlap_detected() {
982
+ return overlap_detected_;
983
+ }
984
+
985
+ bool check_and_correct_overlap_with(
986
+ const at::Tensor& input,
987
+ c10::IValue& output);
988
+ void verify_and_correct_memory_overlap();
989
+
990
+ void set_values(IValue* values) {
991
+ DCHECK(values_ == nullptr);
992
+ values_ = values;
993
+ }
994
+
995
+ [[nodiscard]] uint16_t output_ivalue_index(uint16_t i) const {
996
+ DCHECK(i < num_outputs());
997
+ return outputs_offset_ + i;
998
+ }
999
+ // used in debug mode
1000
+ bool verify_no_memory_overlap(bool force_check = false) const;
1001
+
1002
+ // returns pointer to ProcessedNodeMetadata or nullptr if no object is owned
1003
+ ProcessedNodeMetadata* metadata() {
1004
+ return metadata_.get();
1005
+ }
1006
+
1007
+ // attach block_runner to metadata of ProcessedNode
1008
+ void set_metadata(std::vector<BlockRunner> block_runners) {
1009
+ if (metadata_ == nullptr) {
1010
+ metadata_ = std::make_unique<ProcessedNodeMetadata>();
1011
+ }
1012
+ metadata_->set_block_runners(std::move(block_runners));
1013
+ }
1014
+
1015
+ // attach TaskLauncher to metadata of ProcessedNode
1016
+ void set_metadata(torch::jit::TaskLauncher* launcher) {
1017
+ if (metadata_ == nullptr) {
1018
+ metadata_ = std::make_unique<ProcessedNodeMetadata>();
1019
+ }
1020
+ metadata_->set_launcher(launcher);
1021
+ }
1022
+
1023
+ private:
1024
+ [[nodiscard]] bool verify_outputs_dont_overlap_each_other() const;
1025
+
1026
+ [[nodiscard]] bool verify_inputs_dont_overlap_outputs(bool force_check) const;
1027
+
1028
+ Node* node_{nullptr};
1029
+ const ProcessedFunction* fn_{nullptr};
1030
+ ProcessedNodeInputs inputs_;
1031
+ uint16_t outputs_offset_{0};
1032
+ bool overlap_detected_{false};
1033
+ IValue* values_ = nullptr; // unowned
1034
+ // Metadata for ProcessedNode.
1035
+ // 1. prim::If/Loop nodes contains sub-blocks as metadata
1036
+ // 2. prim::fork nodes contains custom executor for async execution
1037
+ std::unique_ptr<ProcessedNodeMetadata> metadata_;
1038
+ };
1039
+
1040
+ // `StaticRuntime` is the owner of the array of IValues (used for constants,
1041
+ // inputs, and intermediate tensors) that all `BlockRunner`s share.
1042
+ // Upon construction, it initializes all block runners. `operator()` simply
1043
+ // forwards the inputs to the top-level block runner. Each `StaticRuntime`
1044
+ // instance corresponds to one `StaticModule`. Multiple `StaticRuntime`
1045
+ // instances can be created; this is useful for multi-threaded execution, since
1046
+ // `operator()` is not thread-safe.
1047
+ class TORCH_API StaticRuntime {
1048
+ public:
1049
+ explicit StaticRuntime(const StaticModule& sm);
1050
+
1051
+ using KeywordArgs = std::unordered_map<std::string, c10::IValue>;
1052
+ c10::IValue operator()(
1053
+ const std::vector<c10::IValue>& args,
1054
+ const KeywordArgs& kwargs = KeywordArgs());
1055
+ c10::IValue operator()(
1056
+ std::vector<c10::IValue>&& args,
1057
+ const KeywordArgs& kwargs = KeywordArgs());
1058
+
1059
+ // runAsync performs inline execution of graph on
1060
+ // caller thread and async execution on taskLauncher
1061
+ // If no custom taskLauncher is specified, execution is done
1062
+ // on inter-op thread pool.
1063
+ c10::intrusive_ptr<c10::ivalue::Future> runAsync(
1064
+ const std::vector<c10::IValue>& args,
1065
+ const KeywordArgs& kwargs = KeywordArgs(),
1066
+ torch::jit::TaskLauncher taskLauncher = at::launch);
1067
+
1068
+ c10::intrusive_ptr<c10::ivalue::Future> runAsync(
1069
+ std::vector<c10::IValue>&& args,
1070
+ const KeywordArgs& kwargs = KeywordArgs(),
1071
+ torch::jit::TaskLauncher taskLauncher = at::launch);
1072
+
1073
+ bool check_for_memory_leak(bool output_returned = true);
1074
+ bool checkOutputTensorMemoryLeaks();
1075
+
1076
+ void deallocateOutputTensors();
1077
+ bool isManagedOutputTensor(const IValue& ivalue) const;
1078
+ void disableManageOutputTensors();
1079
+
1080
+ // Gets the top-level memory planner. Used for testing.
1081
+ const MemoryPlanner* get_memory_planner() const;
1082
+
1083
+ void benchmark(
1084
+ const std::vector<std::vector<c10::IValue>>& args_list,
1085
+ const std::vector<KeywordArgs>& kwargs_list,
1086
+ const uint32_t warmup_runs,
1087
+ const uint32_t main_runs,
1088
+ bool print_per_node_time = false,
1089
+ bool generate_ai_pep_output = false) {
1090
+ block_->benchmark(
1091
+ args_list,
1092
+ kwargs_list,
1093
+ warmup_runs,
1094
+ main_runs,
1095
+ print_per_node_time,
1096
+ generate_ai_pep_output);
1097
+ }
1098
+
1099
+ using IndividualMetrics = BlockRunner::IndividualMetrics;
1100
+
1101
+ IndividualMetrics benchmark_individual_ops(
1102
+ const std::vector<std::vector<c10::IValue>>& args_list,
1103
+ const std::vector<KeywordArgs>& kwargs_list,
1104
+ const int warmup_runs,
1105
+ const int main_runs) {
1106
+ return block_->benchmark_individual_ops(
1107
+ args_list, kwargs_list, warmup_runs, main_runs);
1108
+ }
1109
+
1110
+ private:
1111
+ // An array of IValues with unchanging size/data ptr.
1112
+ class IValueArray {
1113
+ public:
1114
+ IValueArray() = default;
1115
+ explicit IValueArray(size_t size) : array_(allocate(size)), size_(size) {}
1116
+
1117
+ IValue* data() const {
1118
+ return array_.get();
1119
+ }
1120
+
1121
+ size_t size() const {
1122
+ return size_;
1123
+ }
1124
+
1125
+ private:
1126
+ // NOLINTNEXTLINE(modernize-avoid-c-arrays)
1127
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
1128
+ static std::unique_ptr<IValue[]> allocate(size_t size) {
1129
+ if (size) {
1130
+ return std::make_unique<IValue[]>(size);
1131
+ }
1132
+ return nullptr;
1133
+ }
1134
+
1135
+ // NOLINTNEXTLINE(modernize-avoid-c-arrays)
1136
+ // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
1137
+ std::unique_ptr<IValue[]> array_ = nullptr;
1138
+ size_t size_ = 0;
1139
+ };
1140
+
1141
+ std::unique_ptr<BlockRunner> block_;
1142
+ // for execution of async operations present in graph
1143
+ torch::jit::TaskLauncher async_task_launcher_;
1144
+ IValueArray values_;
1145
+ };
1146
+
1147
+ } // namespace torch::jit
1148
+ C10_DECLARE_bool(static_runtime_disable_debug_memory_overlap_check);
1149
+
1150
+ #else
1151
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
1152
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/init.h ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #include <torch/csrc/jit/python/pybind_utils.h>
3
+
4
+ namespace torch::jit {
5
+
6
+ void initStaticModuleBindings(PyObject* module);
7
+
8
+ } // namespace torch::jit
9
+
10
+ #else
11
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
12
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/memory_planner.h ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/jit/runtime/static/impl.h>
5
+
6
+ namespace torch::jit {
7
+
8
+ // A StorageGroup represents a collection of tensors that share backing storage.
9
+ class StorageGroup {
10
+ public:
11
+ // Every storage group must contain at least one tensor.
12
+ explicit StorageGroup(at::Tensor* tensor) : group_{tensor} {}
13
+
14
+ void addTensor(at::Tensor* tensor) {
15
+ group_.push_back(tensor);
16
+ }
17
+
18
+ const std::vector<at::Tensor*>& group() const {
19
+ return group_;
20
+ }
21
+
22
+ size_t maxTensorSize() const {
23
+ return max_tensor_size_;
24
+ }
25
+
26
+ void setMaxTensorSize(size_t new_size) {
27
+ max_tensor_size_ = new_size;
28
+ }
29
+
30
+ size_t numManagedTensors() const {
31
+ return group_.size();
32
+ }
33
+
34
+ private:
35
+ // The size attribute represents the amount of memory that will be
36
+ // allocated for all tensors in this storage group. Initially it
37
+ // is zero, eventually it gets updated by the MemoryPlanner.
38
+ size_t max_tensor_size_ = 0;
39
+ std::vector<at::Tensor*> group_;
40
+ };
41
+
42
+ // A contiguous buffer of `StorageImpl`s
43
+ class ManagedStorages {
44
+ public:
45
+ ManagedStorages();
46
+
47
+ ~ManagedStorages();
48
+
49
+ void allocate(size_t capacity);
50
+
51
+ void deallocate();
52
+
53
+ bool is_allocated() const {
54
+ return storages_ != nullptr;
55
+ }
56
+
57
+ // Append a new StorageImpl to the buffer. The new StorageImpl is given the
58
+ // same size and allocator as `storageImpl` argument
59
+ void append(at::StorageImpl& storageImpl);
60
+
61
+ at::StorageImpl& operator[](size_t idx) {
62
+ TORCH_INTERNAL_ASSERT(storages_ != nullptr);
63
+ return storages_[idx];
64
+ }
65
+
66
+ const at::StorageImpl& operator[](size_t idx) const {
67
+ TORCH_INTERNAL_ASSERT(storages_ != nullptr);
68
+ return storages_[idx];
69
+ }
70
+
71
+ size_t size() const {
72
+ return size_;
73
+ }
74
+
75
+ bool empty() const {
76
+ return size_ == 0;
77
+ }
78
+
79
+ size_t capacity() const {
80
+ return capacity_;
81
+ }
82
+
83
+ private:
84
+ // We will use placement-new to add new storages to this buffer
85
+ at::StorageImpl* storages_{nullptr};
86
+
87
+ // Current number of storages that have been placed into the storage buffer
88
+ size_t size_{0};
89
+
90
+ // Total allocated capacity of the storage buffer
91
+ size_t capacity_{0};
92
+ };
93
+
94
+ TORCH_API std::vector<StorageGroup> assignStorageToManagedTensors(
95
+ graph_node_list nodes,
96
+ const ManagedTensorRanges& ranges,
97
+ const c10::FastMap<const Value*, at::Tensor*>& tensor_value_to_tensor);
98
+
99
+ // There are three types of ops in a processed graph in Static Runtime:
100
+ // 1. op with _out variant
101
+ // 2. view-producing op
102
+ // 3. tensor-producing op (could be replaced with type 1 by adding the _out
103
+ // variant to Static Runtime)
104
+ // In Static Runtime, type 2 ops are replaced with their corresponding copy
105
+ // versions when enable_out_variant is enabled and become type 1 ops.The memory
106
+ // planner only manages tensors that are outputs of type 1 ops. For type 3, the
107
+ // output tensors are allocated inside the operator and can't be directly
108
+ // managed by memory planner.
109
+ //
110
+ // Memory planner tries to minimize the number of memory allocations by
111
+ // tracking the output tensors of ops with _out variants with unique DataPtr
112
+ // (part of StorageImpl). It tries to do this in several steps:
113
+ // 1. record the max memory usage for each Tensor with unique DataPtr at the
114
+ // end of each iteration
115
+ // 2. in the next iteration, allocate the buffer for the max total usage and
116
+ // compute the offset of each allocation with regard to the single memory
117
+ // buffer, optionally reusing memory. In the first iteration, we rely on
118
+ // the default allocator for memory allocation.
119
+ // 3. free the buffer at the end of each iteration
120
+ // Steps 1 and 3 are handled by `deallocate()`, and step 2 by `allocate()`.
121
+ // Only models with simple output types are supported, i.e. None, Tensor or
122
+ // List/Tuple/Dict of Tensors. Complex output types such as List of Lists are
123
+ // not supported.
124
+ //
125
+ // Additional Optimizations:
126
+ //
127
+ // [Borrowed IValue Outputs]
128
+ // A few native ops (notably, `static_runtime::dict_unpack` and
129
+ // `static_runtime::VarTupleUnpack`) simply unpack IValues to a bunch of
130
+ // outputs without modification. For example, `dict_unpack` does the following:
131
+ // for each key in inputs:
132
+ // output[i] = dict_input[key]
133
+ // To avoid refcount bumps, the outputs of these ops are non-owning references.
134
+ // This requires special logic in the memory planner - when adding an op that
135
+ // borrows outputs, be sure that the memory planner is updated accordingly!
136
+ //
137
+ // [Managed Output Tensors]
138
+ // The memory planner is able to manage output tensors if the appropriate
139
+ // `StaticModuleOptions` are set. However, the memory planner handles output
140
+ // tensors separately from regular intermediate tensors:
141
+ // 1. They don't participate in memory reuse.
142
+ // 2. The memory planner cannot reclaim their backing storage until they have
143
+ // been explicitly freed by the client.
144
+
145
+ class MemoryPlanner {
146
+ public:
147
+ MemoryPlanner(
148
+ BlockRunner* block_runner,
149
+ const BlockInfo& block_info,
150
+ bool enable_out_variant,
151
+ bool manage_output_tensors);
152
+
153
+ // disable copying and moving
154
+ MemoryPlanner(const MemoryPlanner&) = delete;
155
+ MemoryPlanner& operator=(const MemoryPlanner&) = delete;
156
+ MemoryPlanner(MemoryPlanner&&) = delete;
157
+ MemoryPlanner& operator=(MemoryPlanner&&) = delete;
158
+ virtual ~MemoryPlanner() = default;
159
+
160
+ void allocate();
161
+ void deallocate();
162
+ void deallocateOutputTensors();
163
+
164
+ size_t total_num_managed_tensors() const {
165
+ return num_managed_tensors_;
166
+ }
167
+
168
+ size_t total_reused_tensors() const {
169
+ return reused_tensors_;
170
+ }
171
+
172
+ size_t total_num_managed_output_tensors() const {
173
+ return managed_output_tensors_.size();
174
+ }
175
+
176
+ [[nodiscard]] size_t total_num_unmanaged() const {
177
+ return num_unmanaged_non_scalars() + num_unmanaged_scalars();
178
+ }
179
+
180
+ [[nodiscard]] size_t num_unmanaged_non_scalars() const {
181
+ return unmanaged_ivalues_.size() + unmanaged_borrowed_ivalues_.size();
182
+ }
183
+
184
+ [[nodiscard]] size_t num_unmanaged_scalars() const {
185
+ return num_unmanaged_scalar_ivalues_;
186
+ }
187
+
188
+ size_t total_managed() const {
189
+ return managed_bytes_;
190
+ }
191
+
192
+ size_t numOutputBufferBytes() const {
193
+ return output_buffer_bytes_;
194
+ }
195
+
196
+ // Check if `ivalue` is contained as a managed tensor. Only used in DCHECK().
197
+ bool isManagedOutputTensor(const IValue& ivalue) const {
198
+ if (!output_buffer_ || // output buffer got already deallocated.
199
+ output_buffer_bytes_ == 0 || // memory planning is not yet initialized.
200
+ !ivalue.isTensor() // a non-tensor is never managed
201
+ ) {
202
+ return false;
203
+ }
204
+ const auto& tensor = ivalue.toTensor();
205
+ if (!tensor.has_storage() || !tensor.storage().data_ptr()) {
206
+ return false;
207
+ }
208
+ // TODO: Improve this once D31357486 is landed.
209
+ uint8_t* tensor_ptr =
210
+ static_cast<uint8_t*>(tensor.storage().data_ptr().get());
211
+ uint8_t* buffer_start = static_cast<uint8_t*>(output_buffer_.get());
212
+ uint8_t* buffer_end = buffer_start + output_buffer_bytes_;
213
+ return buffer_start <= tensor_ptr && tensor_ptr < buffer_end;
214
+ }
215
+
216
+ bool isManagedStorageImpl(const at::StorageImpl* impl) const {
217
+ if (storages_.empty()) {
218
+ return false;
219
+ }
220
+ // Comparing pointers that aren't within the same array is
221
+ // UB. We're doing fancy memory allocation stuff, so we cast to an
222
+ // integer type and carry on.
223
+ const auto impl_p = reinterpret_cast<uintptr_t>(impl);
224
+ const auto start = reinterpret_cast<uintptr_t>(&storages_[0]);
225
+ const auto end =
226
+ reinterpret_cast<uintptr_t>(&storages_[0] + storages_.size());
227
+ return impl_p >= start && impl_p < end;
228
+ }
229
+
230
+ bool overlapWithInternalBuffer(void* data_ptr) {
231
+ return buffer_start_ <= data_ptr && data_ptr < buffer_end_;
232
+ }
233
+
234
+ protected:
235
+ uint8_t* allocateBuffer(size_t num_bytes);
236
+
237
+ size_t managed_bytes_{0};
238
+ size_t reused_tensors_{0};
239
+
240
+ // We allocate StorageImpls ourselves so that 1) we don't have to do
241
+ // an extra two loads per Tensor (which will likely miss in the CPU
242
+ // data cache) first reading the Storage (i.e., StorageImpl pointer)
243
+ // from the TensorImpl object and then second dereferencing it and
244
+ // 2) our memory access pattern during allocate() has high locality.
245
+ // We don't have any guarantee that the model doesn't change the
246
+ // Storage for managed tensors out from under us during execution,
247
+ // so we have to check the StorageImpls each time we deallocate.
248
+ ManagedStorages storages_;
249
+
250
+ // Contains the size (in bytes) of the data to be allocated for each storage
251
+ std::vector<size_t> storages_nbytes_;
252
+
253
+ private:
254
+ // ivalues created in one run but not managed by MemoryPlanner
255
+ std::vector<IValue*> unmanaged_ivalues_;
256
+
257
+ // Special class of unmanaged values: some native ops create IValues
258
+ // in a "borrowed" state that can and must be cleaned up without a
259
+ // reference count decrement.
260
+ std::vector<IValue*> unmanaged_borrowed_ivalues_;
261
+
262
+ // Even more special class of unmanaged values: if select_tensor
263
+ // outputs are outputs of the graph, then they need to be restored
264
+ // to an ordinary "strong reference" state.
265
+ std::vector<IValue*> borrowed_ivalues_needing_incref_;
266
+
267
+ std::vector<std::pair<size_t, at::Tensor*>> managed_output_tensors_;
268
+ at::DataPtr buffer_; // allocated each time we call Run()
269
+ uint8_t* buffer_start_{nullptr};
270
+ uint8_t* buffer_end_{nullptr};
271
+ size_t num_managed_tensors_{0};
272
+ size_t num_unmanaged_scalar_ivalues_{0};
273
+
274
+ at::DataPtr output_buffer_;
275
+ size_t output_buffer_bytes_{0};
276
+
277
+ virtual void allocateManagedTensors() = 0;
278
+ virtual void deallocateManagedTensors() = 0;
279
+
280
+ void allocateOutputTensors();
281
+ };
282
+
283
+ class StandardMemoryPlanner : public MemoryPlanner {
284
+ public:
285
+ StandardMemoryPlanner(
286
+ BlockRunner* block_runner,
287
+ const BlockInfo& block_info,
288
+ bool enable_out_variant,
289
+ bool manage_output_tensors,
290
+ bool optimize_memory);
291
+
292
+ protected:
293
+ void allocateManagedTensors() override;
294
+ void deallocateManagedTensors() override;
295
+
296
+ std::vector<StorageGroup> managed_tensors_;
297
+ };
298
+
299
+ } // namespace torch::jit
300
+
301
+ #else
302
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
303
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/ops.h ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <ATen/Utils.h>
5
+ #include <torch/csrc/jit/ir/ir.h>
6
+ #include <torch/csrc/jit/runtime/static/impl.h>
7
+
8
+ namespace at::native {
9
+ at::Tensor& reshape_copy_out(
10
+ at::Tensor& out,
11
+ const at::Tensor& self,
12
+ const at::DimVector& proposed_shape,
13
+ bool infer_size = true);
14
+ at::Tensor& to_copy_out(
15
+ Tensor& out,
16
+ const Tensor& self,
17
+ bool non_blocking,
18
+ bool copy_strides,
19
+ std::optional<MemoryFormat> memory_format);
20
+ } // namespace at::native
21
+
22
+ namespace torch::jit {
23
+
24
+ using SROpFunctor = SROperator (*)(Node* n);
25
+ struct SROperatorFunctor {
26
+ virtual SROperator Generate(Node* /*unused*/) {
27
+ SROperator out;
28
+ return out;
29
+ }
30
+ virtual ~SROperatorFunctor() = default;
31
+ };
32
+
33
+ TORCH_DECLARE_REGISTRY(SROperatorRegistry, SROperatorFunctor);
34
+
35
+ #define REGISTER_OPERATOR_FUNCTOR(name, id, ...) \
36
+ struct SROperatorFunctor_##id : public SROperatorFunctor { \
37
+ SROpFunctor fn = __VA_ARGS__; \
38
+ SROperator Generate(Node* n) override { \
39
+ return fn(n); \
40
+ } \
41
+ }; \
42
+ C10_REGISTER_CLASS(SROperatorRegistry, name, SROperatorFunctor_##id)
43
+
44
+ TORCH_DECLARE_REGISTRY(SRNativeOperatorRegistry, SROperatorFunctor);
45
+ #define REGISTER_NATIVE_OPERATOR_FUNCTOR(name, id, ...) \
46
+ struct SRNativeOperatorFunctor_##id : public SROperatorFunctor { \
47
+ SROpFunctor fn = __VA_ARGS__; \
48
+ SROperator Generate(Node* n) override { \
49
+ return fn(n); \
50
+ } \
51
+ }; \
52
+ C10_REGISTER_CLASS( \
53
+ SRNativeOperatorRegistry, name, SRNativeOperatorFunctor_##id)
54
+
55
+ inline at::Tensor create_empty_from(const at::Tensor& t) {
56
+ return at::detail::empty_cpu(
57
+ {0},
58
+ c10::typeMetaToScalarType(t.dtype()),
59
+ t.layout(),
60
+ t.device(),
61
+ std::nullopt,
62
+ std::nullopt);
63
+ }
64
+
65
+ inline at::Tensor create_empty_from(
66
+ at::IntArrayRef sizes,
67
+ const at::Tensor& t) {
68
+ return at::detail::empty_cpu(
69
+ sizes,
70
+ c10::typeMetaToScalarType(t.dtype()),
71
+ t.layout(),
72
+ t.device(),
73
+ std::nullopt,
74
+ std::nullopt);
75
+ }
76
+
77
+ inline at::Tensor create_empty(c10::ScalarType dtype) {
78
+ return at::detail::empty_cpu(
79
+ {0}, dtype, std::nullopt, std::nullopt, std::nullopt, std::nullopt);
80
+ }
81
+
82
+ inline at::Tensor create_empty_from(
83
+ const at::Tensor& t,
84
+ c10::ScalarType dtype) {
85
+ return at::detail::empty_cpu(
86
+ {0}, dtype, t.layout(), t.device(), std::nullopt, std::nullopt);
87
+ }
88
+
89
+ inline at::Tensor create_empty_from(const at::Tensor& t, c10::Layout layout) {
90
+ return at::detail::empty_cpu(
91
+ {0},
92
+ c10::typeMetaToScalarType(t.dtype()),
93
+ layout,
94
+ t.device(),
95
+ std::nullopt,
96
+ std::nullopt);
97
+ }
98
+
99
+ inline at::Tensor create_empty_from(const at::Tensor& t, c10::Device device) {
100
+ return at::detail::empty_cpu(
101
+ {0},
102
+ c10::typeMetaToScalarType(t.dtype()),
103
+ t.layout(),
104
+ device,
105
+ std::nullopt,
106
+ std::nullopt);
107
+ }
108
+
109
+ inline at::Tensor create_empty_from(
110
+ const at::Tensor& t,
111
+ c10::MemoryFormat memory_format) {
112
+ return at::detail::empty_cpu(
113
+ {0},
114
+ c10::typeMetaToScalarType(t.dtype()),
115
+ t.layout(),
116
+ t.device(),
117
+ std::nullopt,
118
+ memory_format);
119
+ }
120
+
121
+ inline at::Tensor create_empty_from(
122
+ const at::Tensor& t,
123
+ c10::ScalarType dtype,
124
+ c10::MemoryFormat memory_format) {
125
+ return at::detail::empty_cpu(
126
+ {0}, dtype, t.layout(), t.device(), std::nullopt, memory_format);
127
+ }
128
+
129
+ inline bool checkResizedDataPtr(at::Tensor& t) {
130
+ auto const prev_data_ptr = t.data_ptr();
131
+ t.resize_({0});
132
+ return prev_data_ptr == t.data_ptr();
133
+ }
134
+
135
+ inline void fastResizeToZero(at::Tensor& t) {
136
+ t.unsafeGetTensorImpl()->set_sizes_contiguous({0});
137
+ TORCH_INTERNAL_ASSERT_DEBUG_ONLY(checkResizedDataPtr(t));
138
+ }
139
+
140
+ // check if an op has an out variant registered in Static Runtime
141
+ bool opIsRegistered(const c10::Symbol& op_name);
142
+ // check if Static Runtime can run an op natively.
143
+ // prim ops that are implemented directly in the jit interpreter are implemented
144
+ // as native ops in Static Runtime
145
+ bool nativeOpIsRegistered(const c10::Symbol& op_name);
146
+
147
+ bool canReuseInputsOutputs(
148
+ Node* n,
149
+ const c10::FastMap<Node*, bool>& node_has_out_variant);
150
+ bool isOptimizableContainerType(
151
+ Node* n,
152
+ const c10::FastMap<Node*, bool>& node_has_out_variant);
153
+
154
+ SROperator getOutOfPlaceOperation(Node* n);
155
+ SROperator getNativeOperation(Node* n);
156
+
157
+ bool hasVarArgs(Node* n);
158
+
159
+ inline std::string PrintNode(const Node* node) {
160
+ std::ostringstream ss;
161
+ node->print(ss, 0, nullptr, false);
162
+ return ss.str();
163
+ }
164
+
165
+ inline void LogAndDumpSchema(const Node* node) {
166
+ VLOG(1) << "Found schema mismatch for: " << node->schema();
167
+ }
168
+
169
+ inline bool sr_schema_check(torch::jit::Node* /*unused*/) {
170
+ return true;
171
+ }
172
+
173
+ template <typename Schema, typename... Schemas>
174
+ bool sr_schema_check(
175
+ torch::jit::Node* node,
176
+ Schema&& first,
177
+ Schemas&&... rest) {
178
+ auto is_match = node->matches(first) || sr_schema_check(node, rest...);
179
+ if (!is_match) {
180
+ torch::jit::LogAndDumpSchema(node);
181
+ }
182
+ return is_match;
183
+ }
184
+
185
+ bool sr_schema_check_kind(torch::jit::Node* node, c10::Symbol node_kind);
186
+ } // namespace torch::jit
187
+
188
+ C10_DECLARE_bool(static_runtime_enable_fast_math);
189
+
190
+ #else
191
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
192
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/passes.h ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #include <torch/csrc/jit/ir/ir.h>
3
+
4
+ namespace torch::jit {
5
+
6
+ TORCH_API void FuseInferenceOpsForSparseNN(
7
+ std::shared_ptr<torch::jit::Graph>& graph);
8
+
9
+ TORCH_API void EliminateTrivialEquallySplit(
10
+ std::shared_ptr<torch::jit::Graph>& graph);
11
+
12
+ TORCH_API void FuseListUnpack(std::shared_ptr<torch::jit::Graph>& graph);
13
+
14
+ // If outputs_are_immutable is set to false, don't replace the view ops that
15
+ // produce aliases of graph outputs with the copy version.
16
+ TORCH_API void ReplaceWithCopy(
17
+ std::shared_ptr<torch::jit::Graph>& graph,
18
+ bool outputs_are_immutable = true);
19
+
20
+ TORCH_API void ReplacePermuteWithCopy(
21
+ std::shared_ptr<torch::jit::Graph>& graph,
22
+ bool outputs_are_immutable = true);
23
+
24
+ TORCH_API void ReplaceWithMaybeCopy(
25
+ std::shared_ptr<torch::jit::Graph>& graph,
26
+ bool outputs_are_immutable = true);
27
+
28
+ TORCH_API void RemoveImmutableInputDictLookups(
29
+ std::shared_ptr<torch::jit::Graph>& graph);
30
+
31
+ TORCH_API bool graphHasOp(std::shared_ptr<Graph>& graph, const char* op_name);
32
+
33
+ TORCH_API bool forwardHasOp(const Module& module, const char* op_name);
34
+
35
+ TORCH_API void FuseSignLog1P(std::shared_ptr<Graph>& graph);
36
+
37
+ TORCH_API void UseVariadicTupleUnpack(const std::shared_ptr<Graph>& graph);
38
+
39
+ // c10::Symbol::fromQualString is a bit long to type everywhere, and
40
+ // we can't use a `using` statement since it's a static class function.
41
+ inline c10::Symbol fromQualString(const std::string& qual_string) {
42
+ return c10::Symbol::fromQualString(qual_string);
43
+ }
44
+
45
+ // [Create owned refs for special values]
46
+ // StaticRuntimeBlockRunner moves its outputs to the return value at the end of
47
+ // run_impl. However, there's a corner case where this can cause problems. If
48
+ // we return a constant, then the only reference in the constants_ array can
49
+ // be destroyed by this move.
50
+ // We could add special logic to handle this in run_impl. But since this is a
51
+ // relatively rare corner case, it's simpler to just add an op that does nothing
52
+ // but create an owned reference to its input. This owned reference can be
53
+ // safely moved out of StaticRuntimeBlockRunner. Note that for scalars,
54
+ // this actually does a copy.
55
+ // Note that we have to do the same thing if we are returning a value from an
56
+ // outer scope in a sub-block.
57
+ TORCH_API void CreateOwnedRefsForSpecialValues(Graph& graph);
58
+
59
+ // [Force non-empty outputs]
60
+ // It is technically possible for sub-blocks to not return anything. This is
61
+ // problematic for StaticRuntimeBlockRunner because it assumes that at least one
62
+ // output is being returned. Rather than slowing down SR with special logic for
63
+ // this corner case, we simply force blocks that return nothing to return None.
64
+ TORCH_API void ForceNonEmptyOutputs(Graph& graph);
65
+
66
+ TORCH_API void UseVariadicGroupedAccessor(const std::shared_ptr<Graph>& graph);
67
+
68
+ TORCH_API void EliminateExtraPermuteOps(std::shared_ptr<Graph>& graph);
69
+
70
+ TORCH_API void EliminateNoOpSlice(std::shared_ptr<Graph>& graph);
71
+
72
+ TORCH_API void UseSplitAndSqueeze(std::shared_ptr<Graph>& graph);
73
+
74
+ // [Remove unnecessary outputs]]
75
+ // Removes outputs to reduce compute when it is not used later in the graph.
76
+ // Currently used to remove the max_indices output of embedding_bag, which
77
+ // isn't necessary to compute the main output.
78
+ TORCH_API void RemoveUnnecessaryOutputs(std::shared_ptr<Graph>& graph);
79
+
80
+ TORCH_API void RemoveUnnecessaryEmbeddingBagOutputs(
81
+ std::shared_ptr<Graph>& graph);
82
+
83
+ TORCH_API void FuseClampNaNToNum(std::shared_ptr<Graph>& graph);
84
+
85
+ TORCH_API void UseInPlaceGetRealInputsFromOptionalInputsV2(
86
+ std::shared_ptr<Graph>& graph);
87
+
88
+ TORCH_API void PrepackWeights(std::shared_ptr<Graph>& graph);
89
+
90
+ } // namespace torch::jit
91
+
92
+ C10_DECLARE_bool(enable_clip_ranges_gather_fusions);
93
+
94
+ #else
95
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
96
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/processed_node_wrapper.h ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <ATen/ATen.h>
5
+ #include <torch/csrc/jit/runtime/static/impl.h>
6
+
7
+ namespace torch::jit {
8
+
9
+ // The following class facilitates code reuse between ProcessedNodeInputWrapper
10
+ // and ProcessedNodeOutputWrapper via CRTP
11
+ template <typename DerivedWrapper>
12
+ class ProcessedNodeWrapperBase {
13
+ public:
14
+ class ProcessedNodeWrapperBaseIter {
15
+ public:
16
+ using iterator_category = std::forward_iterator_tag;
17
+ using value_type = at::Tensor;
18
+ using difference_type = size_t;
19
+ using pointer = const at::Tensor*;
20
+ using reference = const at::Tensor&;
21
+
22
+ ProcessedNodeWrapperBaseIter() = default;
23
+
24
+ ProcessedNodeWrapperBaseIter(
25
+ const DerivedWrapper* container,
26
+ size_t start_idx)
27
+ : container_(container), idx_(start_idx) {}
28
+
29
+ ProcessedNodeWrapperBaseIter& operator++() {
30
+ TORCH_DCHECK_NE(idx_, container_->size());
31
+ ++idx_;
32
+ return *this;
33
+ }
34
+
35
+ ProcessedNodeWrapperBaseIter operator++(int) {
36
+ ProcessedNodeWrapperBaseIter old = *this;
37
+ ++(*this);
38
+ return old;
39
+ }
40
+
41
+ reference operator*() const {
42
+ TORCH_CHECK(container_ != nullptr);
43
+ return (*container_)[idx_];
44
+ }
45
+
46
+ pointer operator->() const {
47
+ TORCH_CHECK(container_ != nullptr);
48
+ return &(*container_)[idx_];
49
+ }
50
+
51
+ friend bool operator==(
52
+ ProcessedNodeWrapperBaseIter lhs,
53
+ ProcessedNodeWrapperBaseIter rhs) {
54
+ TORCH_DCHECK_EQ(lhs.container_, rhs.container_);
55
+ return lhs.idx_ == rhs.idx_;
56
+ }
57
+
58
+ friend bool operator!=(
59
+ ProcessedNodeWrapperBaseIter lhs,
60
+ ProcessedNodeWrapperBaseIter rhs) {
61
+ return !(lhs == rhs);
62
+ }
63
+
64
+ private:
65
+ const DerivedWrapper* container_ = nullptr;
66
+ size_t idx_ = 0;
67
+ };
68
+
69
+ // NB: to mimic the behavior of at::ArrayRef, both iterators are
70
+ // the const version.
71
+ using iterator = ProcessedNodeWrapperBaseIter;
72
+ using const_iterator = ProcessedNodeWrapperBaseIter;
73
+ using size_type = size_t;
74
+ using value_type = at::Tensor;
75
+
76
+ explicit ProcessedNodeWrapperBase(ProcessedNode& pnode) : pnode_(pnode) {}
77
+
78
+ iterator begin() {
79
+ return ProcessedNodeWrapperBaseIter(static_cast<DerivedWrapper*>(this), 0);
80
+ }
81
+ iterator end() {
82
+ return ProcessedNodeWrapperBaseIter(
83
+ static_cast<DerivedWrapper*>(this),
84
+ static_cast<DerivedWrapper*>(this)->size());
85
+ }
86
+
87
+ const_iterator begin() const {
88
+ return ProcessedNodeWrapperBaseIter(
89
+ static_cast<const DerivedWrapper*>(this), 0);
90
+ }
91
+ const_iterator end() const {
92
+ return ProcessedNodeWrapperBaseIter(
93
+ static_cast<const DerivedWrapper*>(this),
94
+ static_cast<const DerivedWrapper*>(this)->size());
95
+ }
96
+
97
+ const_iterator cbegin() const {
98
+ return ProcessedNodeWrapperBaseIter(
99
+ static_cast<const DerivedWrapper*>(this), 0);
100
+ }
101
+ const_iterator cend() const {
102
+ return ProcessedNodeWrapperBaseIter(
103
+ static_cast<const DerivedWrapper*>(this),
104
+ static_cast<const DerivedWrapper*>(this)->size());
105
+ }
106
+
107
+ bool empty() const {
108
+ return static_cast<const DerivedWrapper*>(this)->size() == 0;
109
+ }
110
+
111
+ protected:
112
+ ProcessedNode& pnode_;
113
+ };
114
+
115
+ // A ProcessedNodeWrapperBase lets us use ProcessedNode directly in a context
116
+ // where a container of IValues is expected. This trick is handy for avoiding
117
+ // refcount bumps in perf-sensitive native ops. For example, suppose we have an
118
+ // op that takes a list of tensors as an argument and we've turned the op into a
119
+ // variadic variant in static runtime. To use the PyTorch library implementation
120
+ // of the op, we would have to pack the variadic arguments into a list:
121
+ // std::vector<Tensor> tensor_list;
122
+ // tensor_list.reserve(pnode->num_outputs());
123
+ // for (const auto i : c10::irange(pnode->num_inputs())
124
+ // tensor_list.push_back(pnode->Input(i).toTensor());
125
+ // op_impl(tensor_list);
126
+ // Using ProcessedNodeWrapperBase, we can avoid this round of refcount bumps.
127
+ // All we need to do is turn `op_impl` into a template and pass it
128
+ // ProcessedNodeInputWrapper(*pnode)!
129
+ class ProcessedNodeInputWrapper
130
+ : public ProcessedNodeWrapperBase<ProcessedNodeInputWrapper> {
131
+ public:
132
+ // The last `back_elements_ignored` elements are not considered.
133
+ // Same for the first `front_elements_ignored` elements.
134
+ // This is useful for ops where
135
+ // only the first N elements are tensors (N < inputs.size()).
136
+ // For instance, the last argument to VarStack is an integer dimension.
137
+ explicit ProcessedNodeInputWrapper(
138
+ ProcessedNode& pnode,
139
+ size_t front_elements_ignored = 0,
140
+ size_t back_elements_ignored = 1)
141
+ : ProcessedNodeWrapperBase<ProcessedNodeInputWrapper>(pnode),
142
+ front_elements_ignored_(front_elements_ignored),
143
+ back_elements_ignored_(back_elements_ignored) {
144
+ TORCH_CHECK(front_elements_ignored_ <= pnode_.num_inputs());
145
+ TORCH_CHECK(
146
+ back_elements_ignored_ <=
147
+ pnode_.num_inputs() - front_elements_ignored_);
148
+ }
149
+
150
+ size_t size() const {
151
+ return pnode_.num_inputs() - back_elements_ignored_ -
152
+ front_elements_ignored_;
153
+ }
154
+
155
+ const at::Tensor& operator[](size_t idx) const {
156
+ TORCH_CHECK(idx < size());
157
+ return pnode_.Input(front_elements_ignored_ + idx).toTensor();
158
+ }
159
+
160
+ const at::Tensor& front() const {
161
+ TORCH_CHECK(
162
+ !empty(),
163
+ "Attempted to access front() of empty ProcessedNodeInputWrapper");
164
+ return pnode_.Input(front_elements_ignored_).toTensor();
165
+ }
166
+
167
+ const at::Tensor& back() const {
168
+ TORCH_CHECK(
169
+ !empty(),
170
+ "Attempted to access back() of empty ProcessedNodeInputWrapper");
171
+ return pnode_.Input(pnode_.num_inputs() - back_elements_ignored_ - 1)
172
+ .toTensor();
173
+ }
174
+
175
+ private:
176
+ size_t front_elements_ignored_;
177
+ size_t back_elements_ignored_;
178
+ };
179
+
180
+ // Similar to ProcessedNodeInputWrapper, but wraps outputs and allows for
181
+ // writing.
182
+ class ProcessedNodeOutputWrapper
183
+ : public ProcessedNodeWrapperBase<ProcessedNodeOutputWrapper> {
184
+ public:
185
+ using ProcessedNodeWrapperBase<
186
+ ProcessedNodeOutputWrapper>::ProcessedNodeWrapperBase;
187
+
188
+ size_t size() const {
189
+ return pnode_.num_outputs();
190
+ }
191
+
192
+ at::Tensor& operator[](size_t idx) const {
193
+ TORCH_CHECK(idx < size());
194
+ return pnode_.Output(idx).toTensor();
195
+ }
196
+
197
+ at::Tensor& front() const {
198
+ TORCH_CHECK(
199
+ !empty(),
200
+ "Attempted to access front() of empty ProcessedNodeOutputWrapper");
201
+ return pnode_.Output(0).toTensor();
202
+ }
203
+
204
+ at::Tensor& back() const {
205
+ TORCH_CHECK(
206
+ !empty(),
207
+ "Attempted to access back() of empty ProcessedNodeOutputWrapper");
208
+ return pnode_.Output(size() - 1).toTensor();
209
+ }
210
+ };
211
+
212
+ } // namespace torch::jit
213
+
214
+ #else
215
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
216
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/static_method.h ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/api/include/torch/imethod.h>
5
+ #include <torch/csrc/jit/runtime/static/impl.h>
6
+
7
+ namespace torch::jit {
8
+
9
+ class StaticMethod : public torch::IMethod {
10
+ public:
11
+ StaticMethod(
12
+ std::shared_ptr<StaticModule> static_module,
13
+ std::string method_name)
14
+ : static_module_(std::move(static_module)),
15
+ method_name_(std::move(method_name)) {
16
+ TORCH_CHECK(static_module_);
17
+ }
18
+
19
+ c10::IValue operator()(
20
+ std::vector<IValue> args,
21
+ const IValueMap& kwargs = IValueMap()) const override {
22
+ return (*static_module_)(std::move(args), kwargs);
23
+ }
24
+
25
+ const std::string& name() const override {
26
+ return method_name_;
27
+ }
28
+
29
+ protected:
30
+ void setArgumentNames(
31
+ std::vector<std::string>& argument_names_out) const override {
32
+ const auto& schema = static_module_->schema();
33
+ CAFFE_ENFORCE(schema.has_value());
34
+ const auto& arguments = schema->arguments();
35
+ argument_names_out.clear();
36
+ argument_names_out.reserve(arguments.size());
37
+ std::transform(
38
+ arguments.begin(),
39
+ arguments.end(),
40
+ std::back_inserter(argument_names_out),
41
+ [](const c10::Argument& arg) -> std::string { return arg.name(); });
42
+ }
43
+
44
+ private:
45
+ std::shared_ptr<StaticModule> static_module_;
46
+ std::string method_name_;
47
+ };
48
+
49
+ } // namespace torch::jit
50
+
51
+ #else
52
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
53
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/te_wrapper.h ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <torch/csrc/jit/tensorexpr/codegen.h>
5
+ #include <torch/csrc/jit/tensorexpr/ir.h>
6
+ #include <torch/csrc/jit/tensorexpr/ir_simplifier.h>
7
+ #include <torch/csrc/jit/tensorexpr/llvm_codegen.h>
8
+ #include <torch/csrc/jit/tensorexpr/loopnest.h>
9
+
10
+ namespace torch::jit {
11
+
12
+ class TEWrapper {
13
+ public:
14
+ TEWrapper() = default;
15
+ void call(const std::vector<void*>& args);
16
+
17
+ template <typename ExpectedType>
18
+ bool checkInput(const at::Tensor& t) {
19
+ #ifdef TORCH_ENABLE_LLVM
20
+ return t.is_contiguous() && t.dtype().Match<ExpectedType>();
21
+ #else
22
+ return false;
23
+ #endif
24
+ }
25
+
26
+ #ifdef TORCH_ENABLE_LLVM
27
+ void update(std::unique_ptr<tensorexpr::LLVMCodeGen>&& cg_);
28
+ #endif
29
+
30
+ private:
31
+ #ifdef TORCH_ENABLE_LLVM
32
+ std::unique_ptr<tensorexpr::LLVMCodeGen> cg;
33
+ #endif
34
+ };
35
+
36
+ std::shared_ptr<TEWrapper> createDiv();
37
+ std::shared_ptr<TEWrapper> createLogit();
38
+ std::shared_ptr<TEWrapper> createRelu();
39
+ std::shared_ptr<TEWrapper> createTanh();
40
+ std::shared_ptr<TEWrapper> createSigmoid();
41
+ std::shared_ptr<TEWrapper> createSignedLog1p();
42
+ std::shared_ptr<TEWrapper> createClamp();
43
+ std::shared_ptr<TEWrapper> createClampNanToNum();
44
+
45
+ } // namespace torch::jit
46
+
47
+ #else
48
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
49
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_script.h ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ // This file is temporary until native_functions.yaml and derivatives.yaml are
4
+ // merged. Ideally this should all go into native_functions.yaml
5
+
6
+ #include <c10/util/StringUtil.h>
7
+ #include <torch/csrc/jit/api/module.h>
8
+ #include <optional>
9
+
10
+ namespace torch::jit {
11
+ struct GradientPair {
12
+ std::shared_ptr<Graph> forward;
13
+ std::shared_ptr<Graph> backward;
14
+ };
15
+
16
+ TORCH_API std::optional<GradientPair> gradientInfoForSchema(
17
+ const FunctionSchema& schema);
18
+ TORCH_API bool hasGradientInfoForSchema(const FunctionSchema& schema);
19
+ } // namespace torch::jit
20
+
21
+ #else
22
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
23
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_shape_registry.h ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ // This file is temporary until native_functions.yaml and derivatives.yaml are
4
+ // merged. Ideally this should all go into native_functions.yaml
5
+
6
+ #include <torch/csrc/Export.h>
7
+ #include <torch/csrc/jit/ir/ir.h>
8
+
9
+ namespace torch::jit {
10
+
11
+ /*
12
+ ADDING A NEW SHAPE GRAPH:
13
+ - For one node schema, there is one corresponding registered shape compute
14
+ graph. The schema of the graph should be the same except for Tensor arguments.
15
+ For every Tensor input in operator schema, there should be a List[int]
16
+ corresponding to that Tensor's shape. For example: "aten::linear(Tensor input,
17
+ Tensor weight, Tensor? bias=None) -> Tensor" ==> def linear(input: List[int],
18
+ weight: List[int], bias: Optional[List[int]])
19
+
20
+ Additionally, arguments which are unused at the end of the schema may be left
21
+ off. This allows sharing a single graph for multiple function schemas, such as
22
+ unary operators with different trailing arguments that do not affect the output
23
+ shape.
24
+
25
+ The shape graph should return a new, unaliased List[int] (or tuple of lists for
26
+ multiple returns) and should not modify any input lists. This allows the shape
27
+ graphs to be composed and executed.
28
+
29
+ The shape analysis (particularly for non-complete, or symbolic shapes) works by
30
+ partially evaluating the JIT IR. It may be possible for a Graph to be registered
31
+ that we cannot currently partially evaluate. If this happens, please file an
32
+ issue. There are lints registered to avoid particular known patterns (continue
33
+ or break or early return in a loop). Those may be improved in the future, please
34
+ file an issue if necessary.
35
+
36
+ To debug (and write initially) the recommended flow is to define these functions
37
+ in python and iterate there. Functions should be added to
38
+ torch/jit/_shape_functions.
39
+
40
+ To test operators, the preferred flow is through OpInfos, with
41
+ `assert_jit_shape_analysis=True`. If this is not feasible, you can look at tests
42
+ in `test_symbolic_shape_analysis.py` such as `test_adaptive_avg_pool2d`.
43
+
44
+ Operators which take in a list of tensors, such as concat, are not yet
45
+ supported. Concat has been special cased and could be generalized as needed.
46
+ Please file an issue.
47
+ */
48
+
49
+ struct BoundedShapeGraphs {
50
+ std::shared_ptr<Graph> lower_bound;
51
+ std::shared_ptr<Graph> upper_bound;
52
+ };
53
+
54
+ TORCH_API void RegisterShapeComputeGraphForSchema(
55
+ const FunctionSchema& schema,
56
+ const std::shared_ptr<Graph>& g);
57
+
58
+ TORCH_API std::optional<std::shared_ptr<Graph>> shapeComputeGraphForSchema(
59
+ const FunctionSchema& schema);
60
+
61
+ TORCH_API std::optional<BoundedShapeGraphs> boundedGraphsForSchema(
62
+ const FunctionSchema& schema);
63
+
64
+ TORCH_API std::vector<const FunctionSchema*> RegisteredShapeComputeSchemas();
65
+
66
+ TORCH_API void LintShapeComputeGraph(
67
+ const FunctionSchema* schema,
68
+ const std::shared_ptr<Graph>& graph);
69
+
70
+ } // namespace torch::jit
71
+
72
+ #else
73
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
74
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_shape_registry_util.h ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ // This file is temporary until native_functions.yaml and derivatives.yaml are
4
+ // merged. Ideally this should all go into native_functions.yaml
5
+
6
+ #include <torch/csrc/Export.h>
7
+ #include <torch/csrc/jit/ir/ir.h>
8
+
9
+ namespace torch::jit {
10
+
11
+ TORCH_API const OperatorMap<std::string>& get_tensorexpr_elementwise_set();
12
+
13
+ } // namespace torch::jit
14
+
15
+ #else
16
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
17
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/vararg_functions.h ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <ATen/core/List.h>
4
+ #include <ATen/core/functional.h>
5
+ #include <ATen/core/ivalue.h>
6
+ #include <ATen/core/jit_type.h>
7
+ #include <ATen/core/stack.h>
8
+
9
+ namespace torch::jit {
10
+
11
+ void tupleUnpack(Stack& stack);
12
+
13
+ void format(Stack& stack, size_t num_inputs);
14
+
15
+ void einsum(Stack& stack, size_t num_inputs);
16
+
17
+ void percentFormat(Stack& stack, size_t num_inputs);
18
+
19
+ void listUnpack(Stack& stack, size_t num_outputs);
20
+
21
+ void tupleConstruct(Stack& stack, size_t num_inputs);
22
+
23
+ void namedTupleConstruct(Stack& stack, c10::TypePtr type, size_t num_inputs);
24
+
25
+ void listConstruct(Stack& stack, const c10::Type& list_type, size_t num_inputs);
26
+
27
+ void dictConstruct(Stack& stack, const c10::Type& type, size_t num_inputs);
28
+
29
+ // as weak_ref will create a Object with a non-owning CompilationUnit reference,
30
+ // for use as a constant in the Graph to avoid a reference cycle
31
+ void createObject(
32
+ Stack& stack,
33
+ const at::ClassTypePtr& type,
34
+ bool as_weak_ref = false);
35
+
36
+ void isinstance(Stack& stack, at::ArrayRef<at::TypePtr> types);
37
+
38
+ void tupleSlice(Stack& stack, size_t begin, size_t end);
39
+
40
+ void dequantize(Stack& stack);
41
+
42
+ } // namespace torch::jit
43
+
44
+ #else
45
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
46
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/variable_tensor_list.h ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+ #include <ATen/core/Tensor.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // a wrapper to mark places where we expect all the at::Tensors to be
8
+ // variables
9
+ struct variable_tensor_list : public std::vector<at::Tensor> {
10
+ variable_tensor_list() = default;
11
+ template <class InputIt>
12
+ variable_tensor_list(InputIt first, InputIt last)
13
+ : std::vector<at::Tensor>(first, last) {}
14
+ explicit variable_tensor_list(std::vector<at::Tensor>&& tensor)
15
+ : std::vector<at::Tensor>(std::move(tensor)) {}
16
+ };
17
+
18
+ } // namespace torch::jit
19
+
20
+ #else
21
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
22
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/serialization/callstack_debug_info_serialization.h ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2
+ #pragma once
3
+
4
+ #include <c10/core/Allocator.h>
5
+ #include <torch/csrc/jit/frontend/source_range.h>
6
+ #include <torch/csrc/jit/ir/scope.h>
7
+
8
+ #include <ATen/core/ivalue.h>
9
+
10
+ #include <vector>
11
+
12
+ #include <c10/util/flat_hash_map.h>
13
+
14
+ namespace c10 {
15
+ struct IValue;
16
+ }
17
+
18
+ namespace torch::jit {
19
+
20
+ class Pickler;
21
+ class InlinedCallStackSerializer {
22
+ public:
23
+ // Serialize InlinedCallStack as
24
+ // SerializedInlinedCallStack =
25
+ // [module_info, source range tag, SerializedInlinedCallStack]
26
+ // module_info = [ClassType.qualifiedName, instance_name]
27
+ // source_range_tag = unique source range id
28
+ c10::IValue serialize(
29
+ const InlinedCallStackPtr& cs_ptr,
30
+ const SourceRangeTagMap& source_range_tags);
31
+
32
+ private:
33
+ // module_info = [ClassType.qualifiedName, instance_name]
34
+ c10::IValue serialize_module_instance_info(
35
+ const std::optional<ModuleInstanceInfo>& m);
36
+
37
+ // This caches serialized inlined callstack ptr, since many
38
+ // InlinedCallStackPtr can refer to the same one.
39
+ ska::flat_hash_map<InlinedCallStackPtr, c10::IValue>
40
+ serialized_inlined_callstack_;
41
+ // This caches serialized module instance info.
42
+ // There might be many nodes that are part of the same
43
+ // parent, grandparent etc. module.
44
+ ska::flat_hash_map<std::string, c10::IValue> serialized_module_instance_info_;
45
+ };
46
+
47
+ class TORCH_API CallStackDebugInfoPickler {
48
+ public:
49
+ CallStackDebugInfoPickler() = default;
50
+
51
+ std::vector<char> pickle(
52
+ const std::unordered_map<int64_t, DebugInfoTuple>& callstack_ptrs,
53
+ const SourceRangeTagMap& source_range_tags);
54
+
55
+ private:
56
+ InlinedCallStackSerializer css_;
57
+ };
58
+
59
+ class InlinedCallStackDeserializer {
60
+ public:
61
+ InlinedCallStackPtr deserialize(
62
+ const c10::IValue& iv,
63
+ const ska::flat_hash_map<int64_t, SourceRange>& source_range_map,
64
+ const std::shared_ptr<CompilationUnit>& cu);
65
+
66
+ private:
67
+ std::optional<ModuleInstanceInfo> deserialize_module_instance_info(
68
+ const c10::IValue& iv,
69
+ const std::shared_ptr<CompilationUnit>& cu);
70
+
71
+ ska::
72
+ flat_hash_map<c10::intrusive_ptr<c10::ivalue::Tuple>, InlinedCallStackPtr>
73
+ cached_inlined_callstacks_;
74
+ ska::flat_hash_map<c10::intrusive_ptr<c10::ivalue::Tuple>, ModuleInstanceInfo>
75
+ cached_module_instance_info_;
76
+ };
77
+
78
+ class TORCH_API CallStackDebugInfoUnpickler {
79
+ public:
80
+ ska::flat_hash_map<int64_t, DebugInfoTuple> unpickle(
81
+ const at::DataPtr& data,
82
+ size_t size,
83
+ const ska::flat_hash_map<int64_t, SourceRange>& source_range_map,
84
+ const std::shared_ptr<CompilationUnit>& cu);
85
+
86
+ private:
87
+ InlinedCallStackDeserializer csds_;
88
+ };
89
+
90
+ } // namespace torch::jit
91
+
92
+ #else
93
+ #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
94
+ #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)