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

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/compilation_unit.h +351 -0
  2. lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/function_impl.h +180 -0
  3. lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/method.h +84 -0
  4. lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/module.h +685 -0
  5. lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/object.h +200 -0
  6. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend.h +117 -0
  7. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_handler.h +138 -0
  8. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_info.h +63 -0
  9. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_detail.h +39 -0
  10. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_exception.h +56 -0
  11. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_init.h +9 -0
  12. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_interface.h +32 -0
  13. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_preprocess.h +16 -0
  14. lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_resolver.h +8 -0
  15. lib/python3.12/site-packages/torch/include/torch/csrc/jit/codegen/cuda/interface.h +52 -0
  16. lib/python3.12/site-packages/torch/include/torch/csrc/jit/jit_log.h +126 -0
  17. lib/python3.12/site-packages/torch/include/torch/csrc/jit/jit_opt_limit.h +37 -0
  18. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/add_if_then_else.h +9 -0
  19. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/annotate_warns.h +9 -0
  20. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/autocast.h +13 -0
  21. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/bailout_graph.h +32 -0
  22. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/batch_mm.h +9 -0
  23. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/canonicalize.h +20 -0
  24. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/canonicalize_graph_fuser_ops.h +9 -0
  25. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/check_strict_fusion.h +10 -0
  26. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/clear_profiling.h +17 -0
  27. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/clear_undefinedness.h +22 -0
  28. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/common_subexpression_elimination.h +9 -0
  29. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/concat_opt.h +17 -0
  30. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/constant_pooling.h +9 -0
  31. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/constant_propagation.h +30 -0
  32. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/create_autodiff_subgraphs.h +17 -0
  33. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/create_functional_graphs.h +12 -0
  34. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/dead_code_elimination.h +40 -0
  35. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/decompose_ops.h +9 -0
  36. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/device_type_analysis.h +11 -0
  37. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/dtype_analysis.h +15 -0
  38. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/eliminate_no_ops.h +15 -0
  39. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/erase_number_types.h +21 -0
  40. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fixup_trace_scope_blocks.h +45 -0
  41. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fold_conv_bn.h +35 -0
  42. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fold_linear_bn.h +27 -0
  43. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/freeze_module.h +34 -0
  44. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_concat_linear.h +11 -0
  45. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_conv_add_relu_fusion.h +13 -0
  46. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_conv_folding.h +22 -0
  47. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_graph_optimizations.h +20 -0
  48. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_linear_folding.h +12 -0
  49. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_linear_transpose.h +11 -0
  50. lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_ops_to_mkldnn.h +13 -0
lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/compilation_unit.h ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <ATen/core/function.h>
3
+ #include <c10/util/Exception.h>
4
+ #include <torch/csrc/jit/api/function_impl.h>
5
+ #include <torch/csrc/jit/frontend/name_mangler.h>
6
+ #include <torch/csrc/jit/frontend/source_range.h>
7
+ #include <torch/csrc/jit/ir/ir.h>
8
+ #include <torch/csrc/jit/runtime/graph_executor.h>
9
+
10
+ #include <torch/csrc/Export.h>
11
+
12
+ #include <ATen/core/function_schema.h>
13
+ #include <ATen/core/qualified_name.h>
14
+ #include <c10/util/ArrayRef.h>
15
+ #include <optional>
16
+
17
+ #include <functional>
18
+ #include <memory>
19
+ #include <mutex>
20
+ #include <ostream>
21
+ #include <string>
22
+ #include <unordered_map>
23
+ #include <vector>
24
+
25
+ namespace torch::jit {
26
+
27
+ struct Def;
28
+ struct Property;
29
+ struct ClassDef;
30
+ struct SugaredValue;
31
+ struct Resolver;
32
+
33
+ using ResolverPtr = std::shared_ptr<Resolver>;
34
+ struct Self {
35
+ virtual ~Self() = default;
36
+ virtual std::shared_ptr<SugaredValue> makeSugared(Value* v) const = 0;
37
+ virtual ClassTypePtr getClassType() const = 0;
38
+ };
39
+
40
+ // A CompilationUnit is a list of named Functions
41
+ // with helper methods to iterate the list or invoke the function.
42
+ // Classes have a CompilationUnit holding the class methods,
43
+ // and Modules have a CompilationUnit holding the Functions that
44
+ // are used to implement their Methods
45
+
46
+ struct TORCH_API CompilationUnit {
47
+ enum class FunctionType { Method, Hook, PreHook };
48
+ // constructor that takes a set of functions to compile using the native
49
+ // resolver
50
+ explicit CompilationUnit(const std::string& source);
51
+ CompilationUnit() = default;
52
+
53
+ CompilationUnit& operator=(CompilationUnit&&) = default;
54
+ CompilationUnit(CompilationUnit&&) = default;
55
+ CompilationUnit& operator=(const CompilationUnit&) = delete;
56
+ CompilationUnit(const CompilationUnit&) = delete;
57
+
58
+ Function* find_function(const c10::QualifiedName& name) const {
59
+ auto it = dict_.find(name);
60
+ if (it == dict_.end()) {
61
+ return nullptr;
62
+ }
63
+ return functions_[it->second].get();
64
+ }
65
+
66
+ Function& get_function(const c10::QualifiedName& name) const {
67
+ if (auto r = find_function(name)) {
68
+ return *r;
69
+ }
70
+ TORCH_CHECK(false, "attempted to get undefined function ", name.name());
71
+ }
72
+
73
+ void set_optimized(bool o) {
74
+ TORCH_WARN(
75
+ "CompilationUnit::set_optimized() is deprecated and has no effect. "
76
+ "Please use setGraphExecutorOptimize()");
77
+ }
78
+
79
+ bool is_optimized() const {
80
+ TORCH_WARN(
81
+ "CompilationUnit::is_optimized() is deprecated and always returns true. "
82
+ "Please use getGraphExecutorOptimize()");
83
+ return true;
84
+ }
85
+
86
+ // for historic reasons, these are defined in ir_emitter.cpp
87
+ // Returns the list of Functions just defined.
88
+ std::vector<Function*> define(
89
+ const std::optional<c10::QualifiedName>& prefix,
90
+ const std::vector<Property>& properties,
91
+ const std::vector<ResolverPtr>& propResolvers,
92
+ const std::vector<Def>& definitions,
93
+ const std::vector<ResolverPtr>&
94
+ defResolvers, /* determines how we handle free
95
+ variables in each definition*/
96
+ // if non-null, the first argument to each def, is bound to this value
97
+ const Self* self,
98
+ // see [name mangling]
99
+ bool shouldMangle = false,
100
+ std::optional<size_t> operator_set_version = std::nullopt);
101
+
102
+ void define_hooks(
103
+ const std::optional<c10::QualifiedName>& prefix,
104
+ const std::vector<Def>& hookDefs,
105
+ const std::vector<ResolverPtr>& hookResolvers,
106
+ const std::vector<Def>& preHookDefs,
107
+ const std::vector<ResolverPtr>& preHookResolvers,
108
+ const Self* self,
109
+ bool shouldMangle = false);
110
+
111
+ // same as above but parse the definitions from source
112
+ // Returns the list of Functions just defined.
113
+ std::vector<Function*> define(
114
+ // prefix namespace to put all the defined functions into
115
+ const std::optional<c10::QualifiedName>& prefix,
116
+ const std::string& source,
117
+ const ResolverPtr& resolver,
118
+ const Self* self);
119
+
120
+ void define_interface(
121
+ const c10::QualifiedName& qualifiedName,
122
+ const ClassDef& classDef,
123
+ ResolverPtr rcb,
124
+ bool is_module = false);
125
+
126
+ Function* create_function(
127
+ c10::QualifiedName name,
128
+ std::shared_ptr<Graph> graph,
129
+ bool shouldMangle = false) {
130
+ if (shouldMangle) {
131
+ name = mangle(name);
132
+ }
133
+ auto fn = std::make_unique<GraphFunction>(
134
+ std::move(name), std::move(graph), nullptr);
135
+ auto ret = fn.get();
136
+ register_function(std::move(fn));
137
+ return ret;
138
+ }
139
+
140
+ std::vector<Function*> get_functions() const {
141
+ return fmap(functions_, [](const std::unique_ptr<Function>& fn) {
142
+ return fn.get();
143
+ });
144
+ }
145
+
146
+ /// Run a method from this compilation.
147
+ ///
148
+ /// For example:
149
+ /// @code
150
+ /// IValue output = module->run("relu_script", a, b);
151
+ /// @endcode
152
+ ///
153
+ /// To get a compile a module from a source string, see torch::jit::compile
154
+ ///
155
+ /// @param method_name The name of the method to run
156
+ /// @param args Arguments to be passed to the method
157
+ /// @return An IValue containing the return value (or values if it is a tuple)
158
+ /// from the method
159
+ template <typename... Types>
160
+ IValue run_method(const c10::QualifiedName& method_name, Types&&... args) {
161
+ return get_function(method_name)({IValue(std::forward<Types>(args))...});
162
+ }
163
+
164
+ void drop_all_functions() {
165
+ dict_.clear();
166
+ functions_.clear();
167
+ }
168
+
169
+ /**
170
+ * Register a class as being owned by this compilation unit.
171
+ */
172
+ void register_type(c10::NamedTypePtr namedType) {
173
+ // TODO: class types cannot be redefined because we have no way right now
174
+ // of invalidating their methods. NamedTuples are fine though, since they
175
+ // don't have methods.
176
+ TORCH_CHECK(
177
+ 0 == classDict_.count(*namedType->name()),
178
+ "class '",
179
+ namedType->name()->qualifiedName(),
180
+ "' already defined.");
181
+ classes_.push_back(std::move(namedType));
182
+ classDict_[*classes_.back()->name()] = classes_.size() - 1;
183
+ }
184
+
185
+ c10::ClassTypePtr get_class(const c10::QualifiedName& name) const {
186
+ auto type = get_type(name);
187
+ if (!type) {
188
+ return nullptr;
189
+ }
190
+ return type->cast<c10::ClassType>();
191
+ }
192
+
193
+ c10::InterfaceTypePtr get_interface(const c10::QualifiedName& name) const {
194
+ auto type = get_type(name);
195
+ if (!type) {
196
+ return nullptr;
197
+ }
198
+ return type->cast<c10::InterfaceType>();
199
+ }
200
+
201
+ c10::TupleTypePtr get_named_tuple(const c10::QualifiedName& name) const {
202
+ for (const auto& cls : classes_) {
203
+ if (cls->name()->qualifiedName() == name.qualifiedName()) {
204
+ return cls->expect<TupleType>();
205
+ }
206
+ }
207
+ return nullptr;
208
+ }
209
+
210
+ c10::NamedTypePtr get_type(const c10::QualifiedName& name) const {
211
+ auto it = classDict_.find(name);
212
+ if (it == classDict_.end()) {
213
+ return nullptr;
214
+ }
215
+ return classes_[it->second];
216
+ }
217
+
218
+ // For testing: clear all Python-defined classes to ensure that unit tests
219
+ // have isolation.
220
+ void _clear_python_cu() {
221
+ // Delete all the associated class methods
222
+ for (const auto& type : classes_) {
223
+ if (auto cls = type->cast<ClassType>()) {
224
+ for (auto method : cls->methods()) {
225
+ // Tombstone the method in the compilation unit.
226
+ // Don't erase because the dict_
227
+ auto it = dict_.find(method->qualname());
228
+ if (it != dict_.end()) {
229
+ functions_[it->second] = nullptr;
230
+ // Erase in our big lookup table
231
+ dict_.erase(it);
232
+ }
233
+ }
234
+ // Classes can have multiple pointers to the same hook,
235
+ // need to make sure to not delete it twice
236
+ std::unordered_set<Function*> hooks_to_delete;
237
+ for (const auto& hook : cls->getForwardHooks()) {
238
+ hooks_to_delete.insert(hook);
239
+ }
240
+ for (const auto& pre_hook : cls->getForwardPreHooks()) {
241
+ hooks_to_delete.insert(pre_hook);
242
+ }
243
+ for (const auto& hook : hooks_to_delete) {
244
+ // Tombstone the hook in the compilation unit.
245
+ auto it = dict_.find(hook->qualname());
246
+ if (it != dict_.end()) {
247
+ functions_[it->second] = nullptr;
248
+ // Erase in our big lookup table
249
+ dict_.erase(it);
250
+ }
251
+ }
252
+ }
253
+ }
254
+ classes_.clear();
255
+ classDict_.clear();
256
+ }
257
+
258
+ // [Internal Only] Remove method.
259
+ // Note Used for freezing.
260
+ void unsafeRemoveMethod(const c10::QualifiedName& method_name) {
261
+ auto it = dict_.find(method_name);
262
+ TORCH_CHECK(
263
+ it != dict_.end(),
264
+ "method '",
265
+ method_name.qualifiedName(),
266
+ "' does not exist.");
267
+ functions_[it->second] = nullptr;
268
+ dict_.erase(it);
269
+ }
270
+
271
+ // [name mangling] All code objects must have a unique qualified name in a
272
+ // CompilationUnit. In Python, sometimes functions won't have unique qualified
273
+ // name (for example, nested functions). So we mangle Python functions to
274
+ // ensure that they are uniquely named.
275
+ //
276
+ // We also use mangling to distinguish different Module instances. Since each
277
+ // Module is a singleton class instance, different instances of the same
278
+ // Python Module will have different types but the same qualified name.
279
+ c10::QualifiedName mangle(const c10::QualifiedName& name) const {
280
+ auto mangled = name;
281
+ while (get_type(mangled) || find_function(mangled)) {
282
+ mangled = mangler_.mangle(mangled);
283
+ }
284
+ return mangled;
285
+ }
286
+
287
+ private:
288
+ std::unique_ptr<Function> define(
289
+ const std::optional<c10::QualifiedName>& prefix,
290
+ const Def& def,
291
+ const ResolverPtr& resolver,
292
+ const Self* self,
293
+ const std::unordered_map<std::string, Function*>& function_table,
294
+ bool shouldMangle = false,
295
+ FunctionType type = FunctionType::Method,
296
+ std::optional<size_t> version = std::nullopt) const;
297
+
298
+ // Define a property on \p self.
299
+ struct PropertyPair;
300
+ PropertyPair define_property(
301
+ const std::optional<c10::QualifiedName>& prefix,
302
+ const Property& prop,
303
+ const ResolverPtr& resolver,
304
+ const Self* self,
305
+ const std::unordered_map<std::string, Function*>& function_table,
306
+ bool shouldMangle = false) const;
307
+
308
+ Function& register_function(std::unique_ptr<Function> fn) {
309
+ TORCH_CHECK(
310
+ 0 == dict_.count(fn->qualname().qualifiedName()),
311
+ "method '",
312
+ fn->qualname().qualifiedName(),
313
+ "' already defined.");
314
+ functions_.emplace_back(std::move(fn));
315
+ dict_[functions_.back()->qualname()] = functions_.size() - 1;
316
+ return *functions_.back();
317
+ }
318
+ std::vector<std::unique_ptr<Function>> functions_;
319
+ // for fast lookup
320
+ std::unordered_map<c10::QualifiedName, size_t> dict_;
321
+ std::unordered_map<c10::QualifiedName, size_t> classDict_;
322
+
323
+ // [class ownership] Right now there are two relationships between classes
324
+ // and compilation units:
325
+ // 1. Classes have compilation units internally that hold their methods.
326
+ // 2. On load, the TypePtrs of any imported classes are owned by the main
327
+ // module's compilation unit.
328
+ std::vector<c10::NamedTypePtr> classes_;
329
+
330
+ mutable NameMangler mangler_;
331
+ };
332
+
333
+ // An owning pointer to a Function. Just a pair of a raw Function ptr and it's
334
+ // owning CU. We need this because pybind requires a ref-counted way to refer to
335
+ // Functions.
336
+ struct StrongFunctionPtr {
337
+ StrongFunctionPtr(std::shared_ptr<CompilationUnit> cu, Function* function)
338
+ : cu_(std::move(cu)), function_(function) {
339
+ TORCH_INTERNAL_ASSERT(cu_);
340
+ TORCH_INTERNAL_ASSERT(function_);
341
+ }
342
+ std::shared_ptr<CompilationUnit> cu_;
343
+ Function* function_;
344
+ };
345
+
346
+ namespace script {
347
+ // We once had a `script::` namespace that was deleted. This is for backcompat
348
+ // of the public API; new code should not use this type alias.
349
+ using CompilationUnit = ::torch::jit::CompilationUnit;
350
+ } // namespace script
351
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/function_impl.h ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/core/function.h>
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+ #include <torch/csrc/jit/runtime/graph_executor.h>
6
+
7
+ namespace torch::jit {
8
+
9
+ struct TORCH_API GraphFunction : public Function {
10
+ GraphFunction(
11
+ c10::QualifiedName name,
12
+ std::shared_ptr<Graph> graph,
13
+ std::function<void(GraphFunction&)> function_creator,
14
+ std::optional<ExecutorExecutionMode> executor_execution_mode =
15
+ std::nullopt)
16
+ : name_(std::move(name)),
17
+ graph_(std::move(graph)),
18
+ executor_execution_mode_(executor_execution_mode),
19
+ function_creator_(std::move(function_creator)) {}
20
+
21
+ bool isGraphFunction() const override {
22
+ return true;
23
+ }
24
+
25
+ void run(Stack& stack) override;
26
+
27
+ std::function<void(GraphFunction&)> function_creator() const {
28
+ return function_creator_;
29
+ }
30
+
31
+ c10::intrusive_ptr<c10::ivalue::Future> runAsync(
32
+ Stack& stack,
33
+ TaskLauncher taskLauncher = at::launch) override;
34
+
35
+ std::shared_ptr<Graph> graph() const {
36
+ return graph_;
37
+ }
38
+
39
+ std::shared_ptr<Graph> optimized_graph() const;
40
+
41
+ const c10::QualifiedName& qualname() const override {
42
+ return name_;
43
+ }
44
+
45
+ // private/unstable api. sets the initial execution mode
46
+ // will not affect executor if there is an existing executor
47
+ // created for this function
48
+ void _set_initial_executor_execution_mode(ExecutorExecutionMode mode) {
49
+ executor_execution_mode_ = mode;
50
+ }
51
+ // private/unstable api. sets flag of whether or not to ignore amp.
52
+ // will not affect executor if there is an existing executor
53
+ // created for this function
54
+ void _set_ignore_amp(bool ignore_amp) {
55
+ force_no_amp_ = ignore_amp;
56
+ }
57
+
58
+ // if this isn't yet defined, run its method_creator function
59
+ void ensure_defined() override;
60
+
61
+ size_t num_inputs() const override {
62
+ return graph()->inputs().size();
63
+ }
64
+
65
+ Function& setSchema(FunctionSchema schema) override {
66
+ schema_ = std::make_unique<FunctionSchema>(std::move(schema));
67
+ return *this;
68
+ }
69
+
70
+ const FunctionSchema& getSchema() const override;
71
+
72
+ GraphExecutorState getDebugState() {
73
+ return get_executor().getDebugState();
74
+ }
75
+
76
+ bool is_optimized() const {
77
+ TORCH_WARN(
78
+ "GraphFunction::is_optimized() is deprecated and always returns true. "
79
+ "Please use getGraphExecutorOptimize()");
80
+ return true;
81
+ }
82
+
83
+ void check_single_output() {
84
+ TORCH_CHECK(
85
+ graph()->outputs().size() == 1,
86
+ "Method (but not graphs in general) require a single output. Use None/Tuple for 0 or 2+ outputs");
87
+ }
88
+
89
+ GraphExecutor& get_executor() {
90
+ ensure_defined();
91
+ std::lock_guard<std::recursive_mutex> lock(compile_mutex);
92
+ auto& executor = executors_[currentSpecialization()];
93
+ if (executor) {
94
+ return *executor;
95
+ }
96
+ check_single_output();
97
+ const std::string& name = name_.name();
98
+ std::shared_ptr<Graph> opt_graph = optimized_graph();
99
+ if (!executor_execution_mode_) {
100
+ executor = GraphExecutor(opt_graph, name);
101
+ } else {
102
+ executor = GraphExecutor(opt_graph, name, *executor_execution_mode_);
103
+ }
104
+ return *executor;
105
+ }
106
+
107
+ using Function::call;
108
+ bool call(
109
+ Stack& stack,
110
+ std::optional<size_t> bailOut,
111
+ c10::function_ref<void(const Code&)> f) override {
112
+ f(get_executor().getPlanFor(stack, bailOut).code);
113
+ return true;
114
+ }
115
+
116
+ void clear_optimized_graphs() {
117
+ optimized_graphs_.fill(nullptr);
118
+ }
119
+
120
+ private:
121
+ enum SpecializationKey {
122
+ AutocastOff,
123
+ CpuAutocastOn,
124
+ GpuAutocastOn,
125
+ CpuGpuAutocastOn,
126
+
127
+ // This provides the number of specializations
128
+ // (Must be last entry)
129
+ TotalCount
130
+ };
131
+
132
+ SpecializationKey currentSpecialization() const;
133
+
134
+ private:
135
+ c10::QualifiedName name_;
136
+ // The original, non-optimized graph
137
+ std::shared_ptr<Graph> graph_; // for debugging and for inlining
138
+
139
+ // allows users to specify Simple/Profiling Executor for function
140
+ // TODO: add more executors
141
+ mutable std::optional<ExecutorExecutionMode> executor_execution_mode_;
142
+
143
+ // if invoked on a graph that has already traced through amp
144
+ // don't invoke amp pass
145
+ mutable bool force_no_amp_ = false;
146
+ // Optimized graph, computed lazily. Used for inlining.
147
+ mutable std::array<std::shared_ptr<Graph>, SpecializationKey::TotalCount>
148
+ optimized_graphs_;
149
+
150
+ // GraphFunctions are invokable from multiple threads, so this lock needs to
151
+ // be held when we're initializing graph executor for the first time or
152
+ // computing the optimized graph. We're using reentrant mutex so that we don't
153
+ // need to worry about causing a deadlock by calling one method from another
154
+ // (e.g. optimized_graph() from get_executor()).
155
+ mutable std::recursive_mutex compile_mutex;
156
+
157
+ // executor_[0] - autocast off
158
+ // executor_[1] - autocast cpu on
159
+ // executor_[2] - autocast gpu on
160
+ // executor_[3] - autocast cpu & gpu on
161
+ std::array<std::optional<GraphExecutor>, SpecializationKey::TotalCount>
162
+ executors_;
163
+
164
+ // an optional function that actually creates the method when
165
+ // ensure_defined() is called. This is used by the compiler so
166
+ // that it can construct methods out of order
167
+ std::function<void(GraphFunction&)> function_creator_;
168
+
169
+ // if absent, then we generate a default schema based on the graph
170
+ // mutable because getSchema caches the default schema if one is requested
171
+ // before a call to setSchema
172
+ mutable std::unique_ptr<FunctionSchema> schema_;
173
+ };
174
+
175
+ // Short hands for dynamic_cast<GraphFunction*>.
176
+ TORCH_API GraphFunction* tryToGraphFunction(Function&) noexcept;
177
+ TORCH_API GraphFunction& toGraphFunction(Function&);
178
+ TORCH_API const GraphFunction& toGraphFunction(const Function&);
179
+
180
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/method.h ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/core/function.h>
4
+ #include <ATen/core/ivalue.h>
5
+ #include <ATen/core/stack.h>
6
+ #include <torch/csrc/api/include/torch/imethod.h>
7
+ #include <torch/csrc/jit/api/function_impl.h>
8
+
9
+ namespace torch::jit {
10
+
11
+ using ObjectPtr = c10::intrusive_ptr<c10::ivalue::Object>;
12
+
13
+ // A method in a module, e.g. f in:
14
+ //
15
+ // class M(ScriptModule):
16
+ // @script_method
17
+ // def f(self, x):
18
+ // ...
19
+ // Note: because Method/Module are exposed to python these
20
+ // classes use python method naming conventions
21
+ struct TORCH_API Method : public torch::IMethod {
22
+ Method(ObjectPtr owner, Function* function);
23
+
24
+ // the module that contains this method.
25
+ Module owner() const;
26
+ // the raw objectptr that owns this method, for when the method is owned by a
27
+ // torchbind object.
28
+ ObjectPtr raw_owner() const;
29
+ void run(Stack& stack);
30
+ void run(Stack&& stack) {
31
+ run(stack);
32
+ }
33
+
34
+ c10::IValue operator()(
35
+ std::vector<c10::IValue> stack,
36
+ const Kwargs& kwargs = Kwargs()) const override;
37
+
38
+ // Run method async. Invocation on this function would invokes a JIT
39
+ // interpreter that executes ops inline, one by one, on caller's thread. A
40
+ // model can utilize async op, i.e. `fork`, to launch an asynchronous task
41
+ // which will be launched on provided `taskLauncher`.
42
+ c10::intrusive_ptr<c10::ivalue::Future> run_async(
43
+ std::vector<c10::IValue> stack,
44
+ const Kwargs& kwargs = Kwargs(),
45
+ TaskLauncher taskLauncher = at::launch);
46
+
47
+ std::shared_ptr<Graph> graph() const {
48
+ return toGraphFunction(*function_).graph();
49
+ }
50
+
51
+ const std::string& name() const override {
52
+ return function_->name();
53
+ }
54
+
55
+ size_t num_inputs() const {
56
+ return function_->num_inputs();
57
+ }
58
+
59
+ GraphExecutor& get_executor() {
60
+ return toGraphFunction(*function_).get_executor();
61
+ }
62
+
63
+ Function& function() const {
64
+ return *function_;
65
+ }
66
+
67
+ private:
68
+ void setArgumentNames(std::vector<std::string>&) const override;
69
+
70
+ // Methods are uniqued onwed by a single module. This raw pointer allows
71
+ // looking up the module.
72
+ ObjectPtr owner_;
73
+
74
+ // Underlying unbound function
75
+ Function* function_;
76
+ };
77
+
78
+ namespace script {
79
+ // We once had a `script::` namespace that was deleted. This is for backcompat
80
+ // of the public API; new code should not use this type alias.
81
+ using Method = ::torch::jit::Method;
82
+ } // namespace script
83
+
84
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/module.h ADDED
@@ -0,0 +1,685 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <c10/util/Exception.h>
3
+ #include <torch/csrc/autograd/variable.h>
4
+ #include <torch/csrc/jit/api/object.h>
5
+ #include <torch/csrc/jit/frontend/source_range.h>
6
+ #include <torch/csrc/jit/ir/ir.h>
7
+ #include <torch/csrc/jit/ir/named_value.h>
8
+ #include <torch/csrc/jit/runtime/argument_spec.h>
9
+ #include <torch/csrc/jit/runtime/graph_executor.h>
10
+
11
+ #include <torch/csrc/Export.h>
12
+ #include <torch/csrc/api/include/torch/ordered_dict.h>
13
+ #include <torch/csrc/jit/api/compilation_unit.h>
14
+
15
+ #include <ATen/core/function_schema.h>
16
+ #include <ATen/core/qualified_name.h>
17
+ #include <c10/util/ArrayRef.h>
18
+ #include <c10/util/irange.h>
19
+ #include <optional>
20
+
21
+ #include <functional>
22
+ #include <memory>
23
+ #include <mutex>
24
+ #include <ostream>
25
+ #include <string>
26
+ #include <unordered_map>
27
+ #include <unordered_set>
28
+ #include <utility>
29
+ #include <vector>
30
+
31
+ // This file contains classes which assist in desugaring Python style
32
+ // modules and their methods into flattened graphs which don't have any
33
+ // function calls.
34
+
35
+ namespace torch::jit {
36
+
37
+ using ::c10::Argument;
38
+ using ::c10::FunctionSchema;
39
+ using ::c10::QualifiedName;
40
+ // Map which stores filename to content.
41
+ using ExtraFilesMap = std::unordered_map<std::string, std::string>;
42
+
43
+ using ModulePtr = c10::intrusive_ptr<c10::ivalue::Object>;
44
+
45
+ struct Module;
46
+
47
+ template <typename T>
48
+ struct slot_list_impl;
49
+
50
+ template <typename T>
51
+ struct Named {
52
+ std::string name;
53
+ T value;
54
+ };
55
+
56
+ using NameModule = Named<Module>;
57
+ using NameValue = Named<IValue>;
58
+ using NameTensor = Named<at::Tensor>;
59
+
60
+ namespace detail {
61
+ struct TORCH_API ModulePolicy;
62
+ struct TORCH_API ParameterPolicy;
63
+ struct TORCH_API AttributePolicy;
64
+ struct TORCH_API BufferPolicy;
65
+ template <typename P>
66
+ struct NamedPolicy;
67
+ } // namespace detail
68
+
69
+ using module_list = slot_list_impl<detail::ModulePolicy>;
70
+ using named_module_list =
71
+ slot_list_impl<detail::NamedPolicy<detail::ModulePolicy>>;
72
+
73
+ using parameter_list = slot_list_impl<detail::ParameterPolicy>;
74
+ using named_parameter_list =
75
+ slot_list_impl<detail::NamedPolicy<detail::ParameterPolicy>>;
76
+
77
+ using attribute_list = slot_list_impl<detail::AttributePolicy>;
78
+ using named_attribute_list =
79
+ slot_list_impl<detail::NamedPolicy<detail::AttributePolicy>>;
80
+
81
+ using buffer_list = slot_list_impl<detail::BufferPolicy>;
82
+ using named_buffer_list =
83
+ slot_list_impl<detail::NamedPolicy<detail::BufferPolicy>>;
84
+
85
+ using ModuleLookup = std::function<Module(const std::vector<std::string>&)>;
86
+
87
+ struct TORCH_API Module : public Object {
88
+ explicit Module(c10::QualifiedName class_name);
89
+ Module(std::shared_ptr<CompilationUnit> cu, const c10::ClassTypePtr& type);
90
+ Module() = default;
91
+ Module(const Module&) = default;
92
+ Module& operator=(const Module&) = default;
93
+ Module(Module&&) noexcept = default;
94
+ Module& operator=(Module&&) noexcept = default;
95
+ Module(
96
+ c10::QualifiedName,
97
+ std::shared_ptr<CompilationUnit> cu,
98
+ bool shouldMangle = false);
99
+ Module(ModulePtr module_value) : Object(std::move(module_value)) {}
100
+ ~Module() = default;
101
+
102
+ void set_optimized(bool o) {
103
+ TORCH_WARN(
104
+ "Module::set_optimized() is deprecated and has no effect. "
105
+ "Please use setGraphExecutorOptimize()");
106
+ }
107
+
108
+ bool is_optimized() const {
109
+ TORCH_WARN(
110
+ "Module::is_optimized() is deprecated and always returns true. "
111
+ "Please use getGraphExecutorOptimize()");
112
+ return true;
113
+ }
114
+
115
+ IValue forward(std::vector<IValue> inputs, const Kwargs& kwargs = Kwargs()) {
116
+ return get_method("forward")(std::move(inputs), kwargs);
117
+ }
118
+
119
+ // In script modules, buffers are Tensors attribute that are _not_ registered
120
+ // as parameters. This is different than in nn.Module where there is a special
121
+ // register_buffer method. With this simplification, we only need to track
122
+ // whether a slot is a parameter to be able to classify it.
123
+ void register_buffer(const std::string& name, at::Tensor v) {
124
+ bool is_param = false;
125
+ bool is_buffer = true;
126
+ std::lock_guard<std::mutex> lock(*register_mutex_);
127
+ type()->addOrCheckAttribute(name, TensorType::get(), is_param, is_buffer);
128
+ _ivalue()->setAttr(name, std::move(v));
129
+ }
130
+
131
+ void register_parameter(
132
+ const std::string& name,
133
+ at::Tensor v,
134
+ bool is_buffer) {
135
+ std::lock_guard<std::mutex> lock(*register_mutex_);
136
+ type()->addOrCheckAttribute(name, TensorType::get(), !is_buffer, is_buffer);
137
+ _ivalue()->setAttr(name, std::move(v));
138
+ }
139
+
140
+ void register_attribute(
141
+ const std::string& name,
142
+ const TypePtr& t,
143
+ IValue v,
144
+ bool is_param = false,
145
+ bool is_buffer = false) {
146
+ type()->addOrCheckAttribute(name, t, is_param, is_buffer);
147
+ _ivalue()->setAttr(name, std::move(v));
148
+ }
149
+
150
+ void register_module(const std::string& name, const Module& module) {
151
+ type()->addOrCheckAttribute(name, module.type());
152
+ _ivalue()->setAttr(name, module._ivalue());
153
+ }
154
+
155
+ void apply(const std::function<void(Module&)>& fn);
156
+
157
+ buffer_list buffers(bool recurse = true) const;
158
+ named_buffer_list named_buffers(bool recurse = true) const;
159
+
160
+ module_list children() const; // direct modules
161
+ named_module_list named_children() const;
162
+ module_list modules() const; // all modules, including this one, recursively
163
+ named_module_list named_modules() const;
164
+
165
+ // all tensors involved in gradient optimization
166
+ parameter_list parameters(bool recurse = true) const;
167
+ named_parameter_list named_parameters(bool recurse = true) const;
168
+
169
+ // all members of the object, similar to iterating over dir(obj) in python
170
+ attribute_list attributes(bool recurse = true) const;
171
+ named_attribute_list named_attributes(bool recurse = true) const;
172
+
173
+ void dump(
174
+ bool print_method_bodies,
175
+ bool print_attr_values,
176
+ bool print_param_values) const;
177
+
178
+ std::string dump_to_str(
179
+ bool print_method_bodies,
180
+ bool print_attr_values,
181
+ bool print_param_values) const;
182
+
183
+ /// Enables "training" mode.
184
+ void train(bool on = true);
185
+ /// Calls train(false) to enable "eval" mode.
186
+ /// Do not override this method, override `train()` instead.
187
+ void eval() {
188
+ train(/*on=*/false);
189
+ }
190
+ /// True if the module is in training mode.
191
+ bool is_training() const {
192
+ return attr("training", true).toBool();
193
+ }
194
+
195
+ /// Recursively casts all parameters to the given `dtype` and `device`.
196
+ ///
197
+ /// If `non_blocking` is true and the source is in pinned memory and
198
+ /// destination is on the GPU or vice versa, the copy is performed
199
+ /// asynchronously with respect to the host. Otherwise, the argument has no
200
+ /// effect.
201
+ void to(at::Device device, at::ScalarType dtype, bool non_blocking = false);
202
+
203
+ /// Recursively casts all parameters to the given dtype.
204
+ ///
205
+ /// If `non_blocking` is true and the source is in pinned memory and
206
+ /// destination is on the GPU or vice versa, the copy is performed
207
+ /// asynchronously with respect to the host. Otherwise, the argument has no
208
+ /// effect.
209
+ void to(at::ScalarType dtype, bool non_blocking = false);
210
+
211
+ /// Recursively moves all parameters to the given device.
212
+ ///
213
+ /// If `non_blocking` is true and the source is in pinned memory and
214
+ /// destination is on the GPU or vice versa, the copy is performed
215
+ /// asynchronously with respect to the host. Otherwise, the argument has no
216
+ /// effect.
217
+ void to(at::Device device, bool non_blocking = false);
218
+
219
+ void save(
220
+ std::ostream& out,
221
+ const ExtraFilesMap& extra_files = ExtraFilesMap()) const;
222
+
223
+ void save(
224
+ const std::string& filename,
225
+ const ExtraFilesMap& extra_files = ExtraFilesMap()) const;
226
+
227
+ void _save_for_mobile(
228
+ std::ostream& out,
229
+ const ExtraFilesMap& extra_files = ExtraFilesMap(),
230
+ bool save_mobile_debug_info = false,
231
+ bool use_flatbuffer = false) const;
232
+
233
+ void _save_for_mobile(
234
+ const std::string& filename,
235
+ const ExtraFilesMap& extra_files = ExtraFilesMap(),
236
+ bool save_mobile_debug_info = false,
237
+ bool use_flatbuffer = false) const;
238
+
239
+ Module copy() const;
240
+
241
+ Module deepcopy(std::optional<at::Device> device = std::nullopt) const;
242
+
243
+ // Clones both the underlying `ClassType` and the module instance(data), this
244
+ // function creates a new `ClassType` and returns a new instance that has the
245
+ // same data as the current instance but with the new type, shared ClassType
246
+ // will be preserved as well
247
+ Module clone(bool inplace = false) const;
248
+
249
+ // Clones both the underlying `ClassType` and the module instance(data), this
250
+ // function creates a new `ClassType` and returns a new instance that has the
251
+ // same data as the current instance but with the new type, shared ClassType
252
+ // will be preserved as well. Also allows the caller to specify a set of
253
+ // method and attribute names to not clone.
254
+ Module clone(
255
+ bool inplace,
256
+ const std::unordered_set<std::string>& ignored_method,
257
+ const std::unordered_set<std::string>& ignored_attributes) const;
258
+
259
+ void clone_method(const Module& orig, const std::string& name);
260
+
261
+ IValue operator()(std::vector<IValue> inputs);
262
+
263
+ template <typename... Types>
264
+ IValue create_class(const c10::QualifiedName& name, Types&&... args) const {
265
+ return create_class(name, {IValue(std::forward<Types>(args))...});
266
+ }
267
+
268
+ IValue create_class(const c10::QualifiedName& name, Stack stack) const;
269
+
270
+ inline bool operator==(const Module& y) const noexcept {
271
+ return _ivalue() == y._ivalue();
272
+ }
273
+
274
+ void set_delete_memory(std::shared_ptr<char> delete_mem) {
275
+ mem_to_delete_ = std::move(delete_mem);
276
+ }
277
+
278
+ // A set of functions to maintain input shapes through torch.jit.save and
279
+ // torch.jit.load. It only works on tensors and lists/dicts of tensors
280
+ // because tracing is only supported by these types.
281
+ void store_traced_inputs(
282
+ const std::string& func_name,
283
+ std::vector<IValue> inputs) {
284
+ if (inputs.empty()) {
285
+ return;
286
+ }
287
+ auto c10_inputs = c10::impl::GenericList(AnyType::get());
288
+ for (IValue& value : inputs) {
289
+ // Not checking whether this is traceable type as that is already checked
290
+ // higher up in the stack and changing that would require a larger
291
+ // restructuring.
292
+ c10_inputs.emplace_back(std::move(value));
293
+ }
294
+ traced_inputs_.insert_or_assign(func_name, c10_inputs);
295
+ }
296
+
297
+ c10::Dict<std::string, c10::impl::GenericList> retrieve_traced_inputs()
298
+ const {
299
+ return traced_inputs_;
300
+ }
301
+
302
+ private:
303
+ Module clone_impl(
304
+ std::unordered_map<TypePtr, TypePtr>& type_remap,
305
+ bool inplace,
306
+ IValue::HashIdentityIValueMap memo,
307
+ const std::unordered_set<std::string>& ignored_methods,
308
+ const std::unordered_set<std::string>& ignored_attributes) const;
309
+
310
+ void clone_method(
311
+ const Module& orig,
312
+ const Function& method,
313
+ const std::unordered_map<TypePtr, TypePtr>& type_remap);
314
+
315
+ c10::QualifiedName getNameForMethod(std::string basename) const {
316
+ return QualifiedName(*type()->name(), std::move(basename));
317
+ }
318
+
319
+ void to_impl(
320
+ const std::optional<at::Device>& device,
321
+ const std::optional<at::ScalarType>& dtype,
322
+ bool non_blocking);
323
+
324
+ // Extra handle for the module to delete when itself is deleted
325
+ std::shared_ptr<char> mem_to_delete_;
326
+
327
+ // Map of function names to the traced inputs that they have been traced with
328
+ c10::Dict<std::string, c10::impl::GenericList> traced_inputs_;
329
+
330
+ // Mutex to keep registring buffer or parameter thread safe.
331
+ std::shared_ptr<std::mutex> register_mutex_ = std::make_shared<std::mutex>();
332
+ };
333
+
334
+ // C++ equivalent api of `torch.jit.freeze`. See documentation there for
335
+ // details.
336
+ TORCH_API Module freeze(
337
+ const Module& module,
338
+ const std::optional<std::vector<std::string>>& preserved_attrs =
339
+ std::nullopt,
340
+ bool optimize_numerics = true);
341
+
342
+ // C++ equivalent api of `torch.jit.optimize_for_inference`. See documentation
343
+ // there for details.
344
+ TORCH_API Module optimize_for_inference(
345
+ Module& module,
346
+ const std::vector<std::string>& other_methods = {});
347
+
348
+ enum class FusionBehavior { STATIC, DYNAMIC };
349
+
350
+ using FusionStrategy = std::vector<std::pair<FusionBehavior, size_t>>;
351
+ // clang-format off
352
+ /*
353
+ Sets the type and number of specializations that can occur during fusion.
354
+
355
+ Usage: provide a list of pairs (type, depth) where type is one of STATIC or DYNAMIC
356
+ and depth is an integer.
357
+
358
+ Behavior - static vs dynamic:
359
+ In STATIC fusion, fused ops are compiled to have fixed input shapes. The shape is determined
360
+ based on some initial profiling runs.
361
+ In DYNAMIC fusion, fused ops are compiled to have variable input shapes, so that multiple
362
+ shapes are possible.
363
+
364
+ In both cases, we also recompile on new striding behavior, device, or dtype.
365
+
366
+ Behavior - fallback functions & depth:
367
+ When an input doesn't match the format required by the specialized compiled op, it will run
368
+ a fallback function. Fallback functions are recursively be compiled and specialized based
369
+ on the observed tensor shapes. Since compilation can be slow, the "depth" parameter is provided to
370
+ limit the number of specializations that can be compiled, before giving up on recompiling and
371
+ falling back to a completely un-fused, un-specialized implementation.
372
+
373
+ The list of (type, depth) pairs controls the type of specializations and the number of
374
+ specializations. For example: [(STATIC, 2), (DYNAMIC, 2)] indicates that the first
375
+ two specializations will use static fusions, the following two specializations will use
376
+ dynamic fusion, and any inputs that satisfy none of the 4 options will run an
377
+ unfused implementation.
378
+
379
+ NB: in the future, if more as more fusion backends are added there may be more granular
380
+ apis for specific fusers.
381
+ */
382
+ // clang-format on
383
+ TORCH_API FusionStrategy getFusionStrategy();
384
+ // returns previous strategy
385
+ TORCH_API FusionStrategy setFusionStrategy(FusionStrategy& fusion_strategy);
386
+
387
+ namespace detail {
388
+
389
+ struct TORCH_API SlotCursor {
390
+ Module module_;
391
+ int64_t i_; // slot offset, -1 indicates the module itself
392
+ };
393
+
394
+ } // namespace detail
395
+
396
+ // This iterator allows the (optionally recursive) enumeration of
397
+ // the members of a Module. It performs a depth-first pre-order
398
+ // traversal of the module. The Policy template parameter determines
399
+ // which slots of the object should be included. For instance,
400
+ // when iterating parameters, we return the parameter tensors,
401
+ // but skip modules, buffers, and other attributes.
402
+ // See ModulePolicy for comments about Policy object's API.
403
+ template <typename Policy>
404
+ struct slot_iterator_impl {
405
+ using SlotCursor = detail::SlotCursor;
406
+ using value_type = typename Policy::value_type;
407
+ slot_iterator_impl(
408
+ Module root,
409
+ bool recurse, // if true, do a depth-first search, otherwise, just look at
410
+ // slots of root
411
+ bool return_module) // if true include root itself as the first thing
412
+ // visited (used in modules())
413
+ : cursors_({SlotCursor{std::move(root), return_module ? -1 : 0}}),
414
+ recurse_(recurse) {
415
+ // advance iterator to first valid element (or the end, if empty)
416
+ while_not_valid_next();
417
+ }
418
+ // empty cursors_, represents end of iteration
419
+ slot_iterator_impl() : recurse_(false) {}
420
+ value_type operator*() const {
421
+ return Policy::create(cursors_, cur());
422
+ }
423
+ value_type operator->() const {
424
+ return **this;
425
+ }
426
+ slot_iterator_impl& operator++() {
427
+ next_valid();
428
+ return *this;
429
+ }
430
+ slot_iterator_impl operator++(int) {
431
+ // this is really expensive, should we delete it so people don't use it
432
+ // instead of prefix?
433
+ slot_iterator_impl old = *this;
434
+ ++(*this);
435
+ return old;
436
+ }
437
+
438
+ private:
439
+ // return_module() is a corner case where instead of returning a submodule
440
+ // of root, we are returning root itself, because we are iterating modules(),
441
+ // which contains the root module itself.
442
+ // It is represented with a single SlotCursor whose index is -1.
443
+ bool return_module() const {
444
+ return top().i_ == -1;
445
+ }
446
+ const SlotCursor& top() const {
447
+ return cursors_.back();
448
+ }
449
+ SlotCursor& top() {
450
+ return cursors_.back();
451
+ }
452
+ IValue cur() const {
453
+ return return_module() ? top().module_._ivalue()
454
+ : top().module_._ivalue()->getSlot(top().i_);
455
+ }
456
+
457
+ // advance to the next slot in a depth first pre-order traversal of the
458
+ // modules slots. This function does not guarantee the next slot is a
459
+ // valid element of the iteration. That is done by valid().
460
+ // invariant: !cursors_.empty()
461
+ void next() {
462
+ // we just returned the module itself, advance i_ to 0 so we are now
463
+ // at the first slot of the module.
464
+ if (return_module()) {
465
+ ++top().i_;
466
+ return;
467
+ }
468
+ // the last traversal action advanced beyond the number of slots in the
469
+ // module so continue the iteration in the parent.
470
+ if (top().i_ >= int64_t(top().module_._ivalue()->type()->numAttributes())) {
471
+ cursors_.pop_back();
472
+ if (!cursors_.empty()) {
473
+ ++top().i_;
474
+ }
475
+ return;
476
+ }
477
+ // if the current thing is a module, we have to scan it for recursive
478
+ // traversals. We do this by adding a new SlotCursor to track the traversal.
479
+ if (recurse_ &&
480
+ top().module_._ivalue()->type()->getAttribute(top().i_)->is_module()) {
481
+ cursors_.emplace_back(SlotCursor{cur().toModule(), 0});
482
+ return;
483
+ }
484
+ // common case: advance to the next slot.
485
+ ++top().i_;
486
+ }
487
+ // is the current position of the iterator a valid one?
488
+ // otherwise, we have to continue advancing.
489
+ bool valid() const {
490
+ return top().i_ <
491
+ int64_t(top().module_._ivalue()->type()->numAttributes()) &&
492
+ Policy::valid(
493
+ top().module_._ivalue()->type(),
494
+ top().i_,
495
+ top().module_._ivalue()->getSlot(top().i_));
496
+ }
497
+ void while_not_valid_next() {
498
+ // advance iteration until we are either at the end (cursors_.empty())
499
+ // or in a valid state. return_module() is a special case,
500
+ // and is always considered valid, regardless of Policy, because it is
501
+ // it is only true when we are iterating modules.
502
+ while (!cursors_.empty() && !return_module() && !valid()) {
503
+ next();
504
+ }
505
+ }
506
+ void next_valid() {
507
+ // avoid crashing if this is empty
508
+ if (cursors_.empty()) {
509
+ return;
510
+ }
511
+ // advance to next element, which is maybe not valid
512
+ next();
513
+ while_not_valid_next();
514
+ }
515
+
516
+ std::vector<SlotCursor> cursors_;
517
+ bool recurse_;
518
+
519
+ friend inline bool operator!=(
520
+ const slot_iterator_impl<Policy>& a,
521
+ const slot_iterator_impl<Policy>& b) {
522
+ // we are finished iteration when we have no more iteration SlotCursors.
523
+ // end is always an empty iterator with no cursors.
524
+ return (a.cursors_.empty() != b.cursors_.empty());
525
+ }
526
+ };
527
+
528
+ // This type represents lists of parameters, attributes, and
529
+ // submodules contained in the module. It is abstract because
530
+ // they are not stored directly in std::vectors but inside the
531
+ // module's IValue object itself.
532
+ template <typename Policy>
533
+ struct slot_list_impl {
534
+ using iterator = slot_iterator_impl<Policy>;
535
+ using const_iterator = slot_iterator_impl<Policy>;
536
+ using value_type = typename iterator::value_type;
537
+ slot_iterator_impl<Policy> begin() const {
538
+ return slot_iterator_impl<Policy>(module_, recurse_, return_module_);
539
+ }
540
+ slot_iterator_impl<Policy> end() const {
541
+ return slot_iterator_impl<Policy>();
542
+ }
543
+ size_t size() const {
544
+ if (!size_) {
545
+ size_ = size_t(0);
546
+ for ([[maybe_unused]] const value_type& _ : *(this)) {
547
+ ++*size_;
548
+ }
549
+ }
550
+ return *size_;
551
+ }
552
+
553
+ slot_list_impl(Module module, bool recurse, bool return_module)
554
+ : module_(std::move(module)),
555
+ recurse_(recurse),
556
+ return_module_(return_module),
557
+ size_(std::nullopt) {
558
+ if (!recurse && !return_module && Policy::all_slots) {
559
+ size_ = module_.num_slots();
560
+ }
561
+ }
562
+
563
+ private:
564
+ Module module_;
565
+ bool recurse_;
566
+ bool return_module_;
567
+ // size of this list, cached on first request
568
+ // when we need to filter the slot list
569
+ mutable std::optional<size_t> size_;
570
+ friend struct Module;
571
+ };
572
+
573
+ namespace detail {
574
+
575
+ // slot_iterator_impl always iterate over all the slots in a module,
576
+ // the Policy template argument determines slots should be returned and their
577
+ // types
578
+ struct TORCH_API ModulePolicy {
579
+ // the type of the value being returned
580
+ using value_type = Module;
581
+
582
+ // the logic for creating the type being returned, given the raw IValue
583
+ // of that object.
584
+ static value_type create(
585
+ const std::vector<detail::SlotCursor>& cursors,
586
+ IValue v) {
587
+ return Module(std::move(v).toObject());
588
+ }
589
+ // is slot i in typ something that this iterator should return, otherwise,
590
+ // we skip it.
591
+ static bool valid(const ClassTypePtr& typ, size_t i, const IValue& v) {
592
+ return typ->getAttribute(i)->is_module();
593
+ }
594
+ // are we going to return everything? If so, we can optimize the calculate
595
+ // of the size of the list.
596
+ static constexpr bool all_slots = false;
597
+ };
598
+
599
+ struct TORCH_API ParameterPolicy {
600
+ using value_type = at::Tensor;
601
+ static value_type create(
602
+ const std::vector<detail::SlotCursor>& cursors,
603
+ IValue v) {
604
+ return std::move(v).toTensor();
605
+ }
606
+ static bool valid(const ClassTypePtr& typ, size_t i, const IValue& v) {
607
+ return typ->is_parameter(i) && v.isTensor();
608
+ }
609
+ static constexpr bool all_slots = false;
610
+ };
611
+
612
+ struct TORCH_API BufferPolicy {
613
+ using value_type = at::Tensor;
614
+ static value_type create(
615
+ const std::vector<detail::SlotCursor>& cursors,
616
+ IValue v) {
617
+ return std::move(v).toTensor();
618
+ }
619
+ static bool valid(const ClassTypePtr& typ, size_t i, const IValue& v) {
620
+ return typ->getAttribute(i)->isSubtypeOf(*TensorType::get()) &&
621
+ typ->is_buffer(i);
622
+ }
623
+ static constexpr bool all_slots = false;
624
+ };
625
+
626
+ struct TORCH_API AttributePolicy {
627
+ using value_type = IValue;
628
+ static value_type create(
629
+ const std::vector<detail::SlotCursor>& cursors,
630
+ IValue v) {
631
+ return v;
632
+ }
633
+ static bool valid(const ClassTypePtr& typ, size_t i, const IValue& v) {
634
+ return true;
635
+ }
636
+ static constexpr bool all_slots = true;
637
+ };
638
+
639
+ // take a Policy object, and make a version of it that returns the slot.
640
+ // along with the fully qualified name of that slot. This is used for the named_
641
+ // variants like named_parameters().
642
+ template <typename Policy>
643
+ struct NamedPolicy {
644
+ using value_type = Named<typename Policy::value_type>;
645
+ static value_type create(
646
+ const std::vector<detail::SlotCursor>& cursors,
647
+ IValue v) {
648
+ std::string name;
649
+ if (cursors.size() == 1) {
650
+ name = (cursors.back().i_ == -1) ? "" : nameFragment(cursors.back());
651
+ } else {
652
+ std::ostringstream ss;
653
+ for (const auto i : c10::irange(cursors.size())) {
654
+ if (i > 0) {
655
+ ss << ".";
656
+ }
657
+ ss << nameFragment(cursors[i]);
658
+ }
659
+ name = ss.str();
660
+ }
661
+ return value_type{std::move(name), Policy::create(cursors, std::move(v))};
662
+ }
663
+ static bool valid(const ClassTypePtr& t, size_t i, const IValue& v) {
664
+ return Policy::valid(t, i, v);
665
+ }
666
+ static constexpr bool all_slots = Policy::all_slots;
667
+
668
+ private:
669
+ static std::string nameFragment(const detail::SlotCursor& f) {
670
+ return f.module_.type()->getAttributeName(f.i_);
671
+ }
672
+ };
673
+
674
+ } // namespace detail
675
+
676
+ TORCH_API bool& getInlineEverythingMode();
677
+
678
+ namespace script {
679
+ // We once had a `script::` namespace that was deleted. This is for backcompat
680
+ // of the public API; new code should not use this type alias.
681
+ using Module = ::torch::jit::Module;
682
+ using ExtraFilesMap = ::torch::jit::ExtraFilesMap;
683
+ } // namespace script
684
+
685
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/object.h ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/core/functional.h>
4
+ #include <ATen/core/ivalue.h>
5
+ #include <torch/csrc/jit/api/method.h>
6
+ #include <optional>
7
+
8
+ #include <utility>
9
+
10
+ namespace torch::jit {
11
+
12
+ struct Resolver;
13
+ using ResolverPtr = std::shared_ptr<Resolver>;
14
+
15
+ using ObjectPtr = c10::intrusive_ptr<c10::ivalue::Object>;
16
+
17
+ // Throw this in C++ land if `attr` fails. This will be converted to a Python
18
+ // AttributeError by the Python binding code
19
+ class ObjectAttributeError : public std::runtime_error {
20
+ public:
21
+ ObjectAttributeError(const std::string& what) : std::runtime_error(what) {}
22
+ };
23
+
24
+ struct TORCH_API Object {
25
+ Object() = default;
26
+ Object(const Object&) = default;
27
+ Object& operator=(const Object&) = default;
28
+ Object(Object&&) noexcept = default;
29
+ Object& operator=(Object&&) noexcept = default;
30
+ Object(ObjectPtr _ivalue) : _ivalue_(std::move(_ivalue)) {}
31
+ Object(std::shared_ptr<CompilationUnit> cu, const c10::ClassTypePtr& type);
32
+ Object(
33
+ c10::QualifiedName,
34
+ std::shared_ptr<CompilationUnit> cu,
35
+ bool shouldMangle = false);
36
+
37
+ ObjectPtr _ivalue() const {
38
+ TORCH_INTERNAL_ASSERT(_ivalue_);
39
+ return _ivalue_;
40
+ }
41
+
42
+ c10::ClassTypePtr type() const {
43
+ return _ivalue()->type();
44
+ }
45
+
46
+ struct Property {
47
+ std::string name;
48
+ Method getter_func;
49
+ std::optional<Method> setter_func;
50
+ };
51
+
52
+ void setattr(const std::string& name, c10::IValue v) {
53
+ if (_ivalue()->type()->hasConstant(name)) {
54
+ TORCH_CHECK(
55
+ false,
56
+ "Can't set constant '",
57
+ name,
58
+ "' which has value:",
59
+ _ivalue()->type()->getConstant(name));
60
+ } else if (auto slot = _ivalue()->type()->findAttributeSlot(name)) {
61
+ const c10::TypePtr& expected = _ivalue()->type()->getAttribute(*slot);
62
+ TORCH_CHECK(
63
+ v.type()->isSubtypeOf(*expected),
64
+ "Expected a value of type '",
65
+ expected->repr_str(),
66
+ "' for field '",
67
+ name,
68
+ "', but found '",
69
+ v.type()->repr_str(),
70
+ "'");
71
+ _ivalue()->setSlot(*slot, std::move(v));
72
+ } else {
73
+ TORCH_CHECK(false, "Module has no attribute '", name, "'");
74
+ }
75
+ }
76
+
77
+ c10::IValue attr(const std::string& name) const {
78
+ if (auto r = _ivalue()->type()->findAttributeSlot(name)) {
79
+ return _ivalue()->getSlot(*r);
80
+ }
81
+ if (auto r = _ivalue()->type()->findConstantSlot(name)) {
82
+ return _ivalue()->type()->getConstant(*r);
83
+ }
84
+ std::stringstream err;
85
+ err << _ivalue()->type()->repr_str() << " does not have a field with name '"
86
+ << name.c_str() << "'";
87
+ throw ObjectAttributeError(err.str());
88
+ }
89
+
90
+ c10::IValue attr(const std::string& name, c10::IValue or_else) const {
91
+ if (auto r = _ivalue()->type()->findAttributeSlot(name)) {
92
+ return _ivalue()->getSlot(*r);
93
+ }
94
+ if (auto r = _ivalue()->type()->findConstantSlot(name)) {
95
+ return _ivalue()->type()->getConstant(*r);
96
+ }
97
+ return or_else;
98
+ }
99
+
100
+ bool hasattr(const std::string& name) const {
101
+ return _ivalue()->type()->hasAttribute(name) ||
102
+ _ivalue()->type()->hasConstant(name);
103
+ }
104
+
105
+ // each object owns its methods. The reference returned here
106
+ // is guaranteed to stay valid until this module has been destroyed
107
+ Method get_method(const std::string& name) const {
108
+ if (auto method = find_method(name)) {
109
+ return *method;
110
+ }
111
+ TORCH_CHECK(false, "Method '", name, "' is not defined.");
112
+ }
113
+
114
+ const std::vector<Method> get_methods() const {
115
+ return c10::fmap(type()->methods(), [&](Function* func) {
116
+ return Method(_ivalue(), func);
117
+ });
118
+ }
119
+
120
+ bool has_property(const std::string& name) const {
121
+ for (const auto& prop : type()->properties()) {
122
+ if (prop.name == name) {
123
+ return true;
124
+ }
125
+ }
126
+ return false;
127
+ }
128
+
129
+ const Property get_property(const std::string& name) const {
130
+ for (const auto& prop : type()->properties()) {
131
+ if (prop.name == name) {
132
+ std::optional<Method> setter = std::nullopt;
133
+ if (prop.setter) {
134
+ setter = Method(_ivalue(), prop.setter);
135
+ }
136
+ return Property{
137
+ prop.name, Method(_ivalue(), prop.getter), std::move(setter)};
138
+ }
139
+ }
140
+ TORCH_CHECK(false, "Property '", name, "' is not defined.");
141
+ }
142
+
143
+ const std::vector<Property> get_properties() const {
144
+ return c10::fmap(type()->properties(), [&](ClassType::Property prop) {
145
+ std::optional<Method> setter = std::nullopt;
146
+ if (prop.setter) {
147
+ setter = Method(_ivalue(), prop.setter);
148
+ }
149
+ return Property{
150
+ std::move(prop.name),
151
+ Method(_ivalue(), prop.getter),
152
+ std::move(setter)};
153
+ });
154
+ }
155
+
156
+ std::optional<Method> find_method(const std::string& basename) const;
157
+
158
+ /// Run a method from this module.
159
+ ///
160
+ /// For example:
161
+ /// @code
162
+ /// IValue output = module->run("relu_script", a, b);
163
+ /// @endcode
164
+ ///
165
+ /// To get a compile a module from a source string, see torch::jit::compile
166
+ ///
167
+ /// @param method_name The name of the method to run
168
+ /// @param args Arguments to be passed to the method
169
+ /// @return An IValue containing the return value (or values if it is a tuple)
170
+ /// from the method
171
+ template <typename... Types>
172
+ IValue run_method(const std::string& method_name, Types&&... args) {
173
+ return get_method(method_name)({IValue(std::forward<Types>(args))...});
174
+ }
175
+
176
+ // so that C++ users can easily add methods
177
+ void define(const std::string& src, const ResolverPtr& resolver = nullptr);
178
+
179
+ size_t num_slots() const {
180
+ return _ivalue()->slots().size();
181
+ }
182
+
183
+ // shallow copy the object
184
+ Object copy() const;
185
+
186
+ // Copies all the attributes of the object recursively without creating new
187
+ // `ClassType`, including deepcopy of Tensors
188
+ Object deepcopy() const;
189
+
190
+ private:
191
+ // mutable be we lazily initialize in module_object.
192
+ mutable ObjectPtr _ivalue_;
193
+ };
194
+
195
+ namespace script {
196
+ // We once had a `script::` namespace that was deleted. This is for backcompat
197
+ // of the public API; new code should not use this type alias.
198
+ using Object = ::torch::jit::Object;
199
+ } // namespace script
200
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend.h ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/core/builtin_function.h>
4
+ #include <ATen/core/stack.h>
5
+ #include <torch/csrc/jit/backends/backend_interface.h>
6
+ #include <torch/custom_class.h>
7
+
8
+ namespace torch::jit {
9
+ namespace {
10
+ // NOLINTNEXTLINE(clang-diagnostic-unneeded-internal-declaration)
11
+ inline c10::FunctionSchema getIsAvailableSchema() {
12
+ c10::Argument self("self", c10::AnyType::get());
13
+ c10::Argument available("available", c10::BoolType::get());
14
+ c10::FunctionSchema preprocessor_schema(
15
+ "is_available",
16
+ /*overload_name=*/"",
17
+ /*arguments=*/{self},
18
+ /*returns=*/{available});
19
+ return preprocessor_schema;
20
+ }
21
+
22
+ constexpr static auto kBackendsNamespace = "__backends__";
23
+
24
+ // NOLINTNEXTLINE(clang-diagnostic-unneeded-internal-declaration)
25
+ inline c10::FunctionSchema getCompileSchema() {
26
+ c10::Argument self("self", c10::AnyType::get());
27
+ c10::Argument mod("processed", c10::AnyType::get());
28
+ auto any_dict_ty =
29
+ c10::DictType::create(c10::StringType::get(), c10::AnyType::get());
30
+ c10::Argument method_compile_spec("method_compile_spec", any_dict_ty);
31
+ c10::Argument handles("handles", any_dict_ty);
32
+
33
+ c10::FunctionSchema compile_schema(
34
+ "compile",
35
+ /*overload_name=*/"",
36
+ /*arguments=*/{self, mod, method_compile_spec},
37
+ /*returns=*/{handles});
38
+ return compile_schema;
39
+ }
40
+
41
+ // NOLINTNEXTLINE(clang-diagnostic-unneeded-internal-declaration)
42
+ inline c10::FunctionSchema getExecuteSchema() {
43
+ auto any_list_ty = c10::ListType::create(c10::AnyType::get());
44
+ c10::Argument self("self", c10::AnyType::get());
45
+ c10::Argument handle("handle", c10::AnyType::get());
46
+ c10::Argument input("input", any_list_ty);
47
+ c10::Argument output("output", any_list_ty);
48
+ return c10::FunctionSchema(
49
+ "execute",
50
+ /*overload_name=*/"",
51
+ /*arguments=*/{self, handle, input},
52
+ /*returns=*/{output});
53
+ }
54
+
55
+ template <typename TBackendInterface>
56
+ std::function<void(Stack&)> getIsAvailableFunc() {
57
+ return [](Stack& stack) {
58
+ auto self = pop(stack).toCustomClass<TBackendInterface>();
59
+ auto ret = self->is_available();
60
+ push(stack, ret);
61
+ };
62
+ }
63
+
64
+ template <typename TBackendInterface>
65
+ std::function<void(Stack&)> getCompileFunc() {
66
+ return [](Stack& stack) {
67
+ auto method_compile_spec = pop(stack).toGenericDict();
68
+ auto processed = pop(stack);
69
+ auto self = pop(stack).toCustomClass<TBackendInterface>();
70
+ auto ret = self->compile(processed, method_compile_spec);
71
+ push(stack, ret);
72
+ };
73
+ }
74
+
75
+ template <typename TBackendInterface>
76
+ std::function<void(Stack&)> getExecuteFunc() {
77
+ return [](Stack& stack) {
78
+ auto args = pop(stack);
79
+ auto handle = pop(stack);
80
+ auto self = pop(stack);
81
+ auto backend = self.toCustomClass<TBackendInterface>();
82
+ auto res = backend->execute(handle, args.toList());
83
+ push(stack, res);
84
+ };
85
+ }
86
+ } // namespace
87
+
88
+ // Static registration API for backends.
89
+ template <class TBackendInterface>
90
+ class backend {
91
+ static_assert(
92
+ std::is_base_of_v<PyTorchBackendInterface, TBackendInterface>,
93
+ "torch::jit::backend<T> requires T to inherit from PyTorchBackendInterface");
94
+ std::string backend_name_;
95
+
96
+ public:
97
+ // Registers a new backend with /p name, and the given /p preprocess
98
+ // function.
99
+ backend(const std::string& name) : backend_name_(name) {
100
+ static auto cls = torch::class_<TBackendInterface>(kBackendsNamespace, name)
101
+ .def(torch::init<>())
102
+ ._def_unboxed(
103
+ "is_available",
104
+ getIsAvailableFunc<TBackendInterface>(),
105
+ getIsAvailableSchema())
106
+ ._def_unboxed(
107
+ "compile",
108
+ getCompileFunc<TBackendInterface>(),
109
+ getCompileSchema())
110
+ ._def_unboxed(
111
+ "execute",
112
+ getExecuteFunc<TBackendInterface>(),
113
+ getExecuteSchema());
114
+ }
115
+ };
116
+
117
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_handler.h ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <ATen/core/ivalue.h>
3
+
4
+ #include <torch/csrc/jit/backends/backend_detail.h>
5
+ #include <torch/csrc/jit/ir/ir.h>
6
+ #include <torch/csrc/jit/ir/scope.h>
7
+
8
+ #include <atomic>
9
+
10
+ namespace torch::jit {
11
+
12
+ /*
13
+ * BackendDebugHandleManager is responsible for issuing debug handles to
14
+ * backends. Debug handles are associated with nodes of a graph.
15
+ * BackendDebugHandleManager also maintains a map
16
+ * [debug-handle, DebugInfoTuple = {source range, inlined callstack ptr]} that
17
+ * will help generate a callstack for exception raised using debug handles.
18
+ * Effectively debug handles are something that is given to backend and later
19
+ * when an exception occurs in the backend, backend can tell, using debug
20
+ * handle, that an exception occurred here. Then the runtime can generate
21
+ * callstack correspoding to the exception.
22
+ * There are two parts to BackendDebugHandleManager:
23
+ * 1. static std::atomic debug_handle
24
+ * 2. Map of [debug-handle, DebugInfoTuple]
25
+ *
26
+ * About 1:
27
+ * Why do they have to be unique. The reason is that by ensuring
28
+ * uniqueness of debug handles, we remove the burden of another layer of
29
+ * mapping where we need to say this set of debug handles were generated for
30
+ * this lowered module or this bytecode function. This simplifies the API for
31
+ * serialization since debug handles can uniquely identify DebugInfoTuple.
32
+ * Thus simplifies the runtime API for throwing exception. Exception throwing
33
+ * only needs to know debug_handle and not which module or method threw it.
34
+ * There are 2 issues to keep in mind, though,for static std::atomic
35
+ * debug_handle: A. Performance implications of using atomic variable. However
36
+ * this is only used for compilation so we assume to absorb some of that
37
+ * penalty. Plus if there is no contention then we should have less to worry
38
+ * about. B. If repeated compilation is part of a long running process then we
39
+ * may overflow int64_t. We may detect and fail on this. For now this is not
40
+ * done.
41
+ *
42
+ * Now about 2:
43
+ * There are two usecases for [debug-handle, DebugInfoTuple]
44
+ * A. During bytecode generation the DebugInfoTuple corresponding to the nodes
45
+ * of the inlined graph being serialized, are stored in this object and a
46
+ * unique debug handle is returned. This unique debug handle is stored in
47
+ * mobile_debug info for pytorch lite models. It will be used for raising
48
+ * exceptions as well as profiling. B. During backend lowering, each backend's
49
+ * preprocess/compile method can compile method's graph and serialize those
50
+ * methods. Once the method is lowered to backend, graph is essentially lost.
51
+ * Without access to graph it is hard to generate model level debug info. Thus
52
+ * the debug handles provide a way to map nodes of the graph to the model level
53
+ * debug info.
54
+ *
55
+ * During byte-code model serialization, [debug-handle, DebugInfoTuple] is
56
+ * serialized. Now we know a. debug handles and b. how to map debug handles to
57
+ * model source code. Thus we can either do eager symbolication by converting
58
+ * debug handles to corresponding source code at runtime, or do lazy
59
+ * symbolicattion offline.
60
+ *
61
+ * Note that it is not necessary to serialize [debug-handle, DebugInfoTuple]
62
+ * corresponding to lowered backend if the lowering process, that is
63
+ * preprocess/compile, and execution happens in the same session, then eager
64
+ * symbolication can be employed.
65
+ *
66
+ * Now how does BackendDebugHandleManager capture all of the above?
67
+ * By providing two API.
68
+ * 1. getNextDebugHandle which given a Node* returns a unique debug handle,
69
+ * that will uniquely identify DebugInfoTuple.
70
+ * and
71
+ * 2. getCallStackPtrMap which returns the map
72
+ * [debug-handle, DebugInfoTuple]
73
+ *
74
+ * 1 provides debug handles to backends and 2 provides runtime a way to map
75
+ * debug handles to source level debug info.
76
+ *
77
+ * So why does debug handle map to DebugInfoTuple = {source range and inlined
78
+ * cs}? {debug_handle, source_range_tag, serialized_callstack} Take this
79
+ * example: class L(nn.Module): def __init__(self) -> None:
80
+ * ...
81
+ * def forward(self, x):
82
+ * return x * 5
83
+ * class M(nn.Module):
84
+ * def __init__(self) -> None:
85
+ * ...
86
+ * def forward(self, x):
87
+ * return x - 2
88
+ * class N(nn.Module):
89
+ * def __init__(self) -> None:
90
+ * self.m = M()
91
+ * def forward(self, x):
92
+ * return self.m(x) + 3
93
+ * m = torch.jit.script(N())
94
+ * Once you inline m's forward method, m.forward.graph will look something
95
+ * like this
96
+ * graph(%self...):
97
+ * %x = aten::mul(..)
98
+ * %x = aten::sub(x, ..)
99
+ * %y = aten::add(x, ..)
100
+ * ..
101
+ * Inlined callstack ptr for these two nodes will look like:
102
+ * aten::mul's inlined CS (callstack): [N.forward, source range] -> [M.forward,
103
+ * source range] aten::sub's inlined CS (callstack): [N.forward, source range]
104
+ * aten::add's inlined CS: null
105
+ * mul node's inlined CS contains only information about the callsites' source
106
+ * range The information about mul node's source range ('return x * 5') is not
107
+ * available in its inlined CS. It is rather part of node's source range
108
+ * instead of inlined CS. Thus to get full stack: [N.forward, source range] ->
109
+ * [M.forward, source range] -> [aten::mul's source range] We need to track
110
+ * mul's source range and inlined CS both.
111
+ */
112
+
113
+ using BackendDebugInfoMapType =
114
+ std::unordered_map<torch::jit::DebugHandleType, DebugInfoTuple>;
115
+
116
+ /*
117
+ * This class is used to generate debug info map.
118
+ * backend's preprocess will call generate_debug_handles (see
119
+ * backend_detail.cpp), which uses debug_handle_manager to generate debug
120
+ * handles. When lowering process finishes, calling stopRecording will
121
+ * return debug info map from debug_handle_manager
122
+ */
123
+ class TORCH_API BackendDebugInfoRecorder {
124
+ public:
125
+ BackendDebugInfoRecorder() = default;
126
+ int64_t getNextDebugHandle(const Node* node);
127
+ // Reason this is not done as RAII is that work done in stopRecording
128
+ // can throw, and throwing with dtor will call terminate and thus voids any
129
+ // exception catching at a higher level.
130
+ BackendDebugInfoMapType stopRecording();
131
+ NodeToDebugHandle generate_debug_handles(const std::shared_ptr<Graph>& graph);
132
+
133
+ private:
134
+ static std::atomic<DebugHandleType> unique_debug_handle_;
135
+ BackendDebugInfoMapType handles_to_inlined_callstack_ptrs_;
136
+ };
137
+
138
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_info.h ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #ifndef BUILD_LITE_INTERPRETER
4
+ #include <torch/csrc/jit/backends/backend_debug_handler.h>
5
+ #endif
6
+ #include <torch/custom_class.h>
7
+
8
+ namespace torch::jit {
9
+
10
+ constexpr static auto kBackendUtilsNamespace = "backendutils";
11
+ constexpr static auto kBackendDebugInfoClass = "BackendDebugInfo";
12
+
13
+ #ifndef BUILD_LITE_INTERPRETER
14
+ /*
15
+ * Custom class for holding debug information in lowered modules, intended
16
+ * purely for keeping this information to be later serialized outside of the
17
+ * lowered module itself.
18
+ * Its usage pattern is:
19
+ * 1. LoweredModule declares an instance of this class in __backend_debug_info
20
+ * 2. During serialization, __backend_debug_info is used to obtain the debug
21
+ * information.
22
+ * 3. The contents of LoweredModule.__backend_debug_info are not serialized
23
+ * within the LoweredModule itself.
24
+ */
25
+ class TORCH_API PyTorchBackendDebugInfo : public torch::CustomClassHolder {
26
+ public:
27
+ PyTorchBackendDebugInfo() = default;
28
+
29
+ std::optional<BackendDebugInfoMapType>& getDebugInfoMap() {
30
+ return debug_info_map_;
31
+ }
32
+
33
+ void setDebugInfoMap(BackendDebugInfoMapType&& debug_info_map) {
34
+ debug_info_map_ = std::move(debug_info_map);
35
+ }
36
+
37
+ private:
38
+ std::optional<BackendDebugInfoMapType> debug_info_map_;
39
+ };
40
+
41
+ #else
42
+
43
+ /*
44
+ * Dummy instance exists for the following reason:
45
+ * __backend_debug_info is of type BackendDebugInfo which is a torchbind'
46
+ * class backed by cpp class PyTorchBackendDebugInfo.
47
+ * PyTorchBackendDebugInfo, depends on ir.h., scope.h, source_range etc.
48
+ * We dont include this on lite interpreter side. Thus on lite interpreter side
49
+ * we cannot have valid definition of PyTorchBackendDebugInfo. However we do not
50
+ * need valid instance of __backend_debug_info in lite interpreter anyway as we
51
+ * dont serialize this info as part of LowerdModule as mentioned ealrier.
52
+ * However since LoweredModule has registered attribute of __backend_debug_info
53
+ * we still need to make sure that BackendDebugInfo is registered with
54
+ * TorchScript. However in this instance it does not have to be backed by
55
+ * PyTorchBackendDebugInfo, so we create a dummy PyTorchBackendDebugInfoDummy
56
+ * just for this purpose.
57
+ */
58
+ class PyTorchBackendDebugInfoDummy : public torch::CustomClassHolder {
59
+ public:
60
+ PyTorchBackendDebugInfoDummy() = default;
61
+ };
62
+ #endif
63
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_detail.h ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/api/module.h>
4
+
5
+ #include <ATen/core/jit_type.h>
6
+
7
+ #include <functional>
8
+
9
+ namespace torch::jit {
10
+
11
+ using DebugHandleType = int64_t;
12
+
13
+ using NodeToDebugHandle = std::unordered_map<Node*, DebugHandleType>;
14
+
15
+ using BackendDebugHandleGenerator =
16
+ std::function<NodeToDebugHandle(const std::shared_ptr<Graph>&)>;
17
+
18
+ namespace detail {
19
+
20
+ using BackendPreprocessFunction = std::function<c10::IValue(
21
+ const Module&,
22
+ const c10::Dict<IValue, IValue>&,
23
+ const BackendDebugHandleGenerator& generate_debug_handles)>;
24
+
25
+ TORCH_API void registerBackendPreprocessFunction(
26
+ const std::string& name,
27
+ const BackendPreprocessFunction& preprocess);
28
+
29
+ bool hasBackendPreprocessFunction(const std::string& name);
30
+
31
+ BackendPreprocessFunction getBackendPreprocessFunction(const std::string& name);
32
+
33
+ TORCH_API Module codegen_backend_module(
34
+ const std::string& backend_name,
35
+ const Module& orig_module,
36
+ const c10::Dict<IValue, IValue>& method_compile_spec,
37
+ const c10::DictTypePtr& any_dict_ty);
38
+ } // namespace detail
39
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_exception.h ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <c10/util/Exception.h>
3
+
4
+ #include <utility>
5
+
6
+ namespace c10 {
7
+ class TORCH_API BackendRuntimeException : public c10::Error {
8
+ public:
9
+ // Use debug_handle to throw exception
10
+ BackendRuntimeException(
11
+ SourceLocation loc,
12
+ std::string msg,
13
+ int64_t debug_handle)
14
+ : c10::Error(loc, std::move(msg)) {
15
+ debug_handles.push_back(debug_handle);
16
+ }
17
+ // If rethrowing, can push another debug_handle
18
+ // This is useful in couple of scenarios.
19
+ // 1. A submodule is lowered and lite interperter has CallMethod
20
+ // to lowered module's method. In this case lowered module will throw with
21
+ // a handle, plus there will be another debug handle corresponding
22
+ // to the CallMethod node in lite interpreter. Both together give complete
23
+ // trace. This function allows lite interpreter to rethrow with debug
24
+ // handle it has for CallMethod.
25
+ // 2. Another scenarios is when lite interperter can make function calls or
26
+ // the lowered backend also has function call ability. Thus we have
27
+ // multiple function frames. Now we need a stack of handles to symbolicate
28
+ // entire stack trace.
29
+ void pushDebugHandle(int64_t debug_handle) {
30
+ debug_handles.push_back(debug_handle);
31
+ }
32
+ const std::vector<int64_t>& getDebugHandles() {
33
+ return debug_handles;
34
+ }
35
+
36
+ private:
37
+ // Stores stack of debug handles.
38
+ std::vector<int64_t> debug_handles;
39
+ };
40
+
41
+ } // namespace c10
42
+ #define TORCH_DELEGATED_BACKEND_THROW(cond, msg, debug_handle) \
43
+ if (C10_UNLIKELY_OR_CONST(!(cond))) { \
44
+ throw ::c10::BackendRuntimeException( \
45
+ {__func__, __FILE__, static_cast<uint32_t>(__LINE__)}, \
46
+ msg, \
47
+ debug_handle); \
48
+ }
49
+
50
+ #define TORCH_DELEGATED_BACKEND_RETHROW(e, debug_handle) \
51
+ do { \
52
+ e.pushDebugHandle(debug_handle); \
53
+ throw; \
54
+ } while (false)
55
+
56
+ #define DEBUG_HANDLE_UNKNOWN -1
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_init.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/python/pybind.h>
4
+ #include <torch/csrc/utils/pybind.h>
5
+
6
+ namespace torch::jit {
7
+ // Initialize Python bindings for JIT to_<backend> functions.
8
+ void initJitBackendBindings(PyObject* module);
9
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_interface.h ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/custom_class.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Interface for a JIT backend.
8
+ class TORCH_API PyTorchBackendInterface : public torch::CustomClassHolder {
9
+ public:
10
+ PyTorchBackendInterface() noexcept;
11
+ ~PyTorchBackendInterface() override;
12
+
13
+ // Returns true if the backend is available to process delegation calls.
14
+ virtual bool is_available() = 0;
15
+
16
+ // Compile the module contained in \p processed using the details provided in
17
+ // \p method_compile_spec for each module method that should be compiled for
18
+ // the backend. \p method_compile_spec should be of type Dict<string, Any>.
19
+ // \returns a dictionary of type Dict<string, Any> that contains a backend
20
+ // handle each method that can run on the backend (i.e. each key in \p
21
+ // method_compile_spec).
22
+ virtual c10::impl::GenericDict compile(
23
+ c10::IValue processed,
24
+ c10::impl::GenericDict method_compile_spec) = 0;
25
+
26
+ // Execute the method specified by \p handle using \p inputs. \returns the
27
+ // outputs as a tuple.
28
+ virtual c10::impl::GenericList execute(
29
+ c10::IValue handle,
30
+ c10::impl::GenericList inputs) = 0;
31
+ };
32
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_preprocess.h ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/backends/backend_detail.h>
4
+ namespace torch::jit {
5
+ class backend_preprocess_register {
6
+ std::string backend_name_;
7
+
8
+ public:
9
+ backend_preprocess_register(
10
+ const std::string& name,
11
+ const detail::BackendPreprocessFunction& preprocess)
12
+ : backend_name_(name) {
13
+ detail::registerBackendPreprocessFunction(name, preprocess);
14
+ }
15
+ };
16
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_resolver.h ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/frontend/resolver.h>
4
+
5
+ namespace torch::jit {
6
+ // Create a Resolver for use in generating LoweredModules for specific backends.
7
+ TORCH_API std::shared_ptr<Resolver> loweredModuleResolver();
8
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/codegen/cuda/interface.h ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <c10/macros/Export.h>
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+ #include <torch/csrc/jit/passes/pass_manager.h>
6
+ #include <torch/csrc/jit/runtime/profiling_record.h>
7
+
8
+ /*
9
+ * This file contains APIs for cuda fuser;
10
+ *
11
+ * We use an empty static struct to hold the function pointers, which are
12
+ * registered separately. This is to support cpu-only compilation.
13
+ * Registration is done in torch/csrc/jit/codegen/cuda/register_interface.cpp
14
+ */
15
+
16
+ namespace torch::jit::fuser::cuda {
17
+
18
+ TORCH_API std::atomic<bool>& getCudaFusionGuardMode();
19
+
20
+ TORCH_API bool getSingletonFusion();
21
+ TORCH_API bool setSingletonFusion(bool value);
22
+ TORCH_API bool getHorizontalFusion();
23
+ TORCH_API bool setHorizontalFusion(bool value);
24
+
25
+ // dummy struct to allow API registration
26
+ struct CudaFuserInterface {
27
+ void (*fn_compile_n)(Node*) = nullptr;
28
+ void (*fn_run_n_s)(const Node*, Stack&) = nullptr;
29
+ void (*fn_fuse_graph)(std::shared_ptr<Graph>&) = nullptr;
30
+ bool (*fn_can_fuse_n)(const Node*) = nullptr;
31
+ void (*fn_insert_profile_inodes)(ProfilingRecord* pr) = nullptr;
32
+ bool (*fn_profile_n)(const Node*) = nullptr;
33
+ bool (*fn_skip_n)(const std::string&, bool flip) = nullptr;
34
+ };
35
+
36
+ // Get interface, this is used by registration and user facing API internally
37
+ TORCH_API CudaFuserInterface* getFuserInterface();
38
+
39
+ TORCH_API void compileFusionGroup(Node* fusion_node);
40
+ TORCH_API void runFusionGroup(const Node* fusion_node, Stack& stack);
41
+ TORCH_API void fuseGraph(std::shared_ptr<Graph>&);
42
+ TORCH_API bool canFuseNode(const Node* node);
43
+ TORCH_API void InsertProfileNodesForCUDAFuser(ProfilingRecord* pr);
44
+ TORCH_API bool profileNode(const Node* node);
45
+
46
+ TORCH_API bool skipNode(const std::string& symbol_str, bool flip = true);
47
+
48
+ TORCH_API bool isEnabled();
49
+ TORCH_API bool setEnabled(bool is_enabled);
50
+ TORCH_API bool canBeEnabled();
51
+
52
+ } // namespace torch::jit::fuser::cuda
lib/python3.12/site-packages/torch/include/torch/csrc/jit/jit_log.h ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <torch/csrc/Export.h>
3
+ #include <memory>
4
+ #include <ostream>
5
+ #include <string>
6
+ #include <unordered_map>
7
+
8
+ // `TorchScript` offers a simple logging facility that can enabled by setting an
9
+ // environment variable `PYTORCH_JIT_LOG_LEVEL`.
10
+
11
+ // Logging is enabled on a per file basis. To enable logging in
12
+ // `dead_code_elimination.cpp`, `PYTORCH_JIT_LOG_LEVEL` should be
13
+ // set to `dead_code_elimination.cpp` or, simply, to `dead_code_elimination`
14
+ // (i.e. `PYTORCH_JIT_LOG_LEVEL=dead_code_elimination`).
15
+
16
+ // Multiple files can be logged by separating each file name with a colon `:` as
17
+ // in the following example,
18
+ // `PYTORCH_JIT_LOG_LEVEL=dead_code_elimination:guard_elimination`
19
+
20
+ // There are 3 logging levels available for your use ordered by the detail level
21
+ // from lowest to highest.
22
+
23
+ // * `GRAPH_DUMP` should be used for printing entire graphs after optimization
24
+ // passes
25
+ // * `GRAPH_UPDATE` should be used for reporting graph transformations (i.e.
26
+ // node deletion, constant folding, etc)
27
+ // * `GRAPH_DEBUG` should be used for providing information useful for debugging
28
+ // the internals of a particular optimization pass or analysis
29
+
30
+ // The default logging level is `GRAPH_DUMP` meaning that only `GRAPH_DUMP`
31
+ // statements will be enabled when one specifies a file(s) in
32
+ // `PYTORCH_JIT_LOG_LEVEL`.
33
+
34
+ // `GRAPH_UPDATE` can be enabled by prefixing a file name with an `>` as in
35
+ // `>alias_analysis`.
36
+ // `GRAPH_DEBUG` can be enabled by prefixing a file name with an `>>` as in
37
+ // `>>alias_analysis`.
38
+ // `>>>` is also valid and **currently** is equivalent to `GRAPH_DEBUG` as there
39
+ // is no logging level that is higher than `GRAPH_DEBUG`.
40
+
41
+ namespace torch::jit {
42
+
43
+ struct Node;
44
+ struct Graph;
45
+
46
+ enum class JitLoggingLevels {
47
+ GRAPH_DUMP = 0,
48
+ GRAPH_UPDATE,
49
+ GRAPH_DEBUG,
50
+ };
51
+
52
+ TORCH_API std::string get_jit_logging_levels();
53
+
54
+ TORCH_API void set_jit_logging_levels(std::string level);
55
+
56
+ TORCH_API void set_jit_logging_output_stream(std::ostream& out_stream);
57
+
58
+ TORCH_API std::ostream& get_jit_logging_output_stream();
59
+
60
+ TORCH_API std::string getHeader(const Node* node);
61
+
62
+ TORCH_API std::string log_function(const std::shared_ptr<Graph>& graph);
63
+
64
+ TORCH_API ::torch::jit::JitLoggingLevels jit_log_level();
65
+
66
+ // Prefix every line in a multiline string \p IN_STR with \p PREFIX.
67
+ TORCH_API std::string jit_log_prefix(
68
+ const std::string& prefix,
69
+ const std::string& in_str);
70
+
71
+ TORCH_API std::string jit_log_prefix(
72
+ ::torch::jit::JitLoggingLevels level,
73
+ const char* fn,
74
+ int l,
75
+ const std::string& in_str);
76
+
77
+ TORCH_API bool is_enabled(
78
+ const char* cfname,
79
+ ::torch::jit::JitLoggingLevels level);
80
+
81
+ TORCH_API std::ostream& operator<<(
82
+ std::ostream& out,
83
+ ::torch::jit::JitLoggingLevels level);
84
+
85
+ #define JIT_LOG(level, ...) \
86
+ if (is_enabled(__FILE__, level)) { \
87
+ ::torch::jit::get_jit_logging_output_stream() \
88
+ << ::torch::jit::jit_log_prefix( \
89
+ level, __FILE__, __LINE__, ::c10::str(__VA_ARGS__)); \
90
+ }
91
+
92
+ // tries to reconstruct original python source
93
+ #define SOURCE_DUMP(MSG, G) \
94
+ JIT_LOG( \
95
+ ::torch::jit::JitLoggingLevels::GRAPH_DUMP, \
96
+ MSG, \
97
+ "\n", \
98
+ ::torch::jit::log_function(G));
99
+ // use GRAPH_DUMP for dumping graphs after optimization passes
100
+ #define GRAPH_DUMP(MSG, G) \
101
+ JIT_LOG( \
102
+ ::torch::jit::JitLoggingLevels::GRAPH_DUMP, MSG, "\n", (G)->toString());
103
+ // use GRAPH_UPDATE for reporting graph transformations (i.e. node deletion,
104
+ // constant folding, CSE)
105
+ #define GRAPH_UPDATE(...) \
106
+ JIT_LOG(::torch::jit::JitLoggingLevels::GRAPH_UPDATE, __VA_ARGS__);
107
+ // use GRAPH_DEBUG to provide information useful for debugging a particular opt
108
+ // pass
109
+ #define GRAPH_DEBUG(...) \
110
+ JIT_LOG(::torch::jit::JitLoggingLevels::GRAPH_DEBUG, __VA_ARGS__);
111
+ // use GRAPH_EXPORT to export a graph so that the IR can be loaded by a script
112
+ #define GRAPH_EXPORT(MSG, G) \
113
+ JIT_LOG( \
114
+ ::torch::jit::JitLoggingLevels::GRAPH_DEBUG, \
115
+ MSG, \
116
+ "\n<GRAPH_EXPORT>\n", \
117
+ (G)->toString(), \
118
+ "</GRAPH_EXPORT>");
119
+
120
+ #define GRAPH_DUMP_ENABLED \
121
+ (is_enabled(__FILE__, ::torch::jit::JitLoggingLevels::GRAPH_DUMP))
122
+ #define GRAPH_UPDATE_ENABLED \
123
+ (is_enabled(__FILE__, ::torch::jit::JitLoggingLevels::GRAPH_UPDATE))
124
+ #define GRAPH_DEBUG_ENABLED \
125
+ (is_enabled(__FILE__, ::torch::jit::JitLoggingLevels::GRAPH_DEBUG))
126
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/jit_opt_limit.h ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <torch/csrc/Export.h>
3
+ #include <string>
4
+ #include <unordered_map>
5
+
6
+ // `TorchScript` offers a simple optimization limit checker
7
+ // that can be configured through environment variable `PYTORCH_JIT_OPT_LIMIT`.
8
+ // The purpose is to limit how many optimization you can make per pass.
9
+ // This is useful for debugging any passes.
10
+
11
+ // Opt limit checker is enabled on a per file basis (hence per pass). For
12
+ // example, in `constant_propagation.cpp`, `PYTORCH_JIT_OPT_LIMIT` should be set
13
+ // to `constant_propagation=<opt_limit>` or, simply, to
14
+ // `constant_propagation=<opt_limit>` where <opt_limit> is the number of
15
+ // optimizations you want to make for the pass. (i.e.
16
+ // `PYTORCH_JIT_OPT_LIMIT="constant_propagation=<opt_limit>"`).
17
+
18
+ // Multiple files can be configured by separating each file name with a colon
19
+ // `:` as in the following example,
20
+ // `PYTORCH_JIT_OPT_LIMIT="constant_propagation=<opt_limit>:dead_code_elimination=<opt_limit>"`
21
+
22
+ // You can call opt limiter by calling JIT_OPT_ALLOWED. It will return true if
23
+ // we haven't reached the optimization limit yet. Otherwise, it will return
24
+ // false. Typical usage:
25
+
26
+ // if (!JIT_OPT_ALLOWED) {
27
+ // GRAPH_DUMP(...); //supplied from jit_log
28
+ // return;
29
+ // }
30
+
31
+ namespace torch::jit {
32
+
33
+ TORCH_API bool opt_limit(const char* pass_name);
34
+
35
+ #define JIT_OPT_ALLOWED opt_limit(__FILE__)
36
+
37
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/add_if_then_else.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ TORCH_API bool AddIfThenElseOp(std::shared_ptr<Graph>& graph);
8
+
9
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/annotate_warns.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ TORCH_API void AnnotateWarns(const std::shared_ptr<Graph>& graph);
8
+
9
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/autocast.h ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #pragma once
3
+
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+
6
+ namespace torch::jit {
7
+
8
+ TORCH_API void Autocast(const std::shared_ptr<Graph>& graph);
9
+
10
+ TORCH_API bool setAutocastMode(bool value);
11
+ TORCH_API bool autocastEnabled();
12
+
13
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/bailout_graph.h ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/ATen.h>
4
+ #include <ATen/core/ivalue.h>
5
+ #include <ATen/core/jit_type.h>
6
+ #include <ATen/core/stack.h>
7
+ #include <torch/csrc/Export.h>
8
+ #include <torch/csrc/jit/ir/ir.h>
9
+
10
+ #include <list>
11
+ #include <vector>
12
+
13
+ namespace torch::jit {
14
+
15
+ // Replaces prim::Guard nodes with prim::BailOut nodes and
16
+ // computes sets of inputs needed to resume execution at
17
+ // bailout points
18
+ TORCH_API void InsertBailOuts(std::shared_ptr<Graph> graph);
19
+
20
+ // Builds a bailout graph into `target` (which is an empty graph)
21
+ // for a given bailout point `bailout_index`
22
+ // from the original graph `orig` (the original unoptimized graph)
23
+ // BailOut graphs allow Interpreter to resume
24
+ // execution of the (un/de)optimized graph (i.e.
25
+ // a graph that doesn't rely on any assumptions derived from
26
+ // on profiling information) from a given BailOut point
27
+ // should any of the assumptions fail for an actual input.
28
+ TORCH_API std::shared_ptr<Graph> BuildBailOutGraphFrom(
29
+ int64_t bailout_index,
30
+ const std::shared_ptr<Graph>& orig,
31
+ const std::shared_ptr<Graph>& target);
32
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/batch_mm.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ TORCH_API void BatchMM(std::shared_ptr<Graph>& graph);
8
+
9
+ }
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/canonicalize.h ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ TORCH_API std::shared_ptr<Graph> Canonicalize(
8
+ const std::shared_ptr<Graph>& graph,
9
+ bool keep_unique_names = true);
10
+
11
+ TORCH_API void CanonicalizeOutputs(std::shared_ptr<Graph>& graph);
12
+
13
+ TORCH_API std::optional<const Use> firstOrLastUse(Value* v, bool find_first);
14
+
15
+ TORCH_API bool isBeforeOrAfter(
16
+ const Use& a,
17
+ const Use& b,
18
+ bool checking_before);
19
+
20
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/canonicalize_graph_fuser_ops.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ TORCH_API void CanonicalizeOps(const std::shared_ptr<Graph>& graph);
8
+
9
+ }
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/check_strict_fusion.h ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #pragma once
3
+
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+
6
+ namespace torch::jit {
7
+
8
+ TORCH_API void CheckStrictFusion(std::shared_ptr<Graph>& graph);
9
+
10
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/clear_profiling.h ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/ATen.h>
4
+ #include <ATen/core/ivalue.h>
5
+ #include <ATen/core/jit_type.h>
6
+ #include <torch/csrc/Export.h>
7
+ #include <torch/csrc/jit/ir/ir.h>
8
+
9
+ namespace torch::jit {
10
+
11
+ TORCH_API void unprofileGraphInputs(const std::shared_ptr<Graph>& graph);
12
+ TORCH_API void unprofileBlock(Block* start_block);
13
+ // Unprofiles all the node outputs in a block.
14
+
15
+ TORCH_API void ClearProfilingInformation(const std::shared_ptr<Graph>& graph);
16
+
17
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/clear_undefinedness.h ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <ATen/ATen.h>
4
+ #include <ATen/core/ivalue.h>
5
+ #include <ATen/core/jit_type.h>
6
+ #include <torch/csrc/Export.h>
7
+ #include <torch/csrc/jit/ir/ir.h>
8
+
9
+ namespace torch::jit {
10
+
11
+ // Undefinedness makes argument matching fail for regular tensor operations
12
+ // if 1+ arguments are undefined or possibly undefined tensors.
13
+ // Technically, undefined tensors are **not** tensors as the regular tensor
14
+ // operations do not know how to handle them.
15
+ // However, in practice, there are guards and conversion operators that
16
+ // **always** gate regular operations if undefined tensors may be present
17
+ // Eventually, we would love to move to the world where we use optionals
18
+ // in lieu of undefined tensors.
19
+ // When this happens, this pass will be removed
20
+ TORCH_API void ClearUndefinedness(const std::shared_ptr<Graph>& graph);
21
+
22
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/common_subexpression_elimination.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ TORCH_API bool EliminateCommonSubexpression(
8
+ const std::shared_ptr<Graph>& graph);
9
+ }
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/concat_opt.h ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Eliminates common inputs among `aten::cat` ops.
8
+ TORCH_API bool EliminateConcatCommonInputs(const std::shared_ptr<Graph>& graph);
9
+
10
+ // Expands `aten::cat` ops into `aten::copy` ops and eliminates redudancies
11
+ // in the buffers used for concatenation if possible.
12
+ TORCH_API void ExpandConcatAndEliminateRedundancy(
13
+ const std::shared_ptr<Graph>& graph);
14
+
15
+ TORCH_API bool CombineConcats(const std::shared_ptr<Graph>& graph);
16
+
17
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/constant_pooling.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ TORCH_API void ConstantPooling(const std::shared_ptr<Graph>& graph);
8
+
9
+ }
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/constant_propagation.h ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Runs constant propagation on all objects unless ignore_custom_classes is
8
+ // specified as true, in which case user defined classes are skipped. This is
9
+ // useful to prevent early fusion of packing operations, which end up lowering
10
+ // away information about their constructors (e.g. packed::linear_clamp_prepack
11
+ // and prepacked::conv2d_clamp_prepack)
12
+ // Returns True if the pass made a change to the graph
13
+ TORCH_API bool ConstantPropagation(
14
+ std::shared_ptr<Graph>& graph,
15
+ bool ignore_custom_classes = false);
16
+
17
+ // runs constant propagation only on ops that have non-aliasing inputs & outputs
18
+ // Returns True if the pass made a change to the graph
19
+ TORCH_API bool ConstantPropagationImmutableTypes(std::shared_ptr<Graph>& graph);
20
+
21
+ // Runs the node if its inputs are constants. Callers of this function must
22
+ // make their own determination if constant prop is appropriate - for example
23
+ // non-deterministic ops or ops with side effects. If ignore_custom_classes is
24
+ // specified, nodes that output user defined classes are not run.
25
+ TORCH_API std::optional<Stack> runNodeIfInputsAreConstant(
26
+ const Node* node,
27
+ bool ignore_custom_classes = false,
28
+ AliasDb* db = nullptr);
29
+
30
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/create_autodiff_subgraphs.h ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+
6
+ #include <cstddef>
7
+
8
+ namespace torch::jit {
9
+
10
+ // insert GraphExecutor nodes that group together
11
+ // subgraphs that are differentiable by the jit's autodiff passes
12
+ // threshold - minimum number of nodes that will appear in a block
13
+ // returns all differentiable blocks that have been found
14
+ TORCH_API std::vector<Node*> CreateAutodiffSubgraphs(
15
+ const std::shared_ptr<Graph>& graph,
16
+ size_t threshold = 2);
17
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/create_functional_graphs.h ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+
6
+ namespace torch::jit {
7
+
8
+ TORCH_API void CreateFunctionalGraphs(const std::shared_ptr<Graph>& graph);
9
+
10
+ TORCH_API void InlineFunctionalGraphs(const std::shared_ptr<Graph>& graph);
11
+
12
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/dead_code_elimination.h ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // If given a top-level graph, DCE will construct do alias analysis that allows
8
+ // for "smarter" dead code elimination (we will eliminate mutable ops if we can
9
+ // prove the mutated values are not used). Otherwise, we will not allow DCE to
10
+ // eliminate mutable ops.
11
+ //
12
+ // So, prefer to use the graph version if you can.
13
+ enum class DCESideEffectPolicy : uint8_t {
14
+ // default behavior: dead code elimination will check if a node has side
15
+ // effects
16
+ // and not delete it if it does.
17
+ DONT_DELETE_NODES_WITH_SIDE_EFFECTS,
18
+ // with this flag, dead code elimination will not check if a node has side
19
+ // effects and treat nodes with side effects like any other node,
20
+ // i.e. delete them if their outputs aren't used anywhere.
21
+ ALLOW_DELETING_NODES_WITH_SIDE_EFFECTS
22
+ };
23
+
24
+ TORCH_API void EliminateDeadCode(
25
+ const std::shared_ptr<Graph>& graph,
26
+ DCESideEffectPolicy sideEffectPolicy =
27
+ DCESideEffectPolicy::DONT_DELETE_NODES_WITH_SIDE_EFFECTS);
28
+ TORCH_API void EliminateDeadCode(
29
+ Block* block,
30
+ bool recurse = true,
31
+ DCESideEffectPolicy sideEffectPolicy =
32
+ DCESideEffectPolicy::DONT_DELETE_NODES_WITH_SIDE_EFFECTS);
33
+
34
+ // Invoke the user-provided callback on all live values before deleting anything
35
+ TORCH_API void EliminateDeadCode(
36
+ Block* block,
37
+ std::function<void(const std::unordered_set<const Value*>&)> cb,
38
+ DCESideEffectPolicy sideEffectPolicy =
39
+ DCESideEffectPolicy::DONT_DELETE_NODES_WITH_SIDE_EFFECTS);
40
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/decompose_ops.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ TORCH_API void DecomposeOps(std::shared_ptr<Graph>& graph);
8
+
9
+ }
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/device_type_analysis.h ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+ struct Graph;
7
+
8
+ // Propagates Device type info throughout the given graph.
9
+ TORCH_API bool DeviceTypePropagation(std::shared_ptr<Graph>& graph);
10
+
11
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/dtype_analysis.h ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/Export.h>
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+ #include <memory>
6
+
7
+ namespace torch::jit {
8
+ struct Graph;
9
+
10
+ // Propagate tensor properties (e.g., dtype, device, is_contiguous, layout)
11
+ // propagation on all tensor objects. Currently, we only support dtype
12
+ // propagation
13
+ TORCH_API bool DtypePropagation(std::shared_ptr<Graph>& graph);
14
+
15
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/eliminate_no_ops.h ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Remove ops that do nothing on the forward pass (like aten::detach).
8
+ // This pass is invoked as a part of freeze_module.
9
+ // This function also takes a set of custom ops to eliminate. All ops in this
10
+ // set must take their output as their first input, i.e. x = f(x, ...)
11
+ TORCH_API bool EliminateNoOps(
12
+ std::shared_ptr<Graph>& graph,
13
+ std::unordered_set<c10::Symbol> custom_ops = {});
14
+
15
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/erase_number_types.h ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Erase NumberType information. This is necessary for and only used in
8
+ // exporting to ONNX. This pass ensures that no remaining Values have
9
+ // NumberType types, replacing them with tensors.
10
+ // The following things are done to erase NumberType info:
11
+ // - NumberType outputs are changed to DynamicType.
12
+ // - prim::Constant nodes which are numbers get changed into 0-dim tensors of
13
+ // the corresponding type
14
+ // - prim::TensorToNum, aten::Float, aten::Int and prim::NumToTensor nodes
15
+ // are erased.
16
+ //
17
+ // The pass assumes that DCE will be called sometime after.
18
+ TORCH_API void EraseNumberTypes(const std::shared_ptr<Graph>& graph);
19
+ TORCH_API void EraseNumberTypesOnBlock(Block* block);
20
+
21
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fixup_trace_scope_blocks.h ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/api/module.h>
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+
6
+ namespace torch::jit {
7
+
8
+ // Directly after tracing, we have an ill-formed graph with blocks inserted.
9
+ // Example:
10
+ //
11
+ // graph(%self : ClassType<Module>,
12
+ // %input.1 : Float(3, 4)):
13
+ // %1 : ClassType<Module> = prim::GetAttr[name="relu1"](%self)
14
+ // %2 : ClassType<Module> = prim::GetAttr[name="relu2"](%self)
15
+ // %3 : ClassType<Module> = prim::GetAttr[name="rrr"](%2)
16
+ // = prim::TracedModuleForward[scope="__module.relu1"]()
17
+ // block0():
18
+ // %input : Float(3, 4) = aten::relu(%input.1),
19
+ // -> ()
20
+ // = prim::TracedModuleForward[scope="__module.relu2"](),
21
+ // block0():
22
+ // = prim::TracedModuleForward[scope="__module.relu2.rrr"](),
23
+ // block0():
24
+ // %6 : Float(3, 4) = aten::relu(%input),
25
+ // -> ()
26
+ // -> ()
27
+ // return (%6)
28
+ //
29
+ // In this pass, we:
30
+ // 1) Lift Value defs to as high of a scope as needed to ensure that
31
+ // they dominate all their uses. For example, `input` in the above
32
+ // graph needs to be lifted to the top-level block so that its use
33
+ // in the second `relu` operator is dominated.
34
+ // 2) Lambda lift the blocks. This ensures that all values used within
35
+ // each scope have their defs captured.
36
+ // 3) Convert the scope blocks into methods on their respective Modules,
37
+ // and convert TracedModuleForward nodes to CallMethod nodes into those
38
+ // methods.
39
+ //
40
+ // Then, we'll have a well-formed graph with proper method calls.
41
+ TORCH_API void FixupTraceScopeBlocks(
42
+ std::shared_ptr<Graph>& graph,
43
+ Module* self);
44
+
45
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fold_conv_bn.h ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/api/module.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ /** \brief Fold Conv2d-BatchNorm2d into Conv2d in all methods of this
8
+ * module and all its submodules, forward is included by default.
9
+ *
10
+ * The weight and bias of the Conv2d are correspondingly updated. Should only be
11
+ * used on modules in eval mode.
12
+ */
13
+ TORCH_API Module FoldConvBatchNorm(const Module& module);
14
+
15
+ struct TORCH_API ConvBNParameters {
16
+ at::Tensor conv_w;
17
+ at::Tensor conv_b;
18
+ at::Tensor bn_rm;
19
+ at::Tensor bn_rv;
20
+ double bn_eps = 0.0;
21
+ at::Tensor bn_w;
22
+ at::Tensor bn_b;
23
+ };
24
+
25
+ /**
26
+ * Given the current weight and bias tensors of a Conv module and parameters
27
+ * of the BatchNorm module we're folding with, compute the updated values
28
+ * for the weight and bias.
29
+ *
30
+ * The function is basically copied from torch/nn/utils/fusion.py
31
+ */
32
+ TORCH_API std::tuple<at::Tensor, at::Tensor> computeUpdatedConvWeightAndBias(
33
+ const ConvBNParameters& p);
34
+
35
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fold_linear_bn.h ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/api/module.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ struct TORCH_API LinearBNParameters {
8
+ at::Tensor linear_w;
9
+ at::Tensor linear_b;
10
+ at::Tensor bn_rm;
11
+ at::Tensor bn_rv;
12
+ double bn_eps = 0.0;
13
+ at::Tensor bn_w;
14
+ at::Tensor bn_b;
15
+ };
16
+
17
+ /**
18
+ * Given the current weight and bias tensors of a Linear module and parameters
19
+ * of the BatchNorm module we're folding with, compute the updated values
20
+ * for the weight and bias.
21
+ *
22
+ * The function is basically copied from torch/nn/utils/fusion.py
23
+ */
24
+ TORCH_API std::tuple<at::Tensor, at::Tensor> computeUpdatedLinearWeightAndBias(
25
+ const LinearBNParameters& p);
26
+
27
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/freeze_module.h ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** \brief This file defines freezing Torchscript module API.
2
+ *
3
+ * This API has python-binding and can be invoked directly or as a part of
4
+ * general optimization pipeline.
5
+ */
6
+ #pragma once
7
+
8
+ #include <torch/csrc/jit/api/module.h>
9
+ #include <torch/csrc/jit/ir/ir.h>
10
+
11
+ /** \brief Freeze Module, i.e., Assume all attributes are constants.
12
+ *
13
+ * Freezing module is a functionality that allows the JIT to internalize
14
+ * immutable attributes. Combined with inlining, the module is aggressively
15
+ * optimized and significant overhead is optimized away. The freezeModule API
16
+ * produces a cloned frozen module.
17
+ */
18
+
19
+ namespace torch::jit {
20
+
21
+ TORCH_API Module freeze_module(
22
+ const Module& module,
23
+ std::vector<std::string> preservedAttrs = std::vector<std::string>(),
24
+ bool freezeInterfaces = true,
25
+ bool preserveParameters = false);
26
+
27
+ // Clone-free version of freeze_module. This modifies the module inplace.
28
+ // Use this version to avoid extra memory usage incurred by cloning the module.
29
+ TORCH_API void freeze_module_inplace(
30
+ Module* module,
31
+ std::vector<std::string> preservedAttrs = std::vector<std::string>(),
32
+ bool freezeInterfaces = true,
33
+ bool preserveParameters = false);
34
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_concat_linear.h ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Concats multiple linear ops with the same Tensor input
8
+ // into a single linear op.
9
+ TORCH_API bool FrozenConcatLinear(std::shared_ptr<Graph>& graph);
10
+
11
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_conv_add_relu_fusion.h ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/api/module.h>
4
+ #include <torch/csrc/jit/ir/ir.h>
5
+
6
+ namespace torch::jit {
7
+
8
+ TORCH_API extern std::function<void(std::shared_ptr<Graph>&)>&
9
+ getFuseFrozenConvAddReluImpl();
10
+
11
+ TORCH_API void FuseFrozenConvAddRelu(std::shared_ptr<Graph>& graph);
12
+
13
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_conv_folding.h ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Fuses Convolution -> Batchnorm into a single Convolution by
8
+ // folding batchnorm weights into conv weights.
9
+ // This pass only works on Frozen Graphs; otherwise it is a No-Op.
10
+ TORCH_API bool FoldFrozenConvBatchnorm(std::shared_ptr<Graph>& graph);
11
+
12
+ // Fuses Convolution -> Add/Sub into a single Convolution by
13
+ // folding add constant tensor into conv weights.
14
+ // This pass only works on Frozen Graphs; otherwise it is a No-Op.
15
+ TORCH_API bool FoldFrozenConvAddOrSub(std::shared_ptr<Graph>& graph);
16
+
17
+ // Fuses Convolution -> Mul/Div into a single Convolution by
18
+ // folding add constant tensor into conv weights.
19
+ // This pass only works on Frozen Graphs; otherwise it is a No-Op.
20
+ TORCH_API bool FoldFrozenConvMulOrDiv(std::shared_ptr<Graph>& graph);
21
+
22
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_graph_optimizations.h ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ /** \brief Runs a set of Optimizations that Optimize Frozen Graphs
6
+ *
7
+ * Currently this set of optimizations is:
8
+ * - FoldFrozenConvBatchnorm
9
+ * - FoldFrozenConvAddOrSub
10
+ * - FoldFrozenConvMulOrDiv
11
+ * - FoldFrozenLinearBatchnorm
12
+ */
13
+
14
+ namespace torch::jit {
15
+
16
+ TORCH_API void OptimizeFrozenGraph(
17
+ std::shared_ptr<Graph>& graph,
18
+ bool optimize_numerics = true);
19
+
20
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_linear_folding.h ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Fuses Linear -> BatchNormNd into a single Linear by
8
+ // folding batchnorm weights into linear weights.
9
+ // This pass only works on Frozen Graphs; otherwise it is a No-Op.
10
+ TORCH_API bool FoldFrozenLinearBatchnorm(std::shared_ptr<Graph>& graph);
11
+
12
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_linear_transpose.h ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Transposes the weight matrix for frozen linear modules.
8
+ // and converts it into a matmul
9
+ TORCH_API bool FrozenLinearTranspose(std::shared_ptr<Graph>& graph);
10
+
11
+ } // namespace torch::jit
lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_ops_to_mkldnn.h ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <torch/csrc/jit/ir/ir.h>
4
+
5
+ namespace torch::jit {
6
+
7
+ // Converts operators & their parameters to mkldnn if it is profitable
8
+ // Currently encompassing Conv2d and Conv3d, and Linear
9
+ // Op must be in float32 and mkldnn must be built
10
+ // This pass only works on frozen graph
11
+ TORCH_API void ConvertFrozenOpsToMKLDNN(std::shared_ptr<Graph>& graph);
12
+
13
+ } // namespace torch::jit