Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/compilation_unit.h +351 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/function_impl.h +180 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/method.h +84 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/module.h +685 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/api/object.h +200 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend.h +117 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_handler.h +138 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_debug_info.h +63 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_detail.h +39 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_exception.h +56 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_init.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_interface.h +32 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_preprocess.h +16 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/backends/backend_resolver.h +8 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/codegen/cuda/interface.h +52 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/jit_log.h +126 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/jit_opt_limit.h +37 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/add_if_then_else.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/annotate_warns.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/autocast.h +13 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/bailout_graph.h +32 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/batch_mm.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/canonicalize.h +20 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/canonicalize_graph_fuser_ops.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/check_strict_fusion.h +10 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/clear_profiling.h +17 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/clear_undefinedness.h +22 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/common_subexpression_elimination.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/concat_opt.h +17 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/constant_pooling.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/constant_propagation.h +30 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/create_autodiff_subgraphs.h +17 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/create_functional_graphs.h +12 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/dead_code_elimination.h +40 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/decompose_ops.h +9 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/device_type_analysis.h +11 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/dtype_analysis.h +15 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/eliminate_no_ops.h +15 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/erase_number_types.h +21 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fixup_trace_scope_blocks.h +45 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fold_conv_bn.h +35 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/fold_linear_bn.h +27 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/freeze_module.h +34 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_concat_linear.h +11 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_conv_add_relu_fusion.h +13 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_conv_folding.h +22 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_graph_optimizations.h +20 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_linear_folding.h +12 -0
- lib/python3.12/site-packages/torch/include/torch/csrc/jit/passes/frozen_linear_transpose.h +11 -0
- 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
|