Auto-sync: 2026-06-25 22:43:25 (part 27)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +6 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/python/update_graph_executor_opt.h +11 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/python/utf8_decoding_ignore.h +11 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/resource_guard.h +30 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/argument_spec.h +509 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/autodiff.h +99 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/calculate_necessary_args.h +74 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/custom_operator.h +35 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/decomposition_registry.h +38 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/decomposition_registry_util.h +17 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/exception_message.h +34 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_executor.h +157 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_executor_impl.h +123 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_iterator.h +152 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/instruction.h +103 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter.h +165 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/can_emit_inline.h +111 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/code_impl.h +1066 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/frame.h +45 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/preprocess_graph.h +24 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/jit_exception.h +43 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/jit_trace.h +13 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/logging.h +94 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/operator.h +348 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/operator_options.h +14 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/print_handler.h +20 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/profiling_graph_executor_impl.h +87 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/profiling_record.h +211 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/register_ops_utils.h +888 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/script_profile.h +108 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/serialized_shape_function_registry.h +20 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/shape_function_registry.h +17 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/simple_graph_executor_impl.h +31 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/slice_indices_adjust.h +31 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/ProcessedNodeInputs.h +246 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/fusion.h +20 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/impl.h +1152 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/init.h +12 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/memory_planner.h +303 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/ops.h +192 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/passes.h +96 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/processed_node_wrapper.h +216 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/static_method.h +53 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/te_wrapper.h +49 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_script.h +23 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_shape_registry.h +74 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_shape_registry_util.h +17 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/vararg_functions.h +46 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/variable_tensor_list.h +22 -0
- outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/serialization/callstack_debug_info_serialization.h +94 -0
.gitattributes
CHANGED
|
@@ -125,3 +125,9 @@ outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/t64.exe filt
|
|
| 125 |
outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64-arm.exe filter=lfs diff=lfs merge=lfs -text
|
| 126 |
outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64.exe filter=lfs diff=lfs merge=lfs -text
|
| 127 |
outputs/audit_venv/lib/python3.11/site-packages/pydantic_core/_pydantic_core.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64-arm.exe filter=lfs diff=lfs merge=lfs -text
|
| 126 |
outputs/audit_venv/lib/python3.11/site-packages/pip/_vendor/distlib/w64.exe filter=lfs diff=lfs merge=lfs -text
|
| 127 |
outputs/audit_venv/lib/python3.11/site-packages/pydantic_core/_pydantic_core.cpython-311-x86_64-linux-gnu.so filter=lfs diff=lfs merge=lfs -text
|
| 128 |
+
outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libc10.so filter=lfs diff=lfs merge=lfs -text
|
| 129 |
+
outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libc10_cuda.so filter=lfs diff=lfs merge=lfs -text
|
| 130 |
+
outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cpu.so filter=lfs diff=lfs merge=lfs -text
|
| 131 |
+
outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cuda.so filter=lfs diff=lfs merge=lfs -text
|
| 132 |
+
outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_cuda_linalg.so filter=lfs diff=lfs merge=lfs -text
|
| 133 |
+
outputs/audit_venv/lib/python3.11/site-packages/torch/lib/libtorch_python.so filter=lfs diff=lfs merge=lfs -text
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/python/update_graph_executor_opt.h
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <torch/csrc/Export.h>
|
| 4 |
+
namespace torch::jit {
|
| 5 |
+
TORCH_API void setGraphExecutorOptimize(bool o);
|
| 6 |
+
TORCH_API bool getGraphExecutorOptimize();
|
| 7 |
+
} // namespace torch::jit
|
| 8 |
+
|
| 9 |
+
#else
|
| 10 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 11 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/python/utf8_decoding_ignore.h
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <torch/csrc/Export.h>
|
| 4 |
+
namespace torch::jit {
|
| 5 |
+
TORCH_API void setUTF8DecodingIgnore(bool o);
|
| 6 |
+
TORCH_API bool getUTF8DecodingIgnore();
|
| 7 |
+
} // namespace torch::jit
|
| 8 |
+
|
| 9 |
+
#else
|
| 10 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 11 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/resource_guard.h
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <functional>
|
| 4 |
+
|
| 5 |
+
namespace torch::jit {
|
| 6 |
+
|
| 7 |
+
class ResourceGuard {
|
| 8 |
+
std::function<void()> _destructor;
|
| 9 |
+
bool _released{false};
|
| 10 |
+
|
| 11 |
+
public:
|
| 12 |
+
ResourceGuard(std::function<void()> destructor)
|
| 13 |
+
: _destructor(std::move(destructor)) {}
|
| 14 |
+
|
| 15 |
+
// NOLINTNEXTLINE(bugprone-exception-escape)
|
| 16 |
+
~ResourceGuard() {
|
| 17 |
+
if (!_released)
|
| 18 |
+
_destructor();
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
void release() {
|
| 22 |
+
_released = true;
|
| 23 |
+
}
|
| 24 |
+
};
|
| 25 |
+
|
| 26 |
+
} // namespace torch::jit
|
| 27 |
+
|
| 28 |
+
#else
|
| 29 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 30 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/argument_spec.h
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <ATen/core/jit_type.h>
|
| 5 |
+
#include <ATen/core/stack.h>
|
| 6 |
+
#include <c10/util/hash.h>
|
| 7 |
+
#include <c10/util/irange.h>
|
| 8 |
+
#include <torch/csrc/Export.h>
|
| 9 |
+
#include <torch/csrc/autograd/variable.h>
|
| 10 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 11 |
+
#include <ostream>
|
| 12 |
+
#include <vector>
|
| 13 |
+
|
| 14 |
+
C10_CLANG_DIAGNOSTIC_PUSH()
|
| 15 |
+
#if C10_CLANG_HAS_WARNING("-Wshorten-64-to-32")
|
| 16 |
+
C10_CLANG_DIAGNOSTIC_IGNORE("-Wshorten-64-to-32")
|
| 17 |
+
#endif
|
| 18 |
+
|
| 19 |
+
namespace torch::jit {
|
| 20 |
+
|
| 21 |
+
// GraphExecutor creates specializations of Graphs for different
|
| 22 |
+
// dimensionalitities and types of inputs.
|
| 23 |
+
|
| 24 |
+
struct ArgumentInfo {
|
| 25 |
+
friend struct ArgumentSpec;
|
| 26 |
+
using plain_data_type = uint64_t;
|
| 27 |
+
|
| 28 |
+
bool defined() const {
|
| 29 |
+
return defined_;
|
| 30 |
+
}
|
| 31 |
+
at::Device device() const {
|
| 32 |
+
return at::Device(DeviceType(dev_type_), device_);
|
| 33 |
+
}
|
| 34 |
+
// XXX: It is guaranteed that this will return false when called on non-tensor
|
| 35 |
+
// arguments
|
| 36 |
+
bool requires_grad() const {
|
| 37 |
+
return requires_grad_;
|
| 38 |
+
}
|
| 39 |
+
int dim() const {
|
| 40 |
+
return dim_;
|
| 41 |
+
}
|
| 42 |
+
at::ScalarType type() const {
|
| 43 |
+
return at::ScalarType(type_);
|
| 44 |
+
}
|
| 45 |
+
TypePtr toType() const {
|
| 46 |
+
if (!defined())
|
| 47 |
+
return TensorType::get();
|
| 48 |
+
|
| 49 |
+
return TensorType::create(
|
| 50 |
+
type(), device(), std::optional<size_t>(dim()), requires_grad());
|
| 51 |
+
}
|
| 52 |
+
operator TypePtr() const {
|
| 53 |
+
return toType();
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
private:
|
| 57 |
+
unsigned defined_ : 1;
|
| 58 |
+
unsigned requires_grad_ : 1;
|
| 59 |
+
unsigned : 5;
|
| 60 |
+
unsigned dim_ : 8;
|
| 61 |
+
unsigned device_ : 8;
|
| 62 |
+
unsigned type_ : 8;
|
| 63 |
+
unsigned dev_type_ : 16;
|
| 64 |
+
unsigned : 16;
|
| 65 |
+
};
|
| 66 |
+
|
| 67 |
+
static_assert(
|
| 68 |
+
std::is_standard_layout_v<ArgumentInfo>,
|
| 69 |
+
"ArgumentInfo is to be a POD struct");
|
| 70 |
+
static_assert(
|
| 71 |
+
sizeof(ArgumentInfo) == sizeof(ArgumentInfo::plain_data_type),
|
| 72 |
+
"ArgumentInfo is expected to be a 32-bit struct");
|
| 73 |
+
|
| 74 |
+
struct ArgumentSpec {
|
| 75 |
+
ArgumentSpec(size_t num_flat_tensor_inputs, size_t num_flat_optional_inputs)
|
| 76 |
+
: hash_code(c10::hash_combine(
|
| 77 |
+
num_flat_tensor_inputs,
|
| 78 |
+
num_flat_optional_inputs)) {
|
| 79 |
+
tensor_args.reserve(num_flat_tensor_inputs);
|
| 80 |
+
optional_presence.reserve(num_flat_optional_inputs);
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
void addOptional(const IValue& input) {
|
| 84 |
+
bool is_present = !input.isNone();
|
| 85 |
+
optional_presence.push_back(is_present);
|
| 86 |
+
hash_code = c10::hash_combine(hash_code, is_present);
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
void addTensor(const IValue& input, bool with_grad) {
|
| 90 |
+
AT_ASSERT(input.isTensor(), "Expected Tensor but found ", input.tagKind());
|
| 91 |
+
tensor_args.emplace_back();
|
| 92 |
+
auto& arg = tensor_args.back();
|
| 93 |
+
// Initialize all fields to 0. This is convenient, because e.g.
|
| 94 |
+
// requires_grad() can be checked even on tensors AND will make
|
| 95 |
+
// padding bits all 0s.
|
| 96 |
+
std::memset(&arg, 0, sizeof(ArgumentInfo));
|
| 97 |
+
|
| 98 |
+
// [argspec refcounting] reinterpret the IValue to avoid having to refcount
|
| 99 |
+
// the Tensor microbenchmarks
|
| 100 |
+
// https://github.com/zdevito/pytorch/commit/21e7200a0a0fc456bea2f10e95b1781f83933d10
|
| 101 |
+
// show overhead in extra refcounting along this path
|
| 102 |
+
const at::Tensor* t = reinterpret_cast<const at::Tensor*>(&input);
|
| 103 |
+
arg.defined_ = t->defined();
|
| 104 |
+
if (arg.defined_) {
|
| 105 |
+
arg.requires_grad_ = with_grad && t->requires_grad();
|
| 106 |
+
arg.dim_ = t->dim();
|
| 107 |
+
at::Device device = t->device();
|
| 108 |
+
arg.dev_type_ =
|
| 109 |
+
// NOLINTNEXTLINE(bugprone-signed-char-misuse)
|
| 110 |
+
static_cast<std::underlying_type_t<DeviceType>>(device.type());
|
| 111 |
+
// NOLINTNEXTLINE(bugprone-signed-char-misuse)
|
| 112 |
+
arg.device_ = device.index();
|
| 113 |
+
arg.type_ = static_cast<unsigned>(t->scalar_type());
|
| 114 |
+
}
|
| 115 |
+
combineHash(arg);
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
void combineHash(const ArgumentInfo& arg) {
|
| 119 |
+
ArgumentInfo::plain_data_type arg_data = 0;
|
| 120 |
+
std::memcpy(&arg_data, &arg, sizeof(ArgumentInfo));
|
| 121 |
+
hash_code = c10::hash_combine(hash_code, arg_data);
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
// equality is fast: check ninputs, and then check the raw array data,
|
| 125 |
+
// there are no size/stride indirections
|
| 126 |
+
// hopefully std::vector<bool> has fast equality
|
| 127 |
+
bool operator==(const ArgumentSpec& spec) const {
|
| 128 |
+
if (optional_presence != spec.optional_presence) {
|
| 129 |
+
return false;
|
| 130 |
+
}
|
| 131 |
+
if (tensor_args.size() != spec.tensor_args.size())
|
| 132 |
+
return false;
|
| 133 |
+
// NB: we need to break out early when there are no elements, because
|
| 134 |
+
// passing a nullptr to memcmp is UB.
|
| 135 |
+
if (tensor_args.empty())
|
| 136 |
+
return true;
|
| 137 |
+
return std::memcmp(
|
| 138 |
+
tensor_args.data(),
|
| 139 |
+
spec.tensor_args.data(),
|
| 140 |
+
tensor_args.size() * sizeof(ArgumentInfo)) == 0;
|
| 141 |
+
}
|
| 142 |
+
bool operator!=(const ArgumentSpec& spec) const {
|
| 143 |
+
return !(*this == spec);
|
| 144 |
+
}
|
| 145 |
+
size_t numTensors() const {
|
| 146 |
+
return tensor_args.size();
|
| 147 |
+
}
|
| 148 |
+
const ArgumentInfo& tensorAt(size_t i) const {
|
| 149 |
+
return tensor_args[i];
|
| 150 |
+
}
|
| 151 |
+
size_t numOptionals() const {
|
| 152 |
+
return optional_presence.size();
|
| 153 |
+
}
|
| 154 |
+
bool isPresent(size_t i) const {
|
| 155 |
+
return optional_presence[i];
|
| 156 |
+
}
|
| 157 |
+
size_t hashCode() const noexcept {
|
| 158 |
+
return hash_code;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
private:
|
| 162 |
+
size_t hash_code; // precomputed on construction
|
| 163 |
+
std::vector<ArgumentInfo> tensor_args;
|
| 164 |
+
std::vector<bool> optional_presence;
|
| 165 |
+
};
|
| 166 |
+
|
| 167 |
+
namespace {
|
| 168 |
+
static constexpr size_t ARG_SPEC_DEPTH_LIMIT = 128;
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
// ArgumentSpecCreator takes an initial graph and comes up with a set
|
| 172 |
+
// of simple instructions to compute the ArgumentSpec given a set of
|
| 173 |
+
// input tensors.
|
| 174 |
+
struct TORCH_API ArgumentSpecCreator {
|
| 175 |
+
// instructs acts on a stack of a list of input IValues
|
| 176 |
+
// at the beginning the stack contains a single list of the inputs to the
|
| 177 |
+
// function the ENTER_ instructs descend into subobjects and push new lists
|
| 178 |
+
// onto the stack
|
| 179 |
+
enum Inst : char {
|
| 180 |
+
ENTER_TUPLE, // consume a tuple ivalue from the top-most list, and push the
|
| 181 |
+
// list of its elements onto the stack as a new list
|
| 182 |
+
ENTER_OBJECT, // same as ENTER_TUPLE, but the input is a class
|
| 183 |
+
LEAVE, // pop the top-most list from the stack
|
| 184 |
+
SKIP, // consume an element from the top-most list, and discard
|
| 185 |
+
SPECIALIZE_OPTIONAL_TENSOR, // consume a optional tensor for the top-most
|
| 186 |
+
// list, and add it to the ArgSpec key being
|
| 187 |
+
// created
|
| 188 |
+
SPECIALIZE_TENSOR, // consume a tensor for the top-most
|
| 189 |
+
// list, and add it to the ArgSpec key being created
|
| 190 |
+
SPECIALIZE_OPTIONAL,
|
| 191 |
+
// consume a nontensor optional from the top-most list,
|
| 192 |
+
// and add it to the ArgSpec key being created
|
| 193 |
+
};
|
| 194 |
+
ArgumentSpecCreator(Graph& graph);
|
| 195 |
+
ArgumentSpec create(bool with_grad, const Stack& stack) const;
|
| 196 |
+
void specializeTypes(Graph& g, const ArgumentSpec& spec) const;
|
| 197 |
+
void dump() const;
|
| 198 |
+
using WrittenSlots = std::unordered_set<std::string>;
|
| 199 |
+
|
| 200 |
+
private:
|
| 201 |
+
void scan(
|
| 202 |
+
const TypePtr& typ,
|
| 203 |
+
size_t depth,
|
| 204 |
+
const WrittenSlots& written_slots);
|
| 205 |
+
size_t num_inputs_;
|
| 206 |
+
size_t num_tensors_ = 0;
|
| 207 |
+
size_t num_optionals_ = 0;
|
| 208 |
+
std::vector<Inst> instructions_;
|
| 209 |
+
};
|
| 210 |
+
|
| 211 |
+
// CompleteArgumentSpec represents one particular specialization.
|
| 212 |
+
// It is designed so that it can be created, hashed, and compared quickly
|
| 213 |
+
// since it is used along the hot-path of the JIT to check if the code
|
| 214 |
+
// we have created is valid for the given inputs.
|
| 215 |
+
|
| 216 |
+
// COmpleteArgumentInfoPOD is only used internally in CompleteArgumentSpec
|
| 217 |
+
// API users should use ArgumentInfo
|
| 218 |
+
struct CompleteArgumentInfoPOD {
|
| 219 |
+
// total size is 64-bit
|
| 220 |
+
unsigned is_tensor : 8; // all other fields are invalid if this is false
|
| 221 |
+
unsigned type : 8; // scalar type
|
| 222 |
+
unsigned defined : 1;
|
| 223 |
+
unsigned requires_grad : 1;
|
| 224 |
+
signed device : 14;
|
| 225 |
+
unsigned dev_type : 16;
|
| 226 |
+
unsigned
|
| 227 |
+
total_dims : 16; // all TensorInfoPODs are in CompleteArgumentSpec's
|
| 228 |
+
// tensor_info() array. total_dims is the total number of
|
| 229 |
+
// dimensions seen so far in all previous members of
|
| 230 |
+
// tensor_info(), including this tensor 2*total_dims
|
| 231 |
+
// becomes the offset into the sizes_strides list for the
|
| 232 |
+
// _next_ tensor in the tensor_info array for tensor 0,
|
| 233 |
+
// the offset is always 0
|
| 234 |
+
};
|
| 235 |
+
|
| 236 |
+
static_assert(
|
| 237 |
+
sizeof(CompleteArgumentInfoPOD) == sizeof(int64_t),
|
| 238 |
+
"CompleteArgumentInfoPOD must be 64-bit struct for CompleteArgumentSpec encoding to work");
|
| 239 |
+
|
| 240 |
+
struct CompleteArgumentInfo;
|
| 241 |
+
|
| 242 |
+
struct CompleteArgumentSpec {
|
| 243 |
+
CompleteArgumentSpec(bool with_grad, at::ArrayRef<IValue> inputs)
|
| 244 |
+
: ninputs(inputs.size()) {
|
| 245 |
+
int64_t all_dims = 0;
|
| 246 |
+
const auto num_inputs = inputs.size();
|
| 247 |
+
for (const auto i : c10::irange(num_inputs)) {
|
| 248 |
+
if (!inputs[i].isTensor())
|
| 249 |
+
continue;
|
| 250 |
+
auto& tensor = inputs[i].toTensor();
|
| 251 |
+
all_dims += tensor.defined() ? tensor.ndimension() : 0;
|
| 252 |
+
}
|
| 253 |
+
// allocate enough room for all TensorPODs and dimensions
|
| 254 |
+
data.resize(ninputs + all_dims * 2);
|
| 255 |
+
|
| 256 |
+
// and reinterpret our data array as these structs
|
| 257 |
+
auto* pods = reinterpret_cast<CompleteArgumentInfoPOD*>(data.data());
|
| 258 |
+
int64_t* next_dim = sizes_strides();
|
| 259 |
+
int32_t total_dims = 0;
|
| 260 |
+
for (const auto i : c10::irange(num_inputs)) {
|
| 261 |
+
auto& pod = pods[i];
|
| 262 |
+
pod.is_tensor = static_cast<uint32_t>(inputs[i].isTensor());
|
| 263 |
+
if (pod.is_tensor) {
|
| 264 |
+
at::Tensor t = inputs[i].toTensor();
|
| 265 |
+
pod.defined = t.defined();
|
| 266 |
+
if (pod.defined) {
|
| 267 |
+
pod.type = static_cast<int>(t.scalar_type());
|
| 268 |
+
at::Device device = t.device();
|
| 269 |
+
// NOLINTNEXTLINE(bugprone-signed-char-misuse)
|
| 270 |
+
pod.dev_type =
|
| 271 |
+
static_cast<std::underlying_type_t<DeviceType>>(device.type());
|
| 272 |
+
// NOLINTNEXTLINE(bugprone-signed-char-misuse)
|
| 273 |
+
pod.device = device.index();
|
| 274 |
+
pod.requires_grad = with_grad && t.requires_grad();
|
| 275 |
+
total_dims += t.ndimension();
|
| 276 |
+
auto sizes = t.sizes();
|
| 277 |
+
std::copy(sizes.begin(), sizes.end(), next_dim);
|
| 278 |
+
next_dim += sizes.size();
|
| 279 |
+
auto strides = t.strides();
|
| 280 |
+
std::copy(strides.begin(), strides.end(), next_dim);
|
| 281 |
+
next_dim += strides.size();
|
| 282 |
+
}
|
| 283 |
+
}
|
| 284 |
+
// each POD has a running tally of all dimensions including its own
|
| 285 |
+
TORCH_CHECK(
|
| 286 |
+
total_dims < std::numeric_limits<uint16_t>::max(),
|
| 287 |
+
"The number of dims cannot be packed into CompleteArgumentSpec:",
|
| 288 |
+
total_dims);
|
| 289 |
+
pod.total_dims = total_dims;
|
| 290 |
+
}
|
| 291 |
+
// we precompute the hash_code to minimize the time inside of hash
|
| 292 |
+
// table operations where we may need to hold a compiler cache lock.
|
| 293 |
+
hash_code = c10::hash_combine(0, ninputs);
|
| 294 |
+
for (auto d : data) {
|
| 295 |
+
hash_code = c10::hash_combine(hash_code, d);
|
| 296 |
+
}
|
| 297 |
+
}
|
| 298 |
+
|
| 299 |
+
// equality is fast: check ninputs, and then check the raw array data,
|
| 300 |
+
// there are no size/stride indirections
|
| 301 |
+
bool operator==(const CompleteArgumentSpec& spec) const {
|
| 302 |
+
return ninputs == spec.ninputs && data == spec.data;
|
| 303 |
+
}
|
| 304 |
+
bool operator!=(const CompleteArgumentSpec& spec) const {
|
| 305 |
+
return !(*this == spec);
|
| 306 |
+
}
|
| 307 |
+
friend struct CompleteArgumentInfo;
|
| 308 |
+
CompleteArgumentInfo at(size_t i) const;
|
| 309 |
+
size_t size() const {
|
| 310 |
+
return ninputs;
|
| 311 |
+
}
|
| 312 |
+
size_t hashCode() const noexcept {
|
| 313 |
+
return hash_code;
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
private:
|
| 317 |
+
ArrayRef<CompleteArgumentInfoPOD> tensor_info() const {
|
| 318 |
+
return ArrayRef<CompleteArgumentInfoPOD>(
|
| 319 |
+
reinterpret_cast<const CompleteArgumentInfoPOD*>(data.data()), ninputs);
|
| 320 |
+
}
|
| 321 |
+
// the start of the sizes_strides information, which comes after the
|
| 322 |
+
// CompleteArgumentInfoPOD list.
|
| 323 |
+
const int64_t* sizes_strides() const {
|
| 324 |
+
return data.data() + ninputs;
|
| 325 |
+
}
|
| 326 |
+
int64_t* sizes_strides() {
|
| 327 |
+
return data.data() + ninputs;
|
| 328 |
+
}
|
| 329 |
+
size_t hash_code{0}; // precomputed on construction
|
| 330 |
+
size_t ninputs;
|
| 331 |
+
// layout is ninputs of TensorPOD (each 64-bit) followed by their size and
|
| 332 |
+
// stride info for 3 tensors:
|
| 333 |
+
// [t0POD][t1POD][t2POD]...
|
| 334 |
+
// [t0 sizes][t0 strides][t1 sizes][t1 strides][t2 sizes][t2 strides]
|
| 335 |
+
std::vector<int64_t> data;
|
| 336 |
+
};
|
| 337 |
+
|
| 338 |
+
// public view of compressed CompleteArgumentInfo
|
| 339 |
+
struct CompleteArgumentInfo {
|
| 340 |
+
CompleteArgumentInfo(const CompleteArgumentSpec& spec, const int i)
|
| 341 |
+
: spec(spec), i(i) {}
|
| 342 |
+
bool isTensor() const {
|
| 343 |
+
return pod(i).is_tensor;
|
| 344 |
+
}
|
| 345 |
+
at::ScalarType type() const {
|
| 346 |
+
return at::ScalarType(pod(i).type);
|
| 347 |
+
}
|
| 348 |
+
bool defined() const {
|
| 349 |
+
return pod(i).defined;
|
| 350 |
+
}
|
| 351 |
+
bool requires_grad() const {
|
| 352 |
+
return pod(i).requires_grad;
|
| 353 |
+
}
|
| 354 |
+
at::Device device() const {
|
| 355 |
+
return at::Device(
|
| 356 |
+
DeviceType(pod(i).dev_type),
|
| 357 |
+
static_cast<c10::DeviceIndex>(pod(i).device));
|
| 358 |
+
}
|
| 359 |
+
int ndimension() const {
|
| 360 |
+
// See [valid range], it is always valid to ask for offset for (i + 1)
|
| 361 |
+
return (sizes_strides_offset(i + 1) - sizes_strides_offset(i)) / 2;
|
| 362 |
+
}
|
| 363 |
+
at::IntArrayRef sizes() const {
|
| 364 |
+
return at::IntArrayRef(
|
| 365 |
+
spec.sizes_strides() + sizes_strides_offset(i), ndimension());
|
| 366 |
+
}
|
| 367 |
+
at::IntArrayRef strides() const {
|
| 368 |
+
int ndim = ndimension();
|
| 369 |
+
return at::IntArrayRef(
|
| 370 |
+
spec.sizes_strides() + sizes_strides_offset(i) + ndim, ndim);
|
| 371 |
+
}
|
| 372 |
+
operator TypePtr() const {
|
| 373 |
+
if (!defined())
|
| 374 |
+
return TensorType::get();
|
| 375 |
+
return TensorType::create(
|
| 376 |
+
type(),
|
| 377 |
+
device(),
|
| 378 |
+
c10::VaryingShape<int64_t>{sizes()},
|
| 379 |
+
c10::VaryingShape<int64_t>{strides()},
|
| 380 |
+
requires_grad());
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
private:
|
| 384 |
+
// offsetinto sizes_strides() array where the sizes start for tensor j
|
| 385 |
+
// [valid range] valid range is [0, ninputs]
|
| 386 |
+
// (i.e. you can ask for the offset at ninputs, which would be the offset of
|
| 387 |
+
// the next tensor if it existed)
|
| 388 |
+
int sizes_strides_offset(int j) const {
|
| 389 |
+
if (j == 0)
|
| 390 |
+
return 0;
|
| 391 |
+
return 2 * pod(j - 1).total_dims;
|
| 392 |
+
}
|
| 393 |
+
const CompleteArgumentInfoPOD& pod(int j) const {
|
| 394 |
+
return spec.tensor_info().at(j);
|
| 395 |
+
}
|
| 396 |
+
const CompleteArgumentSpec& spec;
|
| 397 |
+
const int i;
|
| 398 |
+
};
|
| 399 |
+
|
| 400 |
+
inline std::ostream& operator<<(std::ostream& out, const ArgumentInfo& info) {
|
| 401 |
+
if (!info.defined()) {
|
| 402 |
+
return out << "<undefined>";
|
| 403 |
+
}
|
| 404 |
+
out << "Tensor(device=" << info.device() << ", type=" << toString(info.type())
|
| 405 |
+
<< ", requires_grad=" << info.requires_grad() << ", dims=" << info.dim()
|
| 406 |
+
<< ')';
|
| 407 |
+
return out;
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
inline std::ostream& operator<<(std::ostream& out, const ArgumentSpec& spec) {
|
| 411 |
+
out << '{';
|
| 412 |
+
for (const auto i : c10::irange(spec.numTensors())) {
|
| 413 |
+
if (i > 0)
|
| 414 |
+
out << ", ";
|
| 415 |
+
out << spec.tensorAt(i);
|
| 416 |
+
}
|
| 417 |
+
out << "; ";
|
| 418 |
+
for (const auto i : c10::irange(spec.numOptionals())) {
|
| 419 |
+
if (i > 0)
|
| 420 |
+
out << ", ";
|
| 421 |
+
out << spec.isPresent(i);
|
| 422 |
+
}
|
| 423 |
+
out << '}';
|
| 424 |
+
return out;
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
inline std::ostream& operator<<(
|
| 428 |
+
std::ostream& out,
|
| 429 |
+
const CompleteArgumentInfo& info) {
|
| 430 |
+
if (!info.defined()) {
|
| 431 |
+
return out << "<undefined>";
|
| 432 |
+
}
|
| 433 |
+
out << "Tensor(device=" << info.device() << ", type=" << toString(info.type())
|
| 434 |
+
<< ", requires_grad=" << info.requires_grad()
|
| 435 |
+
<< ", sizes=" << info.sizes() << ", strides=" << info.strides() << ')';
|
| 436 |
+
return out;
|
| 437 |
+
}
|
| 438 |
+
|
| 439 |
+
inline std::ostream& operator<<(
|
| 440 |
+
std::ostream& out,
|
| 441 |
+
const CompleteArgumentSpec& spec) {
|
| 442 |
+
out << '{';
|
| 443 |
+
for (const auto i : c10::irange(spec.size())) {
|
| 444 |
+
if (i > 0)
|
| 445 |
+
out << ", ";
|
| 446 |
+
out << spec.at(i);
|
| 447 |
+
}
|
| 448 |
+
out << '}';
|
| 449 |
+
return out;
|
| 450 |
+
}
|
| 451 |
+
|
| 452 |
+
inline CompleteArgumentInfo CompleteArgumentSpec::at(size_t i) const {
|
| 453 |
+
return CompleteArgumentInfo(*this, i);
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
inline std::optional<int8_t> convertOptional(
|
| 457 |
+
std::optional<c10::ScalarType> const& from) {
|
| 458 |
+
return from ? std::optional<int8_t>(static_cast<int8_t>(*from))
|
| 459 |
+
: std::optional<int8_t>{};
|
| 460 |
+
}
|
| 461 |
+
|
| 462 |
+
} // namespace torch::jit
|
| 463 |
+
|
| 464 |
+
namespace std {
|
| 465 |
+
|
| 466 |
+
template <typename T>
|
| 467 |
+
struct hash<c10::VaryingShape<T>> {
|
| 468 |
+
size_t operator()(const c10::VaryingShape<T>& vs) const {
|
| 469 |
+
return c10::get_hash(
|
| 470 |
+
vs.size(),
|
| 471 |
+
vs.size() ? vs.sizes().value() : std::vector<std::optional<T>>());
|
| 472 |
+
}
|
| 473 |
+
};
|
| 474 |
+
|
| 475 |
+
template <>
|
| 476 |
+
struct hash<c10::TensorType> {
|
| 477 |
+
size_t operator()(const c10::TensorType& ptt) const {
|
| 478 |
+
return c10::get_hash<
|
| 479 |
+
std::optional<int8_t>,
|
| 480 |
+
c10::VaryingShape<int64_t>,
|
| 481 |
+
c10::VaryingShape<int64_t>,
|
| 482 |
+
std::optional<bool>>(
|
| 483 |
+
torch::jit::convertOptional(ptt.scalarType()),
|
| 484 |
+
ptt.sizes(),
|
| 485 |
+
ptt.strides(),
|
| 486 |
+
ptt.requiresGrad());
|
| 487 |
+
}
|
| 488 |
+
};
|
| 489 |
+
|
| 490 |
+
template <>
|
| 491 |
+
struct hash<torch::jit::ArgumentSpec> {
|
| 492 |
+
size_t operator()(const torch::jit::ArgumentSpec& spec) const noexcept {
|
| 493 |
+
return spec.hashCode();
|
| 494 |
+
}
|
| 495 |
+
};
|
| 496 |
+
template <>
|
| 497 |
+
struct hash<torch::jit::CompleteArgumentSpec> {
|
| 498 |
+
size_t operator()(
|
| 499 |
+
const torch::jit::CompleteArgumentSpec& spec) const noexcept {
|
| 500 |
+
return spec.hashCode();
|
| 501 |
+
}
|
| 502 |
+
};
|
| 503 |
+
} // namespace std
|
| 504 |
+
|
| 505 |
+
C10_CLANG_DIAGNOSTIC_POP()
|
| 506 |
+
|
| 507 |
+
#else
|
| 508 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 509 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/autodiff.h
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/Export.h>
|
| 5 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 6 |
+
|
| 7 |
+
#include <memory>
|
| 8 |
+
#include <vector>
|
| 9 |
+
|
| 10 |
+
namespace torch::jit {
|
| 11 |
+
|
| 12 |
+
using value_list = std::vector<Value*>;
|
| 13 |
+
// clang-format off
|
| 14 |
+
// Example showcasing how Gradient is constructed:
|
| 15 |
+
//
|
| 16 |
+
// Let's assume we have a function f, `m` and `n` do not require grad
|
| 17 |
+
// (`n` can depend only on `m`):
|
| 18 |
+
// y, n = f(x, m)
|
| 19 |
+
//
|
| 20 |
+
// Now, let's assume that the reverse of f (called f') needs to use values of `x`, `t` and `y`.
|
| 21 |
+
// `t` is an intermediate value produced in the body of f, and let's assume that it requires
|
| 22 |
+
// grad too.
|
| 23 |
+
//
|
| 24 |
+
// In this case differentiate(f) will return this:
|
| 25 |
+
// y, n, t = f(x, m) // `t` is appended to the output list
|
| 26 |
+
// dx = f'(dy, dt, x, t, y) // No `dm` or `dn` because they do not require gradient
|
| 27 |
+
// // All needed values from f are prepended to the input list
|
| 28 |
+
//
|
| 29 |
+
// f_real_outputs = 2 // Only first two outputs were present in f originally
|
| 30 |
+
// df_input_vjps = {0, 2} // i.e. connect grad_fn of y and t variables produced by f,
|
| 31 |
+
// y t // with y's output_nr = 0 and t's output_nr = 1
|
| 32 |
+
// df_input_captures = {I0, O2, O0} // Order matches the prefix of inputs to df
|
| 33 |
+
// x t y
|
| 34 |
+
// df_output_vjps = {0} // i.e. connect next_edge[0] of grad_fn to x's (grad_fn, output_nr).
|
| 35 |
+
//
|
| 36 |
+
// Terminology: vjp = vector-jacobian product
|
| 37 |
+
// clang-format on
|
| 38 |
+
|
| 39 |
+
struct Gradient {
|
| 40 |
+
explicit operator bool() const {
|
| 41 |
+
return df != nullptr;
|
| 42 |
+
}
|
| 43 |
+
std::shared_ptr<Graph> f;
|
| 44 |
+
std::shared_ptr<Graph> df;
|
| 45 |
+
|
| 46 |
+
// Describes how to construct outputs of f from what its graph will return.
|
| 47 |
+
// This is necessary because some trailing outputs are intermediates produced
|
| 48 |
+
// only to be saved for df (and should be ignored).
|
| 49 |
+
size_t f_real_outputs = 0; // initialized for safety.
|
| 50 |
+
|
| 51 |
+
// df inputs are split into two sections: vjps (aka grad_outputs) and
|
| 52 |
+
// captures. VJPs are "seeds" for the gradient computation given for each
|
| 53 |
+
// input capture of an Output kind. Captures are values the need to be saved
|
| 54 |
+
// when f is run. We handle inputs specially, because this allows us to avoid
|
| 55 |
+
// adding extra vjps as df inputs.
|
| 56 |
+
|
| 57 |
+
std::vector<size_t> df_input_vjps; // Offsets into f's outputs.
|
| 58 |
+
// capture can come from inputs or outputs
|
| 59 |
+
std::vector<size_t> df_input_captured_inputs; // Offsets into f's inputs
|
| 60 |
+
std::vector<size_t> df_input_captured_outputs; // Offsets into f's outputs
|
| 61 |
+
|
| 62 |
+
// df will produce vjps for a subset of inputs of f that required grad.
|
| 63 |
+
// df_output_vjps[idx] == inp_idx means that idx-th output of df produces a
|
| 64 |
+
// vjp for inp_idx-th input of f.
|
| 65 |
+
std::vector<size_t> df_output_vjps; // Offsets into f's inputs.
|
| 66 |
+
|
| 67 |
+
// How to use gradient to implement a differentiable autograd function:
|
| 68 |
+
// When running f:
|
| 69 |
+
// - Unwrap input Variables
|
| 70 |
+
// - Run f's graph
|
| 71 |
+
// - Create grad_fn
|
| 72 |
+
// - Wrap outputs in Variables (assume we have a tensor_outputs array):
|
| 73 |
+
// outputs = map(Variable, tensor_output)
|
| 74 |
+
// for i, offset in enumerate(df_input_vjps):
|
| 75 |
+
// outputs[offset].set_grad_fn(grad_fn, output_nr=i)
|
| 76 |
+
// - Use df_output_vjps to connect next_edges of grad_fn:
|
| 77 |
+
// for idx in df_output_vjps:
|
| 78 |
+
// grad_fn.add_next_edge(inputs[idx].gradient_edge())
|
| 79 |
+
// - Save captures for df (care needs to be taken to use SavedVariables for
|
| 80 |
+
// inputs and outputs that we will actually return)
|
| 81 |
+
// - Return outputs[:f_real_outputs]
|
| 82 |
+
//
|
| 83 |
+
// When running df:
|
| 84 |
+
// - Concatenate received vjps and captured Variables
|
| 85 |
+
// - Interpret df
|
| 86 |
+
// - Wrap outputs of df into Variables (that don't require grad)
|
| 87 |
+
};
|
| 88 |
+
TORCH_API Gradient differentiate(std::shared_ptr<Graph>& graph);
|
| 89 |
+
|
| 90 |
+
// can we take a derivative of this node symbolically?
|
| 91 |
+
TORCH_API bool isDifferentiable(const Node* n);
|
| 92 |
+
TORCH_API bool isDifferentiable(Graph& g);
|
| 93 |
+
TORCH_API bool isZero(Value* v);
|
| 94 |
+
|
| 95 |
+
} // namespace torch::jit
|
| 96 |
+
|
| 97 |
+
#else
|
| 98 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 99 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/calculate_necessary_args.h
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/Export.h>
|
| 5 |
+
#include <torch/csrc/jit/frontend/schema_matching.h>
|
| 6 |
+
#include <cstddef>
|
| 7 |
+
|
| 8 |
+
namespace torch::jit {
|
| 9 |
+
|
| 10 |
+
// Calculates the number of args that need to be passed in.
|
| 11 |
+
// Less args may be needed if defaults are provided.
|
| 12 |
+
// Returns: {number args needed, number of out args}
|
| 13 |
+
inline std::pair<int64_t, int64_t> CalculateNecessaryArgs(
|
| 14 |
+
const std::vector<Argument>& schema_args,
|
| 15 |
+
at::ArrayRef<Value*> actual_inputs,
|
| 16 |
+
bool allow_trailing_out_args) {
|
| 17 |
+
if (schema_args.empty()) {
|
| 18 |
+
return std::make_pair(0, 0);
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
// count number of out arguments
|
| 22 |
+
int64_t schema_idx = static_cast<int64_t>(schema_args.size()) - 1;
|
| 23 |
+
if (allow_trailing_out_args) {
|
| 24 |
+
// skip over out arguments in the end.
|
| 25 |
+
while (schema_idx >= 0) {
|
| 26 |
+
const auto& current_arg = schema_args.at(schema_idx);
|
| 27 |
+
if (!current_arg.is_out()) {
|
| 28 |
+
break;
|
| 29 |
+
}
|
| 30 |
+
schema_idx--;
|
| 31 |
+
}
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
int64_t num_out = static_cast<int64_t>(schema_args.size()) - schema_idx - 1;
|
| 35 |
+
|
| 36 |
+
if (schema_args.size() < actual_inputs.size()) {
|
| 37 |
+
return std::make_pair(actual_inputs.size(), num_out);
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
// if it is the default args, we reset the index to the last element
|
| 41 |
+
if (!allow_trailing_out_args) {
|
| 42 |
+
schema_idx = schema_args.size() - 1;
|
| 43 |
+
}
|
| 44 |
+
// keeps track of trailing unnecessary args
|
| 45 |
+
while (schema_idx >= 0) {
|
| 46 |
+
// this means it is not default argument, so it is necessary
|
| 47 |
+
if (!schema_args.at(schema_idx).default_value().has_value()) {
|
| 48 |
+
return std::make_pair(schema_idx + 1, num_out);
|
| 49 |
+
} else {
|
| 50 |
+
auto schema_value =
|
| 51 |
+
schema_args.at(schema_idx).default_value().value().toIValue();
|
| 52 |
+
// non-const value will become nullptr here, so will be marked necessary
|
| 53 |
+
// non-const would include prim::ListConstruct, prim::DictConstruct as
|
| 54 |
+
// well.
|
| 55 |
+
auto actual_value = toIValue(actual_inputs[schema_idx]);
|
| 56 |
+
if (!actual_value.has_value()) {
|
| 57 |
+
return std::make_pair(schema_idx + 1, num_out);
|
| 58 |
+
}
|
| 59 |
+
// if the IR has same value as default value of the schema,
|
| 60 |
+
// it is not necessary argument.
|
| 61 |
+
if (schema_value != actual_value.value()) {
|
| 62 |
+
return std::make_pair(schema_idx + 1, num_out);
|
| 63 |
+
}
|
| 64 |
+
}
|
| 65 |
+
schema_idx--;
|
| 66 |
+
}
|
| 67 |
+
return std::make_pair(0, num_out);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
} // namespace torch::jit
|
| 71 |
+
|
| 72 |
+
#else
|
| 73 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 74 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/custom_operator.h
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <ATen/core/op_registration/op_registration.h>
|
| 5 |
+
#include <ATen/core/stack.h>
|
| 6 |
+
#include <torch/csrc/jit/runtime/operator.h>
|
| 7 |
+
|
| 8 |
+
namespace torch::jit {
|
| 9 |
+
|
| 10 |
+
/// Registration class for new operators. Effectively calls
|
| 11 |
+
/// `torch::jit::registerOperator` for every supplied operator, but allows doing
|
| 12 |
+
/// so in the global scope when a `RegisterOperators` object is assigned to a
|
| 13 |
+
/// static variable.
|
| 14 |
+
/// Note: This is *not* the custom operator API. If you want to register custom
|
| 15 |
+
/// operators, take a look at torch::RegisterOperators.
|
| 16 |
+
struct TORCH_API RegisterOperators {
|
| 17 |
+
RegisterOperators() = default;
|
| 18 |
+
|
| 19 |
+
/// Registers a vector of already created `Operator`s.
|
| 20 |
+
/// The operator element is now optional to filter null ops. It's backward
|
| 21 |
+
/// compatible and works for selective operator registration.
|
| 22 |
+
explicit RegisterOperators(std::vector<std::optional<Operator>> operators) {
|
| 23 |
+
for (std::optional<Operator>& o : operators) {
|
| 24 |
+
if (o) {
|
| 25 |
+
registerOperator(std::move(o.value()));
|
| 26 |
+
}
|
| 27 |
+
}
|
| 28 |
+
}
|
| 29 |
+
};
|
| 30 |
+
|
| 31 |
+
} // namespace torch::jit
|
| 32 |
+
|
| 33 |
+
#else
|
| 34 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 35 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/decomposition_registry.h
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
// This file is temporary until native_functions.yaml and derivatives.yaml are
|
| 4 |
+
// merged. Ideally this should all go into native_functions.yaml
|
| 5 |
+
|
| 6 |
+
#include <torch/csrc/Export.h>
|
| 7 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 8 |
+
|
| 9 |
+
namespace torch::jit {
|
| 10 |
+
|
| 11 |
+
TORCH_API std::optional<std::shared_ptr<Graph>> GetDecomposition(
|
| 12 |
+
const FunctionSchema& schema);
|
| 13 |
+
|
| 14 |
+
TORCH_API void RegisterDecomposition(
|
| 15 |
+
const FunctionSchema& schema,
|
| 16 |
+
std::shared_ptr<Graph> g);
|
| 17 |
+
|
| 18 |
+
TORCH_API void RunDecompositions(std::shared_ptr<Graph> g);
|
| 19 |
+
|
| 20 |
+
TORCH_API std::optional<GraphFunction*> GetDecompositionFunction(
|
| 21 |
+
const FunctionSchema& schema);
|
| 22 |
+
|
| 23 |
+
// For invocation in C++, recommended is to assign to static local variable
|
| 24 |
+
TORCH_API Function* GetDecompositionExecutor(const char* schema_literal);
|
| 25 |
+
|
| 26 |
+
TORCH_API Function* GetDecompositionExecutor(const FunctionSchema& schema);
|
| 27 |
+
|
| 28 |
+
TORCH_API void run_jit_decomposition(
|
| 29 |
+
const c10::OperatorHandle& op,
|
| 30 |
+
torch::jit::Stack* stack);
|
| 31 |
+
|
| 32 |
+
TORCH_API bool has_jit_decomposition(const FunctionSchema& schema);
|
| 33 |
+
|
| 34 |
+
} // namespace torch::jit
|
| 35 |
+
|
| 36 |
+
#else
|
| 37 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 38 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/decomposition_registry_util.h
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/Export.h>
|
| 5 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 6 |
+
|
| 7 |
+
namespace torch::jit {
|
| 8 |
+
|
| 9 |
+
TORCH_API const std::string& GetSerializedDecompositions();
|
| 10 |
+
|
| 11 |
+
TORCH_API const OperatorMap<std::string>& GetDecompositionMapping();
|
| 12 |
+
|
| 13 |
+
} // namespace torch::jit
|
| 14 |
+
|
| 15 |
+
#else
|
| 16 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 17 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/exception_message.h
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <c10/util/Exception.h>
|
| 4 |
+
#include <stdexcept>
|
| 5 |
+
|
| 6 |
+
namespace torch::jit {
|
| 7 |
+
|
| 8 |
+
struct ExceptionMessage {
|
| 9 |
+
ExceptionMessage(const std::exception& e) : e_(e) {}
|
| 10 |
+
|
| 11 |
+
private:
|
| 12 |
+
const std::exception& e_;
|
| 13 |
+
friend std::ostream& operator<<(
|
| 14 |
+
std::ostream& out,
|
| 15 |
+
const ExceptionMessage& msg);
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
inline std::ostream& operator<<(
|
| 19 |
+
std::ostream& out,
|
| 20 |
+
const ExceptionMessage& msg) {
|
| 21 |
+
auto c10_error = dynamic_cast<const c10::Error*>(&msg.e_);
|
| 22 |
+
if (c10_error) {
|
| 23 |
+
out << c10_error->what_without_backtrace();
|
| 24 |
+
} else {
|
| 25 |
+
out << msg.e_.what();
|
| 26 |
+
}
|
| 27 |
+
return out;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
} // namespace torch::jit
|
| 31 |
+
|
| 32 |
+
#else
|
| 33 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 34 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_executor.h
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <atomic>
|
| 5 |
+
#include <memory>
|
| 6 |
+
|
| 7 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 8 |
+
#include <torch/csrc/jit/python/update_graph_executor_opt.h>
|
| 9 |
+
#include <torch/csrc/jit/runtime/argument_spec.h>
|
| 10 |
+
#include <torch/csrc/jit/runtime/interpreter.h>
|
| 11 |
+
#include <torch/csrc/jit/runtime/variable_tensor_list.h>
|
| 12 |
+
|
| 13 |
+
TORCH_DECLARE_bool(torch_jit_enable_new_executor);
|
| 14 |
+
|
| 15 |
+
TORCH_DECLARE_bool(torch_jit_execution_plan_reuse_code_graph);
|
| 16 |
+
|
| 17 |
+
namespace torch::jit {
|
| 18 |
+
struct GraphExecutorState;
|
| 19 |
+
struct Code;
|
| 20 |
+
|
| 21 |
+
enum ExecutorExecutionMode {
|
| 22 |
+
SIMPLE,
|
| 23 |
+
PROFILING,
|
| 24 |
+
};
|
| 25 |
+
|
| 26 |
+
struct ExecutionPlan {
|
| 27 |
+
ExecutionPlan() = default;
|
| 28 |
+
ExecutionPlan(std::shared_ptr<Graph> graph, std::string function_name)
|
| 29 |
+
: code(graph, std::move(function_name)),
|
| 30 |
+
graph(
|
| 31 |
+
FLAGS_torch_jit_execution_plan_reuse_code_graph
|
| 32 |
+
? code.graph()
|
| 33 |
+
: std::move(graph)) {}
|
| 34 |
+
|
| 35 |
+
operator bool() const {
|
| 36 |
+
return static_cast<bool>(graph);
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
Code code;
|
| 40 |
+
std::shared_ptr<Graph> graph;
|
| 41 |
+
};
|
| 42 |
+
|
| 43 |
+
// Notice that those structs don't manage lifetime of their members.
|
| 44 |
+
// They are only valid only right after you call getDebugState() and should
|
| 45 |
+
// never be used again once another GraphExecutor function is called.
|
| 46 |
+
|
| 47 |
+
struct GraphExecutorState {
|
| 48 |
+
const Graph* graph = nullptr;
|
| 49 |
+
ExecutionPlan fallback; // XXX: members of this field are optional
|
| 50 |
+
std::unordered_map<ArgumentSpec, ExecutionPlan> execution_plans;
|
| 51 |
+
};
|
| 52 |
+
|
| 53 |
+
struct TORCH_API EnableProfilingGuard {
|
| 54 |
+
EnableProfilingGuard();
|
| 55 |
+
~EnableProfilingGuard();
|
| 56 |
+
|
| 57 |
+
private:
|
| 58 |
+
bool old_executor_mode = false;
|
| 59 |
+
bool old_get_optimize = false;
|
| 60 |
+
};
|
| 61 |
+
|
| 62 |
+
struct GraphExecutorImplBase;
|
| 63 |
+
struct TORCH_API GraphExecutor {
|
| 64 |
+
GraphExecutor() = default;
|
| 65 |
+
GraphExecutor(const std::shared_ptr<Graph>& graph, std::string function_name);
|
| 66 |
+
|
| 67 |
+
GraphExecutor(
|
| 68 |
+
const std::shared_ptr<Graph>& graph,
|
| 69 |
+
std::string function_name,
|
| 70 |
+
ExecutorExecutionMode executor_mode);
|
| 71 |
+
|
| 72 |
+
void run(Stack& inputs);
|
| 73 |
+
c10::intrusive_ptr<Future> runAsync(
|
| 74 |
+
Stack& stack,
|
| 75 |
+
TaskLauncher taskLauncher = at::launch);
|
| 76 |
+
|
| 77 |
+
// `remaining_bailout_depth` stands for the maximum number of profiled and
|
| 78 |
+
// specialized recompilations allowed for the current `GraphExecutor`. if
|
| 79 |
+
// remaining_bailout_depth is equal to 0, `GraphExecutor` won't perform any
|
| 80 |
+
// profiling and specialization. This is also equivalent to the
|
| 81 |
+
// SIMPLE_EXECUTOR mode. if remaining_bailout_depth is greater than 0,
|
| 82 |
+
// `GraphExecutor` will profile and specialize its input graph based on the
|
| 83 |
+
// profiled information whenever a bailout check is failed/triggered, a new
|
| 84 |
+
// `GraphExecutor` will be created. This new `GraphExecutor`'s
|
| 85 |
+
// remaining_bailout_depth will be reduced by 1.
|
| 86 |
+
// If no bailout depth is passed, the depth will be initialized from the
|
| 87 |
+
// current global fusion strategy settings.
|
| 88 |
+
const ExecutionPlan& getPlanFor(
|
| 89 |
+
Stack& inputs,
|
| 90 |
+
std::optional<size_t> remaining_bailout_depth = std::nullopt);
|
| 91 |
+
// Returns an optimized execution plan without requiring input arguments.
|
| 92 |
+
// Runs input-independent optimization passes (e.g. inlining, constant
|
| 93 |
+
// propagation, peephole, CSE) but skips profiling-based specializations
|
| 94 |
+
// that require runtime type/shape information.
|
| 95 |
+
const ExecutionPlan& getInputIndependentPlan();
|
| 96 |
+
GraphExecutorState getDebugState();
|
| 97 |
+
|
| 98 |
+
void debugFlushCompilationCache();
|
| 99 |
+
|
| 100 |
+
bool isOptimized() const;
|
| 101 |
+
|
| 102 |
+
private:
|
| 103 |
+
std::shared_ptr<GraphExecutorImplBase> pImpl;
|
| 104 |
+
};
|
| 105 |
+
|
| 106 |
+
TORCH_API Node* replaceBlockWithFallbackGraph(
|
| 107 |
+
Block* b,
|
| 108 |
+
ArrayRef<Value*> inputs);
|
| 109 |
+
|
| 110 |
+
// These passes need to run before it is valid to pass to the interpreter
|
| 111 |
+
// regardless of whether sizes have been specialized or not.
|
| 112 |
+
TORCH_API void runRequiredPasses(const std::shared_ptr<Graph>& g);
|
| 113 |
+
|
| 114 |
+
TORCH_API void debugSetFusionGroupInlining(bool state);
|
| 115 |
+
TORCH_API bool getFusionGroupInlining();
|
| 116 |
+
|
| 117 |
+
TORCH_API void debugSetAutodiffSubgraphInlining(bool state);
|
| 118 |
+
TORCH_API std::shared_ptr<Graph> lastExecutedOptimizedGraph();
|
| 119 |
+
|
| 120 |
+
TORCH_API std::atomic<bool>& getProfilingMode();
|
| 121 |
+
TORCH_API std::atomic<bool>& getExecutorMode();
|
| 122 |
+
TORCH_API std::atomic<size_t>& getNumProfiledRuns();
|
| 123 |
+
TORCH_API size_t getBailoutDepth();
|
| 124 |
+
TORCH_API bool IsNewExecutorEnabled();
|
| 125 |
+
|
| 126 |
+
struct TORCH_API GraphOptimizerEnabledGuard {
|
| 127 |
+
GraphOptimizerEnabledGuard(bool state)
|
| 128 |
+
: old_state_(getGraphExecutorOptimize()) {
|
| 129 |
+
setGraphExecutorOptimize(state);
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
~GraphOptimizerEnabledGuard() {
|
| 133 |
+
setGraphExecutorOptimize(old_state_);
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
bool old_state_;
|
| 137 |
+
};
|
| 138 |
+
|
| 139 |
+
namespace detail {
|
| 140 |
+
|
| 141 |
+
GraphExecutor* getGradExecutor(Operation& op);
|
| 142 |
+
|
| 143 |
+
GraphExecutor* getDifferentiableGraphOpExecutor(Operation& op);
|
| 144 |
+
|
| 145 |
+
// for debugging information we expose a way to get the last actually
|
| 146 |
+
// run graph. Previous approaches allowed querying the GraphExecutor
|
| 147 |
+
// for what graph it would run in certain circumstances (graphFor), but
|
| 148 |
+
// this is fragile because we sometimes change how these decisions are made.
|
| 149 |
+
// This interface still allows our tests to look at optimized graphs, but
|
| 150 |
+
// with less plumbing.
|
| 151 |
+
} // namespace detail
|
| 152 |
+
|
| 153 |
+
} // namespace torch::jit
|
| 154 |
+
|
| 155 |
+
#else
|
| 156 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 157 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_executor_impl.h
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <torch/csrc/jit/runtime/graph_executor.h>
|
| 4 |
+
|
| 5 |
+
#include <ATen/core/ivalue.h>
|
| 6 |
+
#include <c10/util/Exception.h>
|
| 7 |
+
#include <torch/csrc/autograd/grad_mode.h>
|
| 8 |
+
#include <torch/csrc/jit/frontend/tracer.h>
|
| 9 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 10 |
+
#include <torch/csrc/jit/passes/shape_analysis.h>
|
| 11 |
+
#include <torch/csrc/jit/resource_guard.h>
|
| 12 |
+
#include <torch/csrc/jit/runtime/argument_spec.h>
|
| 13 |
+
#include <torch/csrc/jit/runtime/autodiff.h>
|
| 14 |
+
#include <torch/csrc/jit/runtime/custom_operator.h>
|
| 15 |
+
#include <torch/csrc/jit/runtime/interpreter.h>
|
| 16 |
+
#include <torch/csrc/jit/runtime/profiling_record.h>
|
| 17 |
+
|
| 18 |
+
#include <torch/csrc/autograd/edge.h>
|
| 19 |
+
#include <torch/csrc/autograd/function.h>
|
| 20 |
+
#include <torch/csrc/jit/frontend/ir_emitter.h>
|
| 21 |
+
#include <torch/csrc/jit/runtime/logging.h>
|
| 22 |
+
|
| 23 |
+
#include <cstdint>
|
| 24 |
+
#include <iterator>
|
| 25 |
+
#include <memory>
|
| 26 |
+
#include <mutex>
|
| 27 |
+
#include <unordered_map>
|
| 28 |
+
#include <utility>
|
| 29 |
+
#include <vector>
|
| 30 |
+
|
| 31 |
+
namespace torch::jit {
|
| 32 |
+
|
| 33 |
+
void packGradient(const Gradient& gradient, Node* dnode);
|
| 34 |
+
bool needsGradient(const std::shared_ptr<const Graph>& graph);
|
| 35 |
+
void runOptimization(
|
| 36 |
+
std::shared_ptr<Graph>& graph,
|
| 37 |
+
bool unroll_non_constant_loops = true,
|
| 38 |
+
bool const_prop_user_classes = true);
|
| 39 |
+
void runNondiffOptimization(
|
| 40 |
+
std::shared_ptr<Graph>& graph,
|
| 41 |
+
bool strict_fuser_check = false);
|
| 42 |
+
void debugSetAutodiffSubgraphInlining(bool state);
|
| 43 |
+
bool TORCH_API getAutodiffSubgraphInlining();
|
| 44 |
+
|
| 45 |
+
void debugSetFusionGroupInlining(bool state);
|
| 46 |
+
bool getFusionGroupInlining();
|
| 47 |
+
|
| 48 |
+
// Tunable parameters for deciding when to create/keep subgraphs of
|
| 49 |
+
// differentiable code
|
| 50 |
+
const size_t autodiffSubgraphNodeThreshold = 2;
|
| 51 |
+
const size_t autodiffSubgraphInlineThreshold = 5;
|
| 52 |
+
|
| 53 |
+
// a Graph can be created via tracing, or via a language-based frontend
|
| 54 |
+
// GraphExecutor runs it. It can run the same graph on many different sizes
|
| 55 |
+
// and different requires_grad states, and handles specializations for each
|
| 56 |
+
// situation. GraphExecutor is completely unaware of tracing or module
|
| 57 |
+
// parameters to keep the tracing concerns separated.
|
| 58 |
+
struct GraphExecutorImplBase {
|
| 59 |
+
static std::shared_ptr<Graph> prepareGraph(
|
| 60 |
+
const std::shared_ptr<Graph>& graph) {
|
| 61 |
+
auto copy = graph->copy();
|
| 62 |
+
EraseShapeInformation(copy);
|
| 63 |
+
return copy;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
GraphExecutorImplBase(
|
| 67 |
+
const std::shared_ptr<Graph>& graph,
|
| 68 |
+
std::string function_name)
|
| 69 |
+
: graph(prepareGraph(graph)),
|
| 70 |
+
function_name_(std::move(function_name)),
|
| 71 |
+
num_inputs(this->graph->inputs().size()),
|
| 72 |
+
num_outputs(this->graph->outputs().size()) {}
|
| 73 |
+
|
| 74 |
+
// entry point where execution begins
|
| 75 |
+
void run(Stack& stack);
|
| 76 |
+
c10::intrusive_ptr<Future> runAsync(
|
| 77 |
+
Stack& stack,
|
| 78 |
+
TaskLauncher taskLauncher = at::launch);
|
| 79 |
+
|
| 80 |
+
virtual const ExecutionPlan& getPlanFor(
|
| 81 |
+
Stack& stack,
|
| 82 |
+
std::optional<size_t> remaining_bailout_depth = std::nullopt) = 0;
|
| 83 |
+
// Returns an optimized execution plan without requiring input arguments.
|
| 84 |
+
// Runs input-independent optimization passes (e.g. inlining, constant
|
| 85 |
+
// propagation, peephole, CSE) but skips profiling-based specializations
|
| 86 |
+
// that require runtime type/shape information.
|
| 87 |
+
virtual const ExecutionPlan& getInputIndependentPlan() = 0;
|
| 88 |
+
virtual GraphExecutorState getDebugState() = 0;
|
| 89 |
+
virtual ~GraphExecutorImplBase() = default;
|
| 90 |
+
|
| 91 |
+
virtual bool isOptimized() const {
|
| 92 |
+
return false;
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
protected:
|
| 96 |
+
friend struct GraphExecutor;
|
| 97 |
+
|
| 98 |
+
// The unoptimized starting graph. This field is effectively const, but we
|
| 99 |
+
// can't make it so because Graph::copy() is not const (and making it const is
|
| 100 |
+
// not that easy at this point).
|
| 101 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 102 |
+
std::shared_ptr<Graph> graph;
|
| 103 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 104 |
+
std::string function_name_;
|
| 105 |
+
|
| 106 |
+
// If false, we'll run the graph as we get it, without any optimizations.
|
| 107 |
+
// Useful for debugging.
|
| 108 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 109 |
+
const size_t num_inputs;
|
| 110 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 111 |
+
const size_t num_outputs;
|
| 112 |
+
|
| 113 |
+
// GraphExecutors can be accessed from multiple threads, so this thread needs
|
| 114 |
+
// to be held every time we access the fallback or plan_cache.
|
| 115 |
+
// NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
|
| 116 |
+
std::mutex compile_mutex;
|
| 117 |
+
};
|
| 118 |
+
|
| 119 |
+
} // namespace torch::jit
|
| 120 |
+
|
| 121 |
+
#else
|
| 122 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 123 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/graph_iterator.h
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 3 |
+
|
| 4 |
+
namespace torch::jit {
|
| 5 |
+
|
| 6 |
+
// This class facilitates depth-first iteration over all nodes in a graph.
|
| 7 |
+
class DepthFirstGraphNodeIterator {
|
| 8 |
+
Node* current_;
|
| 9 |
+
|
| 10 |
+
public:
|
| 11 |
+
// Constructor.
|
| 12 |
+
explicit DepthFirstGraphNodeIterator(std::shared_ptr<Graph>& graph)
|
| 13 |
+
: current_(*(graph->block()->nodes().begin())) {}
|
| 14 |
+
|
| 15 |
+
// Moves up and to the next node (may move up recursively).
|
| 16 |
+
void move_up() {
|
| 17 |
+
if (current_ == nullptr) {
|
| 18 |
+
return;
|
| 19 |
+
}
|
| 20 |
+
// Basically we start from the child block (which is current_)
|
| 21 |
+
// and we try to find the block that owns it. Now we need to check
|
| 22 |
+
// if that block is the graph root block, or if it is an If/Loop/etc
|
| 23 |
+
// block.
|
| 24 |
+
//
|
| 25 |
+
// If it's the graph root block we can stop because there is no "up"
|
| 26 |
+
// but if it is a node (e.g. If/Loop/etc) we need to apply logic
|
| 27 |
+
// based on where we are coming from to move to the next block.
|
| 28 |
+
// This might mean that we need to traverse up again (e.g. if we've
|
| 29 |
+
// reached the end of the else clause in an if block we need to go)
|
| 30 |
+
// up to the parent block that contains the if.
|
| 31 |
+
//
|
| 32 |
+
// Similarly if we've reached the end of the parent block containing
|
| 33 |
+
// the else clause we might need to go up again so this is a recursive
|
| 34 |
+
// function.
|
| 35 |
+
//
|
| 36 |
+
// BlockNode (if/loop/with)
|
| 37 |
+
// |
|
| 38 |
+
// [Block1] ... [Block2]
|
| 39 |
+
// |
|
| 40 |
+
// [ Node1, Node2, Node3, FromNode]
|
| 41 |
+
//
|
| 42 |
+
auto parent_block = current_->owningBlock();
|
| 43 |
+
TORCH_INTERNAL_ASSERT(parent_block, "Every node must be owned by a block");
|
| 44 |
+
|
| 45 |
+
// Get the node that owns the parent block. This node has to be an if,
|
| 46 |
+
// loop, or with.
|
| 47 |
+
auto parent_node = parent_block->owningNode();
|
| 48 |
+
if (parent_node == nullptr) {
|
| 49 |
+
// If there's no node that owns this current block then we're at the
|
| 50 |
+
// top of the graph and since we're trying to move up we have reached
|
| 51 |
+
// the end of the traversal.
|
| 52 |
+
current_ = nullptr;
|
| 53 |
+
return;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
// Check the type of node this root is.
|
| 57 |
+
if (parent_node->kind() == prim::If) {
|
| 58 |
+
// Need to check if we came from the `then` branch or the `else` branch.
|
| 59 |
+
auto* then_block = parent_node->blocks().at(0);
|
| 60 |
+
auto* else_block = parent_node->blocks().at(1);
|
| 61 |
+
|
| 62 |
+
if (parent_block == else_block) {
|
| 63 |
+
// If else block then we move to the next node in the parent block.
|
| 64 |
+
current_ = parent_node->next();
|
| 65 |
+
if (current_->kind() == prim::Return) {
|
| 66 |
+
move_up();
|
| 67 |
+
}
|
| 68 |
+
} else {
|
| 69 |
+
// If then block then move to the else block if it is not empty.
|
| 70 |
+
TORCH_INTERNAL_ASSERT(parent_block == then_block);
|
| 71 |
+
bool else_block_empty =
|
| 72 |
+
else_block->nodes().begin() == else_block->nodes().end();
|
| 73 |
+
|
| 74 |
+
if (!else_block_empty) {
|
| 75 |
+
current_ = *(else_block->nodes().begin());
|
| 76 |
+
} else {
|
| 77 |
+
// Since it's empty we move to the next node.
|
| 78 |
+
current_ = parent_node->next();
|
| 79 |
+
if (current_->kind() == prim::Return) {
|
| 80 |
+
move_up();
|
| 81 |
+
}
|
| 82 |
+
}
|
| 83 |
+
}
|
| 84 |
+
} else if (
|
| 85 |
+
parent_node->kind() == prim::Loop ||
|
| 86 |
+
parent_node->kind() == prim::With) {
|
| 87 |
+
current_ = parent_node->next();
|
| 88 |
+
if (current_->kind() == prim::Return) {
|
| 89 |
+
move_up();
|
| 90 |
+
}
|
| 91 |
+
} else {
|
| 92 |
+
TORCH_INTERNAL_ASSERT(
|
| 93 |
+
false, "Only if/loop/with nodes should have child blocks");
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
// Moves to the next adjacent node or up in to the parent if that is not
|
| 98 |
+
// possible.
|
| 99 |
+
void move_next() {
|
| 100 |
+
if (current_ == nullptr) {
|
| 101 |
+
return;
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
+
// Increment to the next node in the current block.
|
| 105 |
+
current_ = current_->next();
|
| 106 |
+
|
| 107 |
+
// Check if we're at the end of the block. If so we need
|
| 108 |
+
// to move upwards (if it makes sense to).
|
| 109 |
+
if (current_->kind() == prim::Return) {
|
| 110 |
+
move_up();
|
| 111 |
+
}
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
// Moves to the next node in the graph into children if it can.
|
| 115 |
+
void move_into() {
|
| 116 |
+
if (current_ == nullptr) {
|
| 117 |
+
return;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
// Check if we're currently on a node that contains sub-nodes.
|
| 121 |
+
if (current_->kind() == prim::If || current_->kind() == prim::Loop ||
|
| 122 |
+
current_->kind() == prim::With) {
|
| 123 |
+
auto* first_block = current_->blocks().at(0);
|
| 124 |
+
current_ = first_block->param_node();
|
| 125 |
+
// Move next will move up and out of the current node if the block is
|
| 126 |
+
// empty. `move_up` which is called by `move_next` will handle the
|
| 127 |
+
// difference between If, Loop, and With blocks appropriately.
|
| 128 |
+
move_next();
|
| 129 |
+
} else {
|
| 130 |
+
move_next();
|
| 131 |
+
}
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
// Get the next Node in the graph. \returns nullptr if there are no nodes
|
| 135 |
+
// left.
|
| 136 |
+
Node* next() {
|
| 137 |
+
auto result = current_;
|
| 138 |
+
|
| 139 |
+
// Try move into the existing node to set the next node to be returned.
|
| 140 |
+
// This will move to the next node if not possible, or move upwards and
|
| 141 |
+
// to the next.
|
| 142 |
+
move_into();
|
| 143 |
+
|
| 144 |
+
return result;
|
| 145 |
+
}
|
| 146 |
+
};
|
| 147 |
+
|
| 148 |
+
} // namespace torch::jit
|
| 149 |
+
|
| 150 |
+
#else
|
| 151 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 152 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/instruction.h
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <cstdint>
|
| 5 |
+
#include <typeinfo>
|
| 6 |
+
#include <unordered_set>
|
| 7 |
+
|
| 8 |
+
namespace torch::jit {
|
| 9 |
+
// instruction look like:
|
| 10 |
+
// op_code X, N
|
| 11 |
+
// meaning of X, N depend on the op:
|
| 12 |
+
// O - index into operator table
|
| 13 |
+
// R - index into register table
|
| 14 |
+
// I - literal integer
|
| 15 |
+
// C - index into constant table
|
| 16 |
+
// P - jump offset relative to beginning of current instruction
|
| 17 |
+
// F - index into function table
|
| 18 |
+
// T - index into the type table, used for guard instructions
|
| 19 |
+
// S - index into object slots
|
| 20 |
+
// C - index into code table
|
| 21 |
+
|
| 22 |
+
#define FORALL_OPCODES(_) \
|
| 23 |
+
_(OP, "O") /* invoke operator X */ \
|
| 24 |
+
_(OPN, "OI") /* invoke vararg operator X with N arguments */ \
|
| 25 |
+
_(LOAD, "R") /* push a value from a register X */ \
|
| 26 |
+
_(MOVE, "R") /* push a value from register X, clearing the register */ \
|
| 27 |
+
_(STOREN, "RI") /* store N values to registers [X, X+N) */ \
|
| 28 |
+
_(STORE, "R") /* store 1 value to registers X */ \
|
| 29 |
+
_(DROP, "") /* drop 1 value from the top of the stack */ \
|
| 30 |
+
_(DROPR, "R") /* clear register X */ \
|
| 31 |
+
_(LOADC, "C") /* push the constant X */ \
|
| 32 |
+
_(JF, "P") /* pop the top of the stack, if false, branch to P */ \
|
| 33 |
+
_(JMP, "P") /* unconditional branch to X */ \
|
| 34 |
+
_(LOOP, "PI") /* perform a loop, X is where to branch if cond is false */ \
|
| 35 |
+
_(RET, "") /* exit execution */ \
|
| 36 |
+
_(WAIT, "") /* wait for a future to be complete */ \
|
| 37 |
+
_(CALL, "F") /* call function X */ \
|
| 38 |
+
_(GUARD, "T") /* check a guard against type_table, true if passes */ \
|
| 39 |
+
_(TYPECHECK, "TN") /* check each type of input[i] against type_table[X+N] */ \
|
| 40 |
+
_(FAIL_GUARD, "T") /* fail a guard, patch back to GUARD */ \
|
| 41 |
+
_(PROFILE_OP, "F") /* get a callback from profile_function_table at X */ \
|
| 42 |
+
_(TAIL_CALL, "F") /* replace current frame with function F */ \
|
| 43 |
+
_(INTERFACE_CALL, "CI") /* call method X on the first argument (of N) */ \
|
| 44 |
+
_(GET_ATTR, "S") /* get attribute from slot X in an Object */ \
|
| 45 |
+
_(SET_ATTR, "S") /* set attribute to slot X in an Object */ \
|
| 46 |
+
_(LIST_UNPACK, "I") /* unpack list expecting length I */ \
|
| 47 |
+
_(TUPLE_CONSTRUCT, "I") /* construct a tuple using X inputs */ \
|
| 48 |
+
_(NAMED_TUPLE_CONSTRUCT, \
|
| 49 |
+
"TI") /* construct a tuple of type X, using N inputs */ \
|
| 50 |
+
_(LIST_CONSTRUCT, "TI") /* construct a list of type X, using N inputs */ \
|
| 51 |
+
_(DICT_CONSTRUCT, "TI") /* construct a dict of type X, using N inputs */ \
|
| 52 |
+
_(CREATE_OBJECT, "T") /* create an object of type X */ \
|
| 53 |
+
_(ISINSTANCE, "TI") /* check object is one of types[X:X+N] */ \
|
| 54 |
+
_(TUPLE_SLICE, "II") /* slice tup[X:(X+N)] */ \
|
| 55 |
+
_(TUPLE_INDEX, "") /* get the value from a tuple at that index */ \
|
| 56 |
+
_(RAISE_EXCEPTION, "") /* throws the exception from Python */ \
|
| 57 |
+
_(DICT_INDEX, "") /* gets the value from the dict for given key */ \
|
| 58 |
+
_(UNCHECKED_CAST, "") /* perform an unchecked cast operation */ \
|
| 59 |
+
_(__IS__, "") /* performs `is` operator from Python */ \
|
| 60 |
+
_(UN_INITIALIZED, \
|
| 61 |
+
"") /* sets default values to variables that are uninitialized */ \
|
| 62 |
+
_(__ISNOT__, "") /* performs `is not` operator from Python */ \
|
| 63 |
+
_(FORMAT, "I") /* performs string format function `f strings` or `{}.format` \
|
| 64 |
+
the number of inputs in stored in X */ \
|
| 65 |
+
_(DEVICE, "") /* invokes aten::device for a Tensor */ \
|
| 66 |
+
_(DTYPE, "") /* invokes aten::dtype for a Tensor */ \
|
| 67 |
+
_(DIM, "") /* invokes aten::dim for a Tensor */ \
|
| 68 |
+
_(__NOT__, "") /* performs `not` operator from Python */ \
|
| 69 |
+
_(TO_LIST, "") /* convert the input to a list */ \
|
| 70 |
+
_(NUM_TO_TENSOR, \
|
| 71 |
+
"") /* performs the conversion of a number/scalar to Tensor */ \
|
| 72 |
+
_(IS_CUDA, "") /* invokes aten::is_cuda for a Tensor */ \
|
| 73 |
+
_(FORK, "CN") /* launch a thread to run code entry x with N inputs */ \
|
| 74 |
+
_(WARN, "I") /* emit a warning with line information */ \
|
| 75 |
+
_(ENTER, "EN") /* enter scope of a contextmanager */ \
|
| 76 |
+
_(EXIT, "EX") /* exit the last entered contextmanager */ \
|
| 77 |
+
_(AWAITABLE, "CN") /* initialize await for code entry x with N inputs */
|
| 78 |
+
|
| 79 |
+
enum OpCode : uint8_t {
|
| 80 |
+
#define DEFINE_OP(op, _) op,
|
| 81 |
+
FORALL_OPCODES(DEFINE_OP)
|
| 82 |
+
#undef DEFINE_OP
|
| 83 |
+
};
|
| 84 |
+
|
| 85 |
+
struct Instruction {
|
| 86 |
+
OpCode op;
|
| 87 |
+
uint8_t unused{0};
|
| 88 |
+
uint16_t N;
|
| 89 |
+
int32_t X;
|
| 90 |
+
// TODO: check for overflow
|
| 91 |
+
Instruction(OpCode op, int32_t X, uint16_t N) : op(op), N(N), X(X) {}
|
| 92 |
+
};
|
| 93 |
+
std::ostream& operator<<(std::ostream& out, Instruction inst);
|
| 94 |
+
|
| 95 |
+
bool isOpSupportedInMobile(OpCode op);
|
| 96 |
+
char const* toString(OpCode op);
|
| 97 |
+
OpCode parseOpCode(const char* str);
|
| 98 |
+
|
| 99 |
+
} // namespace torch::jit
|
| 100 |
+
|
| 101 |
+
#else
|
| 102 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 103 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter.h
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <memory>
|
| 4 |
+
#include <optional>
|
| 5 |
+
#include <vector>
|
| 6 |
+
|
| 7 |
+
#include <ATen/ThreadLocalState.h>
|
| 8 |
+
#include <ATen/core/ivalue.h>
|
| 9 |
+
#include <ATen/core/jit_type.h>
|
| 10 |
+
#include <torch/csrc/Export.h>
|
| 11 |
+
#include <torch/csrc/jit/frontend/source_range.h>
|
| 12 |
+
|
| 13 |
+
TORCH_DECLARE_bool(torch_jit_disable_warning_prints);
|
| 14 |
+
TORCH_DECLARE_bool(torch_jit_enable_rethrow_caught_exception);
|
| 15 |
+
|
| 16 |
+
namespace at {
|
| 17 |
+
class Tensor;
|
| 18 |
+
TORCH_API void launch(std::function<void()> func);
|
| 19 |
+
} // namespace at
|
| 20 |
+
namespace c10 {
|
| 21 |
+
struct IValue;
|
| 22 |
+
struct OperatorName;
|
| 23 |
+
} // namespace c10
|
| 24 |
+
|
| 25 |
+
namespace torch::jit {
|
| 26 |
+
|
| 27 |
+
// The interpreter run Graphs with Tensor inputs and Tensor outputs
|
| 28 |
+
// a separate component in the autograd handles unwrapping and wrapping
|
| 29 |
+
// variable objects for use in the interpreter.
|
| 30 |
+
namespace interpreter {
|
| 31 |
+
struct CodeImpl;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
struct Node;
|
| 35 |
+
struct GraphExecutor;
|
| 36 |
+
struct InterpreterStateImpl;
|
| 37 |
+
struct Graph;
|
| 38 |
+
struct Node;
|
| 39 |
+
struct Instruction;
|
| 40 |
+
using Stack = std::vector<c10::IValue>;
|
| 41 |
+
using c10::ivalue::Future;
|
| 42 |
+
using TaskLauncher = std::function<void(std::function<void()>)>;
|
| 43 |
+
|
| 44 |
+
bool TORCH_API in_torchscript_runtime();
|
| 45 |
+
|
| 46 |
+
struct TORCH_API Code {
|
| 47 |
+
Code() = default;
|
| 48 |
+
explicit Code(interpreter::CodeImpl* pImpl);
|
| 49 |
+
// remaining_bailout_depth is irrelevant in a `Code` object unless the `Code`
|
| 50 |
+
// is directly created by `GraphExecutor` in which case it's likely to contain
|
| 51 |
+
// `prim::BailOut`s to control the maximum depth of bailout chains
|
| 52 |
+
explicit Code(
|
| 53 |
+
const std::shared_ptr<Graph>& graph,
|
| 54 |
+
std::string function_name,
|
| 55 |
+
size_t remaining_bailout_depth = 0);
|
| 56 |
+
|
| 57 |
+
const std::vector<GraphExecutor*>& grad_executors();
|
| 58 |
+
const std::vector<GraphExecutor*>& diff_graph_op_executors();
|
| 59 |
+
|
| 60 |
+
explicit operator bool() const {
|
| 61 |
+
return pImpl != nullptr;
|
| 62 |
+
}
|
| 63 |
+
size_t num_inputs() const;
|
| 64 |
+
size_t num_outputs() const;
|
| 65 |
+
size_t num_bailouts() const;
|
| 66 |
+
const std::vector<c10::IValue>& constant_table() const;
|
| 67 |
+
const std::vector<c10::TypePtr>& type_table() const;
|
| 68 |
+
const std::vector<Instruction>& instructions() const;
|
| 69 |
+
const std::unordered_map<std::string, size_t>& op_to_num_specified_args()
|
| 70 |
+
const;
|
| 71 |
+
const std::vector<Node*>& instructions_source() const;
|
| 72 |
+
void request_bailout(size_t index);
|
| 73 |
+
size_t register_size() const;
|
| 74 |
+
std::shared_ptr<Graph> graph() const;
|
| 75 |
+
|
| 76 |
+
private:
|
| 77 |
+
std::shared_ptr<interpreter::CodeImpl> pImpl;
|
| 78 |
+
friend struct InterpreterStateImpl;
|
| 79 |
+
friend std::ostream& operator<<(std::ostream& out, const Code& code);
|
| 80 |
+
};
|
| 81 |
+
|
| 82 |
+
struct TORCH_API MobileCode : Code {
|
| 83 |
+
explicit MobileCode(
|
| 84 |
+
const std::shared_ptr<Graph>& graph,
|
| 85 |
+
std::string function_name,
|
| 86 |
+
bool emit_default_input_instructions = true,
|
| 87 |
+
bool support_default_args_before_out = true,
|
| 88 |
+
bool emit_promoted_ops = true,
|
| 89 |
+
size_t remaining_bailout_depth = 0);
|
| 90 |
+
};
|
| 91 |
+
|
| 92 |
+
struct InterpreterState {
|
| 93 |
+
TORCH_API InterpreterState(
|
| 94 |
+
const Code& code,
|
| 95 |
+
TaskLauncher taskLauncher = at::launch);
|
| 96 |
+
TORCH_API void run(Stack& stack);
|
| 97 |
+
TORCH_API c10::intrusive_ptr<Future> runAsync(Stack& stack);
|
| 98 |
+
c10::intrusive_ptr<Future> getFuture();
|
| 99 |
+
|
| 100 |
+
private:
|
| 101 |
+
InterpreterState(c10::intrusive_ptr<c10::intrusive_ptr_target> pImpl);
|
| 102 |
+
// Ideally we should use c10::intrusive_ptr<InterpreterStateImpl> for pImpl;
|
| 103 |
+
// but intrusive_ptr requires full definition of InterpreterStateImpl,
|
| 104 |
+
// which we need to hide in the header.
|
| 105 |
+
c10::intrusive_ptr<c10::intrusive_ptr_target> pImpl;
|
| 106 |
+
friend struct InterpreterStateImpl;
|
| 107 |
+
};
|
| 108 |
+
|
| 109 |
+
// Created by wait()
|
| 110 |
+
struct Suspend : public std::exception {
|
| 111 |
+
const char* what() const noexcept override {
|
| 112 |
+
return "Suspend";
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
explicit Suspend(c10::intrusive_ptr<Future> future_)
|
| 116 |
+
: future(std::move(future_)) {}
|
| 117 |
+
|
| 118 |
+
c10::intrusive_ptr<Future> future;
|
| 119 |
+
};
|
| 120 |
+
|
| 121 |
+
// InterpreterContinuation propagates dist_autograd_context_id
|
| 122 |
+
// through (and only through) the forward pass manually, other
|
| 123 |
+
// thread local settings are propagated with ThreadLocalState
|
| 124 |
+
struct InterpreterContinuation {
|
| 125 |
+
InterpreterContinuation(
|
| 126 |
+
InterpreterState state_,
|
| 127 |
+
Stack stack_,
|
| 128 |
+
int64_t dist_autograd_context_id = 0,
|
| 129 |
+
std::optional<at::ThreadLocalState> tls_state = std::nullopt)
|
| 130 |
+
: state(std::move(state_)),
|
| 131 |
+
stack(std::move(stack_)),
|
| 132 |
+
tls_state_(std::move(tls_state))
|
| 133 |
+
#ifdef USE_DISTRIBUTED
|
| 134 |
+
,
|
| 135 |
+
dist_autograd_context_id_(dist_autograd_context_id)
|
| 136 |
+
#endif
|
| 137 |
+
{
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
void operator()();
|
| 141 |
+
|
| 142 |
+
private:
|
| 143 |
+
InterpreterState state;
|
| 144 |
+
Stack stack;
|
| 145 |
+
std::optional<at::ThreadLocalState> tls_state_ = std::nullopt;
|
| 146 |
+
#ifdef USE_DISTRIBUTED
|
| 147 |
+
int64_t dist_autograd_context_id_;
|
| 148 |
+
#endif
|
| 149 |
+
};
|
| 150 |
+
|
| 151 |
+
// what is the tensors type, including state from the current execution context
|
| 152 |
+
// that modifies how the tensor behaves. For instance if no_grad is enabled
|
| 153 |
+
// this will cause the TensorType to have requires_grad=False.
|
| 154 |
+
TORCH_API at::TensorTypePtr tensorTypeInCurrentExecutionContext(
|
| 155 |
+
const at::Tensor& t);
|
| 156 |
+
|
| 157 |
+
// current (TLS) TorchScript interpreter callstack
|
| 158 |
+
TORCH_API std::vector<StackEntry> currentCallstack();
|
| 159 |
+
TORCH_API std::vector<std::string> currentModuleHierarchy();
|
| 160 |
+
|
| 161 |
+
} // namespace torch::jit
|
| 162 |
+
|
| 163 |
+
#else
|
| 164 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 165 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/can_emit_inline.h
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <memory>
|
| 5 |
+
|
| 6 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 7 |
+
|
| 8 |
+
namespace torch::jit::interpreter {
|
| 9 |
+
/*
|
| 10 |
+
This is an optimization that reduces the number of store/load/move nodes needed
|
| 11 |
+
by recognizing that parts of the graph are simple trees like a*x + b*y. When
|
| 12 |
+
this happens it is possible to work directly off of the stack by emitting the
|
| 13 |
+
tree in a depth-first left-to-right manner:
|
| 14 |
+
load a
|
| 15 |
+
load x
|
| 16 |
+
mul # stack now is a*x
|
| 17 |
+
load b
|
| 18 |
+
load y
|
| 19 |
+
mul # stack now is a*x, b*y
|
| 20 |
+
add
|
| 21 |
+
|
| 22 |
+
can_emit_inline_[node] == true means that this node participates as a non-root
|
| 23 |
+
member of one of these trees. The code emitter will not emit this node when
|
| 24 |
+
it is encountered in the node. Instead the node is emitted in a depth first
|
| 25 |
+
traversal from where it is used in a tree.
|
| 26 |
+
|
| 27 |
+
To participate in a tree a node must have a single use (otherwise it is not
|
| 28 |
+
tree-like) and output a single value (for simplicity.) If our IR was functional,
|
| 29 |
+
these would be the only constraints. However, many nodes have side effects, so
|
| 30 |
+
we must ensure that emitting the nodes in depth first order from the tree's root
|
| 31 |
+
_does not reorder the emission of the nodes_. To ensure this, we work backward
|
| 32 |
+
from the root of a potential tree, visiting its inputs in reverse depth first
|
| 33 |
+
order, while scanning the node list backward (with the block_point node). When
|
| 34 |
+
these traversal line up we know it is safe to emit the tree in this way. We
|
| 35 |
+
ignore constant nodes, which do not have side effects.
|
| 36 |
+
*/
|
| 37 |
+
struct CanEmitInline {
|
| 38 |
+
explicit CanEmitInline(Graph& graph) {
|
| 39 |
+
scanBlock(graph.block());
|
| 40 |
+
}
|
| 41 |
+
bool canInline(Value* v) {
|
| 42 |
+
return v->node()->kind() != prim::Param &&
|
| 43 |
+
// without this a BailOut may float downstream past some later
|
| 44 |
+
// BailOut
|
| 45 |
+
// and receive a higher jf_index. Then a GUARD instruction
|
| 46 |
+
// we generated for the floated BailOut will get popped up from the
|
| 47 |
+
// instruction stack
|
| 48 |
+
// by the later BailOut in createBailoutBlock and its jf_index
|
| 49 |
+
// will become invalid.
|
| 50 |
+
v->node()->kind() != prim::TensorExprGroup &&
|
| 51 |
+
v->node()->kind() != prim::TensorExprDynamicGroup &&
|
| 52 |
+
v->node()->kind() != prim::StaticSubgraph &&
|
| 53 |
+
v->node()->kind() != prim::CudaFusionGroup &&
|
| 54 |
+
v->node()->kind() != prim::FusionGroup &&
|
| 55 |
+
v->node()->kind() != prim::BailOut && v->uses().size() == 1 &&
|
| 56 |
+
v->node()->outputs().size() == 1;
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
Node* previousNonConstant(Node* n) {
|
| 60 |
+
do {
|
| 61 |
+
n = n->prev();
|
| 62 |
+
} while (n->kind() == prim::Constant);
|
| 63 |
+
return n;
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
Node* scanValue(Node* block_point, Value* v) {
|
| 67 |
+
// this node is a candidate for inline, if our reverse scan of the
|
| 68 |
+
// node list lines up with the use of v, we know it will be emitted in
|
| 69 |
+
// tree order, and we can inlining. Scan continues for further nodes.
|
| 70 |
+
if (v->node() == block_point && canInline(v)) {
|
| 71 |
+
// since we inlined this node, we may be able to recursively inline
|
| 72 |
+
// its inputs, so we continue scanning it
|
| 73 |
+
block_point = scanNode(v->node());
|
| 74 |
+
can_emit_inline_[v->node()] = true;
|
| 75 |
+
}
|
| 76 |
+
// if it does not line up, we can't inline 'v', and will just generate
|
| 77 |
+
// a load/move for it. However, other inputs may still appear in tree
|
| 78 |
+
// order so we continue the scan of the inputs.
|
| 79 |
+
return block_point;
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
Node* scanNode(Node* n) {
|
| 83 |
+
// don't bother to scan nodes we have already determined to be inline
|
| 84 |
+
if (can_emit_inline_.count(n)) {
|
| 85 |
+
return nullptr;
|
| 86 |
+
}
|
| 87 |
+
for (auto b : n->blocks()) {
|
| 88 |
+
scanBlock(b);
|
| 89 |
+
}
|
| 90 |
+
Node* block_point = previousNonConstant(n);
|
| 91 |
+
for (auto it = n->inputs().rbegin(), end = n->inputs().rend(); it != end;
|
| 92 |
+
++it) {
|
| 93 |
+
block_point = scanValue(block_point, *it);
|
| 94 |
+
}
|
| 95 |
+
return block_point;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
void scanBlock(Block* b) {
|
| 99 |
+
scanNode(b->return_node());
|
| 100 |
+
for (auto node : b->nodes().reverse()) {
|
| 101 |
+
scanNode(node);
|
| 102 |
+
}
|
| 103 |
+
}
|
| 104 |
+
std::unordered_map<Node*, bool> can_emit_inline_;
|
| 105 |
+
};
|
| 106 |
+
|
| 107 |
+
} // namespace torch::jit::interpreter
|
| 108 |
+
|
| 109 |
+
#else
|
| 110 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 111 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/code_impl.h
ADDED
|
@@ -0,0 +1,1066 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <memory>
|
| 5 |
+
#include <unordered_map>
|
| 6 |
+
#include <utility>
|
| 7 |
+
#include <vector>
|
| 8 |
+
|
| 9 |
+
#include <c10/util/irange.h>
|
| 10 |
+
#include <torch/csrc/jit/api/function_impl.h>
|
| 11 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 12 |
+
#include <torch/csrc/jit/jit_log.h>
|
| 13 |
+
#include <torch/csrc/jit/passes/bailout_graph.h>
|
| 14 |
+
#include <torch/csrc/jit/runtime/calculate_necessary_args.h>
|
| 15 |
+
#include <torch/csrc/jit/runtime/graph_iterator.h>
|
| 16 |
+
#include <torch/csrc/jit/runtime/instruction.h>
|
| 17 |
+
#include <torch/csrc/jit/runtime/interpreter/preprocess_graph.h>
|
| 18 |
+
|
| 19 |
+
TORCH_DECLARE_bool(torch_jit_enable_expanded_stacks);
|
| 20 |
+
TORCH_DECLARE_bool(torch_jit_expanded_stacks_mangled);
|
| 21 |
+
|
| 22 |
+
namespace torch::jit::interpreter {
|
| 23 |
+
|
| 24 |
+
template <class Ttarget, class Tsource>
|
| 25 |
+
Ttarget safe_narrow_cast(Tsource v) {
|
| 26 |
+
Ttarget res = static_cast<Ttarget>(v);
|
| 27 |
+
// Casting it back to check whether it overflew.
|
| 28 |
+
if (static_cast<Tsource>(res) != v) {
|
| 29 |
+
TORCH_WARN(
|
| 30 |
+
"ATTENTION: your model computation is overflowing, safe_narrow_cast<>() failed");
|
| 31 |
+
return v;
|
| 32 |
+
}
|
| 33 |
+
return res;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
// BailoutBlocks are used to temporarily store
|
| 37 |
+
// instructions (typically, argument LOADs and TAIL_CALL)
|
| 38 |
+
// generated for prim::BailOut nodes
|
| 39 |
+
// before they are merged back into
|
| 40 |
+
// CodeImpl._instructions_ by insertBailoutBlocks
|
| 41 |
+
struct BailoutBlock {
|
| 42 |
+
size_t jf_instruction_index; // this node gets patched to jump here on failure
|
| 43 |
+
std::vector<Instruction> instructions; // ends in a TAIL_CALL
|
| 44 |
+
|
| 45 |
+
explicit BailoutBlock(size_t jf_index) : jf_instruction_index(jf_index) {}
|
| 46 |
+
};
|
| 47 |
+
|
| 48 |
+
// for keeping track of the current node
|
| 49 |
+
struct WithCurrentNode {
|
| 50 |
+
WithCurrentNode(Node** loc, Node* new_value) : loc_(loc), old_value_(*loc_) {
|
| 51 |
+
*loc = new_value;
|
| 52 |
+
}
|
| 53 |
+
~WithCurrentNode() {
|
| 54 |
+
*loc_ = old_value_;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
private:
|
| 58 |
+
Node** loc_;
|
| 59 |
+
Node* old_value_;
|
| 60 |
+
};
|
| 61 |
+
|
| 62 |
+
struct NodeSourceInfo {
|
| 63 |
+
const char* func_name_{nullptr};
|
| 64 |
+
const char* file_name_{nullptr};
|
| 65 |
+
size_t line_{0};
|
| 66 |
+
NodeSourceInfo() = default;
|
| 67 |
+
};
|
| 68 |
+
|
| 69 |
+
struct CodeImpl {
|
| 70 |
+
friend struct InterpreterState;
|
| 71 |
+
std::vector<Instruction> instructions_;
|
| 72 |
+
|
| 73 |
+
const c10::unique_t node_stack_attr_symbol_ =
|
| 74 |
+
static_cast<c10::unique_t>(attr::node_stack_idx);
|
| 75 |
+
// Expanded inlined stacks as pointers to values in inlined call stack.
|
| 76 |
+
std::vector<std::vector<NodeSourceInfo>> expanded_node_stacks_;
|
| 77 |
+
|
| 78 |
+
// same length as instructions.
|
| 79 |
+
// what node in the graph cause this
|
| 80 |
+
// instruction to be emitted?
|
| 81 |
+
std::vector<Node*> instructions_source_;
|
| 82 |
+
std::vector<IValue> constant_table_;
|
| 83 |
+
std::vector<Operation> operator_table_;
|
| 84 |
+
#ifndef NDEBUG
|
| 85 |
+
std::vector<Operator> full_operator_table_;
|
| 86 |
+
#endif
|
| 87 |
+
// map<(op name, num inputs), index in operator table>, to avoid duplicates,
|
| 88 |
+
// not including vararg operators
|
| 89 |
+
std::unordered_map<
|
| 90 |
+
std::pair<std::string, int>,
|
| 91 |
+
int,
|
| 92 |
+
std::function<size_t(const std::pair<std::string, int>& p)>>
|
| 93 |
+
operator_table_inv_;
|
| 94 |
+
std::vector<Function*> function_table_;
|
| 95 |
+
std::vector<std::unique_ptr<GraphFunction>> forked_functions_;
|
| 96 |
+
std::vector<std::unique_ptr<GraphFunction>> awaited_functions_;
|
| 97 |
+
std::vector<TypePtr> type_table_;
|
| 98 |
+
std::vector<std::function<void(std::vector<IValue>&)>>
|
| 99 |
+
profile_function_table_;
|
| 100 |
+
|
| 101 |
+
int register_size_ = 0;
|
| 102 |
+
size_t n_outputs;
|
| 103 |
+
size_t n_inputs;
|
| 104 |
+
TypePtr return_type_;
|
| 105 |
+
std::string function_name_;
|
| 106 |
+
|
| 107 |
+
// We MUST hold onto graph here because some Operators stored in the
|
| 108 |
+
// instruction lists have dependencies on meta-data stored in the graph
|
| 109 |
+
// that would be dead otherwise.
|
| 110 |
+
// It is also very useful for debugging interpreter problems to
|
| 111 |
+
// keep this around.
|
| 112 |
+
std::shared_ptr<Graph> graph_;
|
| 113 |
+
std::optional<std::vector<GraphExecutor*>> grad_executors_;
|
| 114 |
+
std::optional<std::vector<GraphExecutor*>> forward_executors_;
|
| 115 |
+
PreprocessGraph preprocess_;
|
| 116 |
+
|
| 117 |
+
// map from unique of nodes to register in register table
|
| 118 |
+
std::unordered_map<Value*, int> value_to_reg_;
|
| 119 |
+
|
| 120 |
+
// map from operator name to specified arguments
|
| 121 |
+
// Example: for a schema of aten::foo.str
|
| 122 |
+
// aten::foo.str(arg0: str="default", arg1: int=0,
|
| 123 |
+
// arg2: bool=False, arg3: float=0.0)
|
| 124 |
+
// If the usages in a graph is:
|
| 125 |
+
// aten::foo("somestr", arg1=0, arg2=True, arg3=0.0)
|
| 126 |
+
// aten::foo("somestr", arg1=1, arg2=False, arg3=0.0)
|
| 127 |
+
// op_to_num_specified_args_["aten::foo.str"] = 3
|
| 128 |
+
// This is because for all usages, at most 3 args are used.
|
| 129 |
+
std::unordered_map<std::string, size_t> op_to_num_specified_args_;
|
| 130 |
+
|
| 131 |
+
std::unordered_map<std::string, size_t> op_to_num_out_args_;
|
| 132 |
+
|
| 133 |
+
// running count of uses as we emit. When we reach use_count_[v] =
|
| 134 |
+
// v.uses().size() we know it is the final use and we can move rather than
|
| 135 |
+
// load.
|
| 136 |
+
std::unordered_map<Value*, size_t> use_count_;
|
| 137 |
+
|
| 138 |
+
Node* current_node_; // used in creation of code to keep track
|
| 139 |
+
// of node being emitted
|
| 140 |
+
Node* last_inserted_op_ = nullptr;
|
| 141 |
+
|
| 142 |
+
// out-of-line jumps for bailouts that are patched in at the end
|
| 143 |
+
std::vector<BailoutBlock> bailout_blocks_;
|
| 144 |
+
std::vector<std::unique_ptr<Function>> bailout_functions_;
|
| 145 |
+
size_t remaining_bailout_depth_;
|
| 146 |
+
|
| 147 |
+
CodeImpl(
|
| 148 |
+
const std::shared_ptr<Graph>& graph,
|
| 149 |
+
std::string function_name,
|
| 150 |
+
size_t remaining_bailout_depth,
|
| 151 |
+
bool emit_instructions = true)
|
| 152 |
+
: operator_table_inv_(
|
| 153 |
+
0,
|
| 154 |
+
[](const std::pair<std::string, int>& p) {
|
| 155 |
+
return std::hash<std::string>()(p.first) ^
|
| 156 |
+
std::hash<int>()(p.second);
|
| 157 |
+
}),
|
| 158 |
+
function_name_(std::move(function_name)),
|
| 159 |
+
preprocess_(*graph),
|
| 160 |
+
current_node_(preprocess_.graph->return_node()),
|
| 161 |
+
remaining_bailout_depth_(remaining_bailout_depth) {
|
| 162 |
+
graph_ = preprocess_.graph;
|
| 163 |
+
n_outputs = graph_->outputs().size();
|
| 164 |
+
if (n_outputs == 1) {
|
| 165 |
+
return_type_ = graph->outputs().at(0)->type();
|
| 166 |
+
} else {
|
| 167 |
+
return_type_ = TupleType::create(
|
| 168 |
+
fmap(graph->outputs(), [](const Value* v) { return v->type(); }));
|
| 169 |
+
}
|
| 170 |
+
n_inputs = graph_->inputs().size();
|
| 171 |
+
if (emit_instructions) {
|
| 172 |
+
// NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.VirtualCall)
|
| 173 |
+
run();
|
| 174 |
+
}
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
virtual ~CodeImpl() = default;
|
| 178 |
+
|
| 179 |
+
// since subclass of CodeImpl needs to populate
|
| 180 |
+
// op_to_num_specified_args, we separate the calls
|
| 181 |
+
// that changes internals of CodeImpl into a separate
|
| 182 |
+
// function.
|
| 183 |
+
virtual void run() {
|
| 184 |
+
emitCodeForBlock(graph_->block());
|
| 185 |
+
insertInstruction(RET);
|
| 186 |
+
// we deferred the emission of bailout blocks so they appear at the end
|
| 187 |
+
// emit them now and patch up the jumps
|
| 188 |
+
insertBailoutBlocks();
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
const std::vector<c10::IValue>& constant_table() const {
|
| 192 |
+
return constant_table_;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
void request_bailout(size_t index) {
|
| 196 |
+
auto count = index;
|
| 197 |
+
for (const auto instr_index : c10::irange(instructions_.size())) {
|
| 198 |
+
if (instructions_[instr_index].op == GUARD ||
|
| 199 |
+
instructions_[instr_index].op == FAIL_GUARD) {
|
| 200 |
+
if (count-- == 0) {
|
| 201 |
+
// patching GUARD to FAIL_GUARD
|
| 202 |
+
instructions_[instr_index].op = FAIL_GUARD;
|
| 203 |
+
GRAPH_DEBUG(
|
| 204 |
+
"Added a bailout request for ",
|
| 205 |
+
index,
|
| 206 |
+
" at instruction ",
|
| 207 |
+
instr_index);
|
| 208 |
+
break;
|
| 209 |
+
}
|
| 210 |
+
}
|
| 211 |
+
}
|
| 212 |
+
}
|
| 213 |
+
|
| 214 |
+
const std::vector<Instruction>& instructions() const {
|
| 215 |
+
return instructions_;
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
const std::unordered_map<std::string, size_t>& op_to_num_specified_args()
|
| 219 |
+
const {
|
| 220 |
+
return op_to_num_specified_args_;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
const std::vector<Node*>& instructions_source() const {
|
| 224 |
+
return instructions_source_;
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
NodeSourceInfo getSourceInfoFromSourceRange(const SourceRange& range) {
|
| 228 |
+
NodeSourceInfo nodeSource;
|
| 229 |
+
SourceRange r = range;
|
| 230 |
+
if (!FLAGS_torch_jit_expanded_stacks_mangled && range.source()) {
|
| 231 |
+
if (auto orig = range.source()->findSourceRangeThatGenerated(r)) {
|
| 232 |
+
r = *orig;
|
| 233 |
+
}
|
| 234 |
+
}
|
| 235 |
+
if (r.source()) {
|
| 236 |
+
auto lineno = r.source()->lineno_for_offset(r.start());
|
| 237 |
+
nodeSource.line_ = r.source()->lineno_to_source_lineno(lineno);
|
| 238 |
+
if (r.source()->filename()) {
|
| 239 |
+
nodeSource.file_name_ = r.source()->filename().value().c_str();
|
| 240 |
+
}
|
| 241 |
+
}
|
| 242 |
+
return nodeSource;
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
void expandInlinedNodeStack(
|
| 246 |
+
const InlinedCallStackPtr& cs,
|
| 247 |
+
std::vector<NodeSourceInfo>* expandedstack) {
|
| 248 |
+
auto nodeSourceInfo = getSourceInfoFromSourceRange(cs->source_range());
|
| 249 |
+
nodeSourceInfo.func_name_ = cs->function_name().c_str();
|
| 250 |
+
expandedstack->emplace_back(nodeSourceInfo);
|
| 251 |
+
|
| 252 |
+
if (cs->callee()) {
|
| 253 |
+
expandInlinedNodeStack(cs->callee().value(), expandedstack);
|
| 254 |
+
}
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
void getNodeStack(
|
| 258 |
+
const Node* node,
|
| 259 |
+
std::vector<NodeSourceInfo>* expandedstack) {
|
| 260 |
+
if (current_node_->callstack()) {
|
| 261 |
+
expandInlinedNodeStack(current_node_->callstack().value(), expandedstack);
|
| 262 |
+
}
|
| 263 |
+
auto nodeSourceInfo = getSourceInfoFromSourceRange(node->sourceRange());
|
| 264 |
+
expandedstack->emplace_back(nodeSourceInfo);
|
| 265 |
+
}
|
| 266 |
+
|
| 267 |
+
void insertInstruction(OpCode op, int64_t X = 0, uint64_t N = 0) {
|
| 268 |
+
instructions_.emplace_back(
|
| 269 |
+
op,
|
| 270 |
+
safe_narrow_cast<int32_t, int64_t>(X),
|
| 271 |
+
safe_narrow_cast<uint16_t, uint64_t>(N));
|
| 272 |
+
instructions_source_.emplace_back(current_node_);
|
| 273 |
+
|
| 274 |
+
if (FLAGS_torch_jit_enable_expanded_stacks &&
|
| 275 |
+
!current_node_->hasAttribute(attr::node_stack_idx)) {
|
| 276 |
+
std::vector<NodeSourceInfo> expandedStack;
|
| 277 |
+
getNodeStack(current_node_, &expandedStack);
|
| 278 |
+
auto insertIdx = expanded_node_stacks_.size();
|
| 279 |
+
expanded_node_stacks_.emplace_back(expandedStack);
|
| 280 |
+
current_node_->i_(attr::node_stack_idx, insertIdx);
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
// check that we didn't accidentally emit nodes out of topological order
|
| 284 |
+
if (op == OP) {
|
| 285 |
+
if (last_inserted_op_ != nullptr && current_node_ != last_inserted_op_ &&
|
| 286 |
+
current_node_->owningBlock() == last_inserted_op_->owningBlock()) {
|
| 287 |
+
TORCH_INTERNAL_ASSERT(
|
| 288 |
+
current_node_->isAfter(last_inserted_op_),
|
| 289 |
+
*current_node_,
|
| 290 |
+
" is not after ",
|
| 291 |
+
*last_inserted_op_);
|
| 292 |
+
}
|
| 293 |
+
last_inserted_op_ = current_node_;
|
| 294 |
+
}
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
void truncateInstructions(size_t size) {
|
| 298 |
+
while (instructions_.size() > size) {
|
| 299 |
+
instructions_.pop_back();
|
| 300 |
+
instructions_source_.pop_back();
|
| 301 |
+
}
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
void createBailoutBlock(size_t jf_index) {
|
| 305 |
+
bailout_blocks_.emplace_back(jf_index);
|
| 306 |
+
auto& bailout_instructions = bailout_blocks_.back().instructions;
|
| 307 |
+
|
| 308 |
+
bailout_instructions.insert(
|
| 309 |
+
bailout_instructions.end(),
|
| 310 |
+
instructions_.begin() + jf_index + 1,
|
| 311 |
+
instructions_.end());
|
| 312 |
+
truncateInstructions(jf_index + 1);
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
int allocRegs(at::ArrayRef<Value*> vs) {
|
| 316 |
+
int result = register_size_ + 1;
|
| 317 |
+
for (Value* v : vs) {
|
| 318 |
+
AT_ASSERT(value_to_reg_.count(v) == 0);
|
| 319 |
+
value_to_reg_[v] = ++register_size_;
|
| 320 |
+
}
|
| 321 |
+
return result;
|
| 322 |
+
}
|
| 323 |
+
|
| 324 |
+
int registerFor(Value* v) {
|
| 325 |
+
return value_to_reg_.at(v);
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
void emitUse(Value* input, bool drop) {
|
| 329 |
+
// drop - if true, we are not actually going to use this thing
|
| 330 |
+
// and we can short circuit doing many instructions here
|
| 331 |
+
// by either clearing the register (DROPR) or just popping the stack
|
| 332 |
+
// (DROP)
|
| 333 |
+
if (preprocess_.can_emit_inline[input->node()]) {
|
| 334 |
+
emitNode(input->node());
|
| 335 |
+
if (drop) {
|
| 336 |
+
insertInstruction(DROP);
|
| 337 |
+
}
|
| 338 |
+
} else {
|
| 339 |
+
int reg = registerFor(input);
|
| 340 |
+
bool moved = input->uses().size() == ++use_count_[input];
|
| 341 |
+
|
| 342 |
+
OpCode op{};
|
| 343 |
+
if (input->node()->kind() == prim::Constant) {
|
| 344 |
+
op = LOADC;
|
| 345 |
+
} else if (moved) {
|
| 346 |
+
op = MOVE;
|
| 347 |
+
} else {
|
| 348 |
+
op = LOAD;
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
if (drop) {
|
| 352 |
+
op = DROPR;
|
| 353 |
+
}
|
| 354 |
+
insertInstruction(op, reg);
|
| 355 |
+
}
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
void emitLoadInputs(at::ArrayRef<Value*> inputs) {
|
| 359 |
+
for (Value* input : inputs) {
|
| 360 |
+
emitUse(input, false);
|
| 361 |
+
}
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
void emitLoadInputs(at::ArrayRef<Value*> inputs, int num_include) {
|
| 365 |
+
int count = 0;
|
| 366 |
+
for (Value* input : inputs) {
|
| 367 |
+
if (count < num_include) {
|
| 368 |
+
emitUse(input, false);
|
| 369 |
+
count++;
|
| 370 |
+
}
|
| 371 |
+
}
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
void emitLoadInputs(at::ArrayRef<Value*> inputs, size_t start, size_t end) {
|
| 375 |
+
for (size_t i = start; i < end; i++) {
|
| 376 |
+
emitUse(inputs[i], false);
|
| 377 |
+
}
|
| 378 |
+
}
|
| 379 |
+
|
| 380 |
+
virtual void emitOperator(Node* node) {
|
| 381 |
+
emitLoadInputs(node->inputs());
|
| 382 |
+
const Operator& op = node->getOperator();
|
| 383 |
+
int num_inputs = node->inputs().size();
|
| 384 |
+
bool is_vararg = op.schema().is_vararg();
|
| 385 |
+
|
| 386 |
+
int operation_index = add_to_operator_table(
|
| 387 |
+
op,
|
| 388 |
+
node,
|
| 389 |
+
c10::toString(op.schema().operator_name()),
|
| 390 |
+
num_inputs,
|
| 391 |
+
is_vararg);
|
| 392 |
+
|
| 393 |
+
if (op.hasOperation() && is_vararg) {
|
| 394 |
+
insertInstruction(OPN, operation_index, num_inputs);
|
| 395 |
+
} else {
|
| 396 |
+
insertInstruction(OP, operation_index);
|
| 397 |
+
}
|
| 398 |
+
}
|
| 399 |
+
|
| 400 |
+
void emitWait(Node* node) {
|
| 401 |
+
emitLoadInputs(node->inputs());
|
| 402 |
+
insertInstruction(WAIT);
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
void emitDrop(at::ArrayRef<Value*> to_drop) {
|
| 406 |
+
for (Value* input : to_drop) {
|
| 407 |
+
emitUse(input, true);
|
| 408 |
+
}
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
void emitStoreOutputs(Node* node) {
|
| 412 |
+
size_t N = node->outputs().size();
|
| 413 |
+
if (N == 0) {
|
| 414 |
+
return;
|
| 415 |
+
}
|
| 416 |
+
int regs = allocRegs(node->outputs());
|
| 417 |
+
if (N == 1) {
|
| 418 |
+
insertInstruction(STORE, regs);
|
| 419 |
+
} else {
|
| 420 |
+
insertInstruction(STOREN, regs, node->outputs().size());
|
| 421 |
+
}
|
| 422 |
+
}
|
| 423 |
+
|
| 424 |
+
int insertConstant(IValue value) {
|
| 425 |
+
int result = constant_table_.size();
|
| 426 |
+
constant_table_.emplace_back(std::move(value));
|
| 427 |
+
return result;
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
virtual void emitOperatorOrInstruction(
|
| 431 |
+
Node* node,
|
| 432 |
+
OpCode op,
|
| 433 |
+
int64_t X = 0,
|
| 434 |
+
uint64_t N = 0,
|
| 435 |
+
bool emit_inputs = true) {
|
| 436 |
+
if (emit_inputs) {
|
| 437 |
+
emitLoadInputs(node->inputs());
|
| 438 |
+
}
|
| 439 |
+
insertInstruction(op, X, N);
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
void emitFormat(Node* node) {
|
| 443 |
+
emitOperatorOrInstruction(node, FORMAT, node->inputs().size(), 0);
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
void checkNodeAndEmit(Node* node) {
|
| 447 |
+
// check if the node should be emitted as instruction or operator
|
| 448 |
+
const Operator& op = node->getOperator();
|
| 449 |
+
std::string unique_op_name = c10::toString(op.schema().operator_name());
|
| 450 |
+
if (unique_op_name.find("aten::__getitem__.Dict") == 0) {
|
| 451 |
+
// __get_item__ overloaded operator for Dict
|
| 452 |
+
// needs to be emitted an instruction
|
| 453 |
+
emitOperatorOrInstruction(node, DICT_INDEX);
|
| 454 |
+
} else {
|
| 455 |
+
emitOperator(node);
|
| 456 |
+
}
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
void emitConstant(Node* node) {
|
| 460 |
+
if (node->output()->type()->kind() == FunctionType::Kind) {
|
| 461 |
+
return;
|
| 462 |
+
}
|
| 463 |
+
// constants are just put in the constant table
|
| 464 |
+
value_to_reg_[node->output()] =
|
| 465 |
+
insertConstant(toIValue(node->output()).value());
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
void emitIf(Node* node) {
|
| 469 |
+
emitLoadInputs(node->inputs());
|
| 470 |
+
size_t start_if = instructions_.size();
|
| 471 |
+
insertInstruction(JF, 0); // dummy offset to be filled in
|
| 472 |
+
emitCodeForBlock(node->blocks().at(0));
|
| 473 |
+
insertInstruction(JMP, 0); // dummy offset
|
| 474 |
+
size_t start_else = instructions_.size();
|
| 475 |
+
instructions_[start_if].X = start_else - start_if;
|
| 476 |
+
emitCodeForBlock(node->blocks().at(1));
|
| 477 |
+
instructions_[start_else - 1].X = instructions_.size() - (start_else - 1);
|
| 478 |
+
}
|
| 479 |
+
|
| 480 |
+
void emitLoop(Node* loop) {
|
| 481 |
+
insertInstruction(LOADC, insertConstant(0));
|
| 482 |
+
emitLoadInputs(loop->inputs());
|
| 483 |
+
size_t start = instructions_.size();
|
| 484 |
+
insertInstruction(LOOP, 0, loop->inputs().size()); // dummy offset
|
| 485 |
+
emitCodeForBlock(loop->blocks().at(0));
|
| 486 |
+
insertInstruction(JMP, start - instructions_.size());
|
| 487 |
+
instructions_[start].X = instructions_.size() - start;
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
+
void emitCall(Function* func, at::ArrayRef<Value*> inputs) {
|
| 491 |
+
emitLoadInputs(inputs);
|
| 492 |
+
insertInstruction(CALL, function_table_.size());
|
| 493 |
+
function_table_.emplace_back(func);
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
void emitNodeAtBlockLevel(Node* node) {
|
| 497 |
+
WithCurrentNode guard(¤t_node_, node);
|
| 498 |
+
switch (node->kind()) {
|
| 499 |
+
case prim::Constant:
|
| 500 |
+
emitConstant(node);
|
| 501 |
+
break;
|
| 502 |
+
case prim::Return:
|
| 503 |
+
emitLoadInputs(node->inputs());
|
| 504 |
+
break;
|
| 505 |
+
default:
|
| 506 |
+
if (!preprocess_.can_emit_inline[node]) {
|
| 507 |
+
emitNode(node);
|
| 508 |
+
emitStoreOutputs(node);
|
| 509 |
+
}
|
| 510 |
+
break;
|
| 511 |
+
}
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
size_t emitType(TypePtr t) {
|
| 515 |
+
size_t r = type_table_.size();
|
| 516 |
+
type_table_.emplace_back(std::move(t));
|
| 517 |
+
return r;
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
void emitTypeCheck(Node* node) {
|
| 521 |
+
auto num_inputs = node->inputs().size();
|
| 522 |
+
|
| 523 |
+
// Check that TypeCheck has at least one input.
|
| 524 |
+
TORCH_INTERNAL_ASSERT(
|
| 525 |
+
num_inputs && num_inputs + 1 == node->outputs().size());
|
| 526 |
+
emitLoadInputs(node->inputs());
|
| 527 |
+
|
| 528 |
+
// Emit the expected type.
|
| 529 |
+
size_t types_start = type_table_.size();
|
| 530 |
+
auto types = node->tys(attr::types);
|
| 531 |
+
for (const auto i : c10::irange(num_inputs)) {
|
| 532 |
+
emitType(types[i]);
|
| 533 |
+
}
|
| 534 |
+
insertInstruction(TYPECHECK, types_start, num_inputs);
|
| 535 |
+
}
|
| 536 |
+
|
| 537 |
+
size_t emitGuard(Node* node) {
|
| 538 |
+
// unoptimized graph is at index 0
|
| 539 |
+
// guarded input is at index 1
|
| 540 |
+
// the rest of args follow
|
| 541 |
+
emitLoadInputs(node->inputs().slice(1, 1));
|
| 542 |
+
insertInstruction(GUARD, emitType(node->outputs().at(0)->type()));
|
| 543 |
+
insertInstruction(JF, 0 /* to be patched */);
|
| 544 |
+
return instructions_.size() - 1;
|
| 545 |
+
}
|
| 546 |
+
|
| 547 |
+
void emitBailOut(Node* node) {
|
| 548 |
+
auto jf_index = emitGuard(node);
|
| 549 |
+
auto unoptimized_graph = node->inputs().at(0)->node()->g(attr::Subgraph);
|
| 550 |
+
// note, guaded input is already loaded onto the stack
|
| 551 |
+
// for GUARD instruction
|
| 552 |
+
emitLoadInputs(node->inputs().slice(2));
|
| 553 |
+
insertInstruction(TAIL_CALL, function_table_.size());
|
| 554 |
+
TORCH_INTERNAL_ASSERT(node->kind() == prim::BailOut);
|
| 555 |
+
auto bailout_index = node->i(attr::index);
|
| 556 |
+
TORCH_INTERNAL_ASSERT(bailout_index >= 0);
|
| 557 |
+
|
| 558 |
+
auto build_bailout_graph = [bailout_index,
|
| 559 |
+
unoptimized_graph](GraphFunction& func) {
|
| 560 |
+
BuildBailOutGraphFrom(bailout_index, unoptimized_graph, func.graph());
|
| 561 |
+
};
|
| 562 |
+
|
| 563 |
+
auto empty_graph = std::make_shared<Graph>();
|
| 564 |
+
auto func = std::make_unique<GraphFunction>(
|
| 565 |
+
"bailout", empty_graph, build_bailout_graph);
|
| 566 |
+
function_table_.emplace_back(func.get());
|
| 567 |
+
bailout_functions_.emplace_back(std::move(func));
|
| 568 |
+
createBailoutBlock(jf_index);
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
void emitProfile(Node* node) {
|
| 572 |
+
emitLoadInputs(node->inputs());
|
| 573 |
+
insertInstruction(PROFILE_OP, profile_function_table_.size());
|
| 574 |
+
if (node->cast<ProfileOp>()) {
|
| 575 |
+
profile_function_table_.push_back(node->cast<ProfileOp>()->getCallback());
|
| 576 |
+
} else if (node->cast<ProfileIValueOp>()) {
|
| 577 |
+
profile_function_table_.push_back(
|
| 578 |
+
node->cast<ProfileIValueOp>()->getCallback());
|
| 579 |
+
} else {
|
| 580 |
+
TORCH_INTERNAL_ASSERT(false);
|
| 581 |
+
}
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
void emitGetAttr(Node* node) {
|
| 585 |
+
emitLoadInputs(node->inputs());
|
| 586 |
+
const auto type = node->input()->type()->expect<ClassType>();
|
| 587 |
+
const auto& field = node->s(attr::name);
|
| 588 |
+
const auto slot = type->getAttributeSlot(field);
|
| 589 |
+
insertInstruction(GET_ATTR, slot);
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
void emitSetAttr(Node* node) {
|
| 593 |
+
emitLoadInputs(node->inputs());
|
| 594 |
+
const auto type = node->inputs().at(0)->type()->expect<ClassType>();
|
| 595 |
+
const auto& field = node->s(attr::name);
|
| 596 |
+
const auto slot = type->getAttributeSlot(field);
|
| 597 |
+
insertInstruction(SET_ATTR, slot);
|
| 598 |
+
}
|
| 599 |
+
|
| 600 |
+
void insertBailoutBlocks() {
|
| 601 |
+
for (const BailoutBlock& block : bailout_blocks_) {
|
| 602 |
+
TORCH_INTERNAL_ASSERT(instructions_[block.jf_instruction_index].op == JF)
|
| 603 |
+
instructions_[block.jf_instruction_index].X =
|
| 604 |
+
instructions_.size() - block.jf_instruction_index;
|
| 605 |
+
instructions_.insert(
|
| 606 |
+
instructions_.end(),
|
| 607 |
+
block.instructions.begin(),
|
| 608 |
+
block.instructions.end());
|
| 609 |
+
instructions_source_.insert(
|
| 610 |
+
instructions_source_.end(),
|
| 611 |
+
block.instructions.size(),
|
| 612 |
+
instructions_source_[block.jf_instruction_index]);
|
| 613 |
+
}
|
| 614 |
+
}
|
| 615 |
+
void emitInterfaceCall(
|
| 616 |
+
std::string method_name_str,
|
| 617 |
+
c10::ArrayRef<Value*> inputs) {
|
| 618 |
+
emitLoadInputs(inputs);
|
| 619 |
+
auto method_name = insertConstant(std::move(method_name_str));
|
| 620 |
+
insertInstruction(INTERFACE_CALL, method_name, inputs.size());
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
void emitListUnpack(Node* node) {
|
| 624 |
+
emitLoadInputs(node->inputs());
|
| 625 |
+
insertInstruction(LIST_UNPACK, node->outputs().size());
|
| 626 |
+
}
|
| 627 |
+
|
| 628 |
+
void emitTupleConstruct(Node* node) {
|
| 629 |
+
bool named =
|
| 630 |
+
node->output()->type()->expectRef<TupleType>().name().has_value();
|
| 631 |
+
if (named) {
|
| 632 |
+
emitContainerConstruct(NAMED_TUPLE_CONSTRUCT, node);
|
| 633 |
+
} else {
|
| 634 |
+
emitLoadInputs(node->inputs());
|
| 635 |
+
insertInstruction(TUPLE_CONSTRUCT, node->inputs().size());
|
| 636 |
+
}
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
void emitContainerConstruct(OpCode op, Node* node) {
|
| 640 |
+
emitLoadInputs(node->inputs());
|
| 641 |
+
insertInstruction(
|
| 642 |
+
op, emitType(node->output()->type()), node->inputs().size());
|
| 643 |
+
}
|
| 644 |
+
|
| 645 |
+
void emitCreateObject(Node* node) {
|
| 646 |
+
insertInstruction(CREATE_OBJECT, emitType(node->output()->type()));
|
| 647 |
+
}
|
| 648 |
+
void emitIsinstance(Node* node) {
|
| 649 |
+
emitLoadInputs(node->inputs());
|
| 650 |
+
std::vector<TypePtr> types = node->tys(attr::types);
|
| 651 |
+
size_t types_start = type_table_.size();
|
| 652 |
+
for (const auto& typ : types) {
|
| 653 |
+
emitType(typ);
|
| 654 |
+
}
|
| 655 |
+
insertInstruction(ISINSTANCE, types_start, types.size());
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
void emitTupleSlice(Node* node) {
|
| 659 |
+
emitLoadInputs(node->inputs());
|
| 660 |
+
int64_t beg_ind = node->i(attr::beg);
|
| 661 |
+
int64_t end_ind = node->i(attr::end);
|
| 662 |
+
insertInstruction(TUPLE_SLICE, beg_ind, end_ind - beg_ind);
|
| 663 |
+
}
|
| 664 |
+
|
| 665 |
+
void emitFork(Node* node) {
|
| 666 |
+
emitLoadInputs(node->inputs());
|
| 667 |
+
auto forked_fn = std::make_unique<GraphFunction>(
|
| 668 |
+
"<forked function>", node->g(attr::Subgraph), nullptr);
|
| 669 |
+
forked_functions_.emplace_back(std::move(forked_fn));
|
| 670 |
+
function_table_.emplace_back(forked_functions_.back().get());
|
| 671 |
+
insertInstruction(FORK, function_table_.size() - 1, node->inputs().size());
|
| 672 |
+
}
|
| 673 |
+
|
| 674 |
+
void emitAwaitable(Node* node) {
|
| 675 |
+
emitLoadInputs(node->inputs());
|
| 676 |
+
auto await_fn = std::make_unique<GraphFunction>(
|
| 677 |
+
"<awaitable function>", node->g(attr::Subgraph), nullptr);
|
| 678 |
+
awaited_functions_.emplace_back(std::move(await_fn));
|
| 679 |
+
function_table_.emplace_back(awaited_functions_.back().get());
|
| 680 |
+
insertInstruction(
|
| 681 |
+
AWAITABLE, function_table_.size() - 1, node->inputs().size());
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
void emitWarn(Node* node) {
|
| 685 |
+
if (FLAGS_torch_jit_disable_warning_prints) {
|
| 686 |
+
return;
|
| 687 |
+
}
|
| 688 |
+
|
| 689 |
+
emitLoadInputs(node->inputs());
|
| 690 |
+
int32_t idx = -1;
|
| 691 |
+
if (node->hasAttribute(attr::warn_id)) {
|
| 692 |
+
idx = static_cast<int32_t>(node->i(attr::warn_id));
|
| 693 |
+
}
|
| 694 |
+
insertInstruction(WARN, idx);
|
| 695 |
+
}
|
| 696 |
+
|
| 697 |
+
void emitEnter(Node* node) {
|
| 698 |
+
emitLoadInputs(node->inputs());
|
| 699 |
+
insertInstruction(ENTER);
|
| 700 |
+
}
|
| 701 |
+
|
| 702 |
+
void emitExit(Node* /* node */) {
|
| 703 |
+
insertInstruction(EXIT);
|
| 704 |
+
}
|
| 705 |
+
|
| 706 |
+
void emitNode(Node* node) {
|
| 707 |
+
WithCurrentNode guard(¤t_node_, node);
|
| 708 |
+
switch (node->kind()) {
|
| 709 |
+
default:
|
| 710 |
+
// NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.VirtualCall)
|
| 711 |
+
checkNodeAndEmit(node);
|
| 712 |
+
// emitOperator(node);
|
| 713 |
+
break;
|
| 714 |
+
case prim::RaiseException:
|
| 715 |
+
emitOperatorOrInstruction(node, RAISE_EXCEPTION);
|
| 716 |
+
break;
|
| 717 |
+
case prim::TupleIndex:
|
| 718 |
+
emitOperatorOrInstruction(node, TUPLE_INDEX);
|
| 719 |
+
break;
|
| 720 |
+
case prim::Drop:
|
| 721 |
+
emitDrop(node->inputs());
|
| 722 |
+
break;
|
| 723 |
+
case prim::Constant:
|
| 724 |
+
emitConstant(node);
|
| 725 |
+
break;
|
| 726 |
+
case prim::If:
|
| 727 |
+
emitIf(node);
|
| 728 |
+
break;
|
| 729 |
+
case prim::Loop:
|
| 730 |
+
emitLoop(node);
|
| 731 |
+
break;
|
| 732 |
+
case aten::wait:
|
| 733 |
+
emitWait(node);
|
| 734 |
+
break;
|
| 735 |
+
case prim::Param:
|
| 736 |
+
break;
|
| 737 |
+
case prim::CallFunction:
|
| 738 |
+
emitCall(
|
| 739 |
+
node->inputs().at(0)->type()->expectRef<FunctionType>().function(),
|
| 740 |
+
node->inputs().slice(1));
|
| 741 |
+
break;
|
| 742 |
+
case prim::CallMethod:
|
| 743 |
+
if (auto class_type = node->inputs().at(0)->type()->cast<ClassType>()) {
|
| 744 |
+
emitCall(&class_type->getMethod(node->s(attr::name)), node->inputs());
|
| 745 |
+
} else {
|
| 746 |
+
emitInterfaceCall(node->s(attr::name), node->inputs());
|
| 747 |
+
}
|
| 748 |
+
break;
|
| 749 |
+
case prim::TypeCheck:
|
| 750 |
+
emitTypeCheck(node);
|
| 751 |
+
break;
|
| 752 |
+
case prim::BailOut:
|
| 753 |
+
emitBailOut(node);
|
| 754 |
+
break;
|
| 755 |
+
case prim::profile_ivalue:
|
| 756 |
+
case prim::profile:
|
| 757 |
+
emitProfile(node);
|
| 758 |
+
break;
|
| 759 |
+
case prim::GetAttr:
|
| 760 |
+
emitGetAttr(node);
|
| 761 |
+
break;
|
| 762 |
+
case prim::SetAttr:
|
| 763 |
+
emitSetAttr(node);
|
| 764 |
+
break;
|
| 765 |
+
case prim::ListUnpack:
|
| 766 |
+
emitListUnpack(node);
|
| 767 |
+
break;
|
| 768 |
+
case prim::TupleConstruct:
|
| 769 |
+
emitTupleConstruct(node);
|
| 770 |
+
break;
|
| 771 |
+
case prim::ListConstruct:
|
| 772 |
+
emitContainerConstruct(LIST_CONSTRUCT, node);
|
| 773 |
+
break;
|
| 774 |
+
case prim::DictConstruct:
|
| 775 |
+
emitContainerConstruct(DICT_CONSTRUCT, node);
|
| 776 |
+
break;
|
| 777 |
+
case prim::CreateObject:
|
| 778 |
+
emitCreateObject(node);
|
| 779 |
+
break;
|
| 780 |
+
case prim::isinstance:
|
| 781 |
+
emitIsinstance(node);
|
| 782 |
+
break;
|
| 783 |
+
case prim::TupleSlice:
|
| 784 |
+
emitTupleSlice(node);
|
| 785 |
+
break;
|
| 786 |
+
case prim::fork:
|
| 787 |
+
emitFork(node);
|
| 788 |
+
break;
|
| 789 |
+
case prim::awaitable:
|
| 790 |
+
emitAwaitable(node);
|
| 791 |
+
break;
|
| 792 |
+
case aten::warn:
|
| 793 |
+
emitWarn(node);
|
| 794 |
+
break;
|
| 795 |
+
case prim::Enter:
|
| 796 |
+
emitEnter(node);
|
| 797 |
+
break;
|
| 798 |
+
case prim::Exit:
|
| 799 |
+
emitExit(node);
|
| 800 |
+
break;
|
| 801 |
+
case prim::Uninitialized:
|
| 802 |
+
emitOperatorOrInstruction(node, UN_INITIALIZED, 0, 0, false);
|
| 803 |
+
break;
|
| 804 |
+
case prim::dtype:
|
| 805 |
+
emitOperatorOrInstruction(node, DTYPE);
|
| 806 |
+
break;
|
| 807 |
+
case prim::device:
|
| 808 |
+
emitOperatorOrInstruction(node, DEVICE);
|
| 809 |
+
break;
|
| 810 |
+
case aten::dim:
|
| 811 |
+
emitOperatorOrInstruction(node, DIM);
|
| 812 |
+
break;
|
| 813 |
+
case prim::is_cuda:
|
| 814 |
+
emitOperatorOrInstruction(node, IS_CUDA);
|
| 815 |
+
break;
|
| 816 |
+
case aten::__not__:
|
| 817 |
+
emitOperatorOrInstruction(node, __NOT__);
|
| 818 |
+
break;
|
| 819 |
+
case aten::format:
|
| 820 |
+
emitFormat(node);
|
| 821 |
+
break;
|
| 822 |
+
case aten::__is__:
|
| 823 |
+
emitOperatorOrInstruction(node, __IS__);
|
| 824 |
+
break;
|
| 825 |
+
case aten::__isnot__:
|
| 826 |
+
emitOperatorOrInstruction(node, __ISNOT__);
|
| 827 |
+
break;
|
| 828 |
+
case prim::NumToTensor:
|
| 829 |
+
emitOperatorOrInstruction(node, NUM_TO_TENSOR);
|
| 830 |
+
break;
|
| 831 |
+
case prim::tolist:
|
| 832 |
+
emitOperatorOrInstruction(node, TO_LIST);
|
| 833 |
+
break;
|
| 834 |
+
}
|
| 835 |
+
}
|
| 836 |
+
|
| 837 |
+
void emitCodeForBlock(Block* block) {
|
| 838 |
+
emitNodeAtBlockLevel(block->param_node());
|
| 839 |
+
for (auto node : block->nodes()) {
|
| 840 |
+
emitNodeAtBlockLevel(node);
|
| 841 |
+
}
|
| 842 |
+
emitNodeAtBlockLevel(block->return_node());
|
| 843 |
+
}
|
| 844 |
+
|
| 845 |
+
const std::vector<GraphExecutor*>& grad_executors() {
|
| 846 |
+
if (!grad_executors_) {
|
| 847 |
+
grad_executors_.emplace();
|
| 848 |
+
for (Operation& op : operator_table_) {
|
| 849 |
+
if (auto executor = detail::getGradExecutor(op)) {
|
| 850 |
+
grad_executors_->push_back(executor);
|
| 851 |
+
}
|
| 852 |
+
}
|
| 853 |
+
}
|
| 854 |
+
return *grad_executors_;
|
| 855 |
+
}
|
| 856 |
+
|
| 857 |
+
const std::vector<GraphExecutor*>& diff_graph_op_executors() {
|
| 858 |
+
if (!forward_executors_) {
|
| 859 |
+
forward_executors_.emplace();
|
| 860 |
+
for (Operation& op : operator_table_) {
|
| 861 |
+
if (auto executor = detail::getDifferentiableGraphOpExecutor(op)) {
|
| 862 |
+
forward_executors_->push_back(executor);
|
| 863 |
+
}
|
| 864 |
+
}
|
| 865 |
+
}
|
| 866 |
+
return *forward_executors_;
|
| 867 |
+
}
|
| 868 |
+
|
| 869 |
+
void dump(std::ostream& out, size_t i) const {
|
| 870 |
+
out << i << ' ' << instructions_[i];
|
| 871 |
+
if (instructions_[i].op == OP || instructions_[i].op == CALL ||
|
| 872 |
+
instructions_[i].op == OPN) {
|
| 873 |
+
out << " # " << *instructions_source_[i];
|
| 874 |
+
} else {
|
| 875 |
+
out << '\n';
|
| 876 |
+
}
|
| 877 |
+
}
|
| 878 |
+
|
| 879 |
+
void dump(std::ostream& out) const {
|
| 880 |
+
out << *graph_ << '\n';
|
| 881 |
+
for (const auto i : c10::irange(instructions_.size())) {
|
| 882 |
+
dump(out, i);
|
| 883 |
+
}
|
| 884 |
+
}
|
| 885 |
+
|
| 886 |
+
/**
|
| 887 |
+
* Add an operation to operator_table_ if not a duplicate and return its index
|
| 888 |
+
*/
|
| 889 |
+
int add_to_operator_table(
|
| 890 |
+
const Operator& op,
|
| 891 |
+
const Node* node,
|
| 892 |
+
const std::string& op_name,
|
| 893 |
+
const int num_inputs,
|
| 894 |
+
const bool is_vararg) {
|
| 895 |
+
int size = operator_table_.size();
|
| 896 |
+
|
| 897 |
+
const Operation& oper = op.getOperation(node);
|
| 898 |
+
|
| 899 |
+
if (!is_vararg) {
|
| 900 |
+
std::pair<std::string, int> key(op_name, num_inputs);
|
| 901 |
+
auto found = operator_table_inv_.find(key);
|
| 902 |
+
|
| 903 |
+
if (found != operator_table_inv_.end()) {
|
| 904 |
+
return found->second;
|
| 905 |
+
}
|
| 906 |
+
|
| 907 |
+
operator_table_inv_.emplace(key, size);
|
| 908 |
+
}
|
| 909 |
+
|
| 910 |
+
operator_table_.emplace_back(oper);
|
| 911 |
+
#ifndef NDEBUG
|
| 912 |
+
full_operator_table_.emplace_back(op);
|
| 913 |
+
#endif
|
| 914 |
+
return size;
|
| 915 |
+
}
|
| 916 |
+
|
| 917 |
+
inline void assert_stack_size(
|
| 918 |
+
int32_t instruction_index,
|
| 919 |
+
size_t init_size,
|
| 920 |
+
size_t actual_size) const {
|
| 921 |
+
#ifndef NDEBUG
|
| 922 |
+
const auto& schema = full_operator_table_[instruction_index].schema();
|
| 923 |
+
int64_t expected_size = static_cast<int64_t>(init_size) -
|
| 924 |
+
static_cast<int64_t>(schema.arguments().size()) +
|
| 925 |
+
static_cast<int64_t>(schema.returns().size());
|
| 926 |
+
TORCH_INTERNAL_ASSERT_DEBUG_ONLY(
|
| 927 |
+
static_cast<size_t>(expected_size) == actual_size ||
|
| 928 |
+
schema.is_varret() || schema.is_vararg(),
|
| 929 |
+
"Expected to find ",
|
| 930 |
+
expected_size,
|
| 931 |
+
" values on the stack, but found ",
|
| 932 |
+
actual_size,
|
| 933 |
+
" on the stack after ",
|
| 934 |
+
toString(full_operator_table_[instruction_index].schema()));
|
| 935 |
+
#endif
|
| 936 |
+
}
|
| 937 |
+
};
|
| 938 |
+
|
| 939 |
+
struct MobileCodeImpl : CodeImpl {
|
| 940 |
+
MobileCodeImpl(
|
| 941 |
+
const std::shared_ptr<Graph>& graph,
|
| 942 |
+
std::string function_name,
|
| 943 |
+
bool emit_default_input_instructions,
|
| 944 |
+
bool support_default_args_before_out,
|
| 945 |
+
bool emit_promoted_ops,
|
| 946 |
+
size_t remaining_bailout_depth)
|
| 947 |
+
: CodeImpl(
|
| 948 |
+
graph,
|
| 949 |
+
std::move(function_name),
|
| 950 |
+
remaining_bailout_depth,
|
| 951 |
+
false),
|
| 952 |
+
emit_default_input_instructions_(emit_default_input_instructions),
|
| 953 |
+
support_default_args_before_out_(support_default_args_before_out),
|
| 954 |
+
emit_promoted_ops_(emit_promoted_ops) {
|
| 955 |
+
// NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.VirtualCall)
|
| 956 |
+
run();
|
| 957 |
+
}
|
| 958 |
+
|
| 959 |
+
void run() override {
|
| 960 |
+
process_ops_for_mobile();
|
| 961 |
+
emitCodeForBlock(graph_->block());
|
| 962 |
+
insertInstruction(RET);
|
| 963 |
+
// we deferred the emission of bailout blocks so they appear at the end
|
| 964 |
+
// emit them now and patch up the jumps
|
| 965 |
+
insertBailoutBlocks();
|
| 966 |
+
}
|
| 967 |
+
|
| 968 |
+
void process_ops_for_mobile() {
|
| 969 |
+
DepthFirstGraphNodeIterator graph_it(graph_);
|
| 970 |
+
Node* node = graph_it.next();
|
| 971 |
+
while (node) {
|
| 972 |
+
if (node->maybeOperator()) {
|
| 973 |
+
auto op_schema = node->getOperator().schema();
|
| 974 |
+
// skip if schema has vararg
|
| 975 |
+
if (!op_schema.is_vararg()) {
|
| 976 |
+
auto specifiedArgs = CalculateNecessaryArgs(
|
| 977 |
+
op_schema.arguments(),
|
| 978 |
+
node->inputs(),
|
| 979 |
+
support_default_args_before_out_);
|
| 980 |
+
|
| 981 |
+
size_t numInclude = specifiedArgs.first +
|
| 982 |
+
(support_default_args_before_out_ ? specifiedArgs.second : 0);
|
| 983 |
+
auto unique_name = !op_schema.overload_name().empty()
|
| 984 |
+
? op_schema.name() + "." + op_schema.overload_name()
|
| 985 |
+
: op_schema.name();
|
| 986 |
+
auto it = op_to_num_specified_args_.insert(
|
| 987 |
+
std::pair<std::string, size_t>(unique_name, 0));
|
| 988 |
+
op_to_num_out_args_.insert(std::pair<std::string, size_t>(
|
| 989 |
+
unique_name, specifiedArgs.second));
|
| 990 |
+
auto prev_value = it.first->second;
|
| 991 |
+
it.first->second = std::max(numInclude, prev_value);
|
| 992 |
+
}
|
| 993 |
+
}
|
| 994 |
+
node = graph_it.next();
|
| 995 |
+
}
|
| 996 |
+
}
|
| 997 |
+
|
| 998 |
+
private:
|
| 999 |
+
void emitOperator(Node* node) override {
|
| 1000 |
+
if (emit_default_input_instructions_) {
|
| 1001 |
+
CodeImpl::emitOperator(node);
|
| 1002 |
+
} else {
|
| 1003 |
+
const Operator& op = node->getOperator();
|
| 1004 |
+
std::string unique_op_name = c10::toString(op.schema().operator_name());
|
| 1005 |
+
int num_inputs = node->inputs().size();
|
| 1006 |
+
bool is_vararg = op.schema().is_vararg();
|
| 1007 |
+
|
| 1008 |
+
if (op.hasOperation() && is_vararg) {
|
| 1009 |
+
emitLoadInputs(node->inputs());
|
| 1010 |
+
int operation_index = add_to_operator_table(
|
| 1011 |
+
op,
|
| 1012 |
+
node,
|
| 1013 |
+
unique_op_name,
|
| 1014 |
+
num_inputs,
|
| 1015 |
+
/* is_vararg */ true);
|
| 1016 |
+
insertInstruction(OPN, operation_index, num_inputs);
|
| 1017 |
+
} else {
|
| 1018 |
+
auto num_include = num_inputs;
|
| 1019 |
+
auto it = op_to_num_specified_args_.find(unique_op_name);
|
| 1020 |
+
if (it != op_to_num_specified_args_.end()) {
|
| 1021 |
+
num_include = it->second;
|
| 1022 |
+
}
|
| 1023 |
+
if (support_default_args_before_out_) {
|
| 1024 |
+
auto num_out = op_to_num_out_args_.find(unique_op_name)->second;
|
| 1025 |
+
auto num_specified_before_out = num_include - num_out;
|
| 1026 |
+
emitLoadInputs(node->inputs(), 0, num_specified_before_out);
|
| 1027 |
+
emitLoadInputs(
|
| 1028 |
+
node->inputs(),
|
| 1029 |
+
node->inputs().size() - num_out,
|
| 1030 |
+
node->inputs().size());
|
| 1031 |
+
} else {
|
| 1032 |
+
emitLoadInputs(node->inputs(), num_include);
|
| 1033 |
+
}
|
| 1034 |
+
int operation_index = add_to_operator_table(
|
| 1035 |
+
op, node, unique_op_name, num_inputs, is_vararg);
|
| 1036 |
+
insertInstruction(OP, operation_index);
|
| 1037 |
+
}
|
| 1038 |
+
}
|
| 1039 |
+
}
|
| 1040 |
+
|
| 1041 |
+
void emitOperatorOrInstruction(
|
| 1042 |
+
Node* node,
|
| 1043 |
+
OpCode op,
|
| 1044 |
+
int64_t X = 0,
|
| 1045 |
+
uint64_t N = 0,
|
| 1046 |
+
bool emit_inputs = true) override {
|
| 1047 |
+
if (emit_promoted_ops_) {
|
| 1048 |
+
CodeImpl::emitOperatorOrInstruction(node, op, X, N, emit_inputs);
|
| 1049 |
+
} else {
|
| 1050 |
+
CodeImpl::emitOperator(node);
|
| 1051 |
+
}
|
| 1052 |
+
}
|
| 1053 |
+
|
| 1054 |
+
// To support forward compatibility for bytecode version bump from v5 to v6
|
| 1055 |
+
bool emit_default_input_instructions_;
|
| 1056 |
+
// To support forward compatibility for bytecode version bump from v6 to v7
|
| 1057 |
+
bool support_default_args_before_out_;
|
| 1058 |
+
// To support forward compatibility for bytecode version bump from v7 to v8
|
| 1059 |
+
bool emit_promoted_ops_;
|
| 1060 |
+
};
|
| 1061 |
+
|
| 1062 |
+
} // namespace torch::jit::interpreter
|
| 1063 |
+
|
| 1064 |
+
#else
|
| 1065 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 1066 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/frame.h
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <atomic>
|
| 5 |
+
#include <memory>
|
| 6 |
+
|
| 7 |
+
#include <torch/csrc/jit/runtime/interpreter/code_impl.h>
|
| 8 |
+
#include <torch/csrc/jit/runtime/profiling_record.h>
|
| 9 |
+
|
| 10 |
+
namespace torch::jit::interpreter {
|
| 11 |
+
|
| 12 |
+
// A Frame captures function's state
|
| 13 |
+
// (e.g. `pc` and `base_pointer`)
|
| 14 |
+
// Each Frame corresponds to a call to a `Frame::function`
|
| 15 |
+
// which has not yet returned
|
| 16 |
+
// The arguments for `Frame::function`
|
| 17 |
+
// are located at [base_pointer + arg_number]
|
| 18 |
+
struct Frame {
|
| 19 |
+
std::shared_ptr<CodeImpl> function;
|
| 20 |
+
// program counter corresponds to the index
|
| 21 |
+
// of the currently executed instruction
|
| 22 |
+
size_t pc;
|
| 23 |
+
// marks the start index of the frame
|
| 24 |
+
// base_pointer is used by TAIL_CALL
|
| 25 |
+
// to replace the current frame
|
| 26 |
+
// with a frame of a bailout graph
|
| 27 |
+
size_t base_pointer;
|
| 28 |
+
|
| 29 |
+
// unique to every frame with prim::profile across all threads
|
| 30 |
+
std::optional<size_t> id;
|
| 31 |
+
|
| 32 |
+
// RecordFunction object associated with this frame
|
| 33 |
+
std::unique_ptr<at::RecordFunction> record_function;
|
| 34 |
+
|
| 35 |
+
// symbol table for a frame
|
| 36 |
+
ShapeSymbolTable symbols2dims;
|
| 37 |
+
|
| 38 |
+
static size_t genId();
|
| 39 |
+
};
|
| 40 |
+
|
| 41 |
+
} // namespace torch::jit::interpreter
|
| 42 |
+
|
| 43 |
+
#else
|
| 44 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 45 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/interpreter/preprocess_graph.h
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <memory>
|
| 5 |
+
#include <unordered_map>
|
| 6 |
+
|
| 7 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 8 |
+
|
| 9 |
+
namespace torch::jit::interpreter {
|
| 10 |
+
|
| 11 |
+
// pre-processing that happens once per graph
|
| 12 |
+
struct PreprocessGraph {
|
| 13 |
+
explicit PreprocessGraph(Graph& g);
|
| 14 |
+
|
| 15 |
+
// Outputs of the preprocessing:
|
| 16 |
+
std::shared_ptr<Graph> graph;
|
| 17 |
+
std::unordered_map<Node*, bool> can_emit_inline;
|
| 18 |
+
};
|
| 19 |
+
|
| 20 |
+
} // namespace torch::jit::interpreter
|
| 21 |
+
|
| 22 |
+
#else
|
| 23 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 24 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/jit_exception.h
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <stdexcept>
|
| 5 |
+
|
| 6 |
+
#include <torch/csrc/Export.h>
|
| 7 |
+
#include <optional>
|
| 8 |
+
#include <string>
|
| 9 |
+
|
| 10 |
+
namespace torch::jit {
|
| 11 |
+
|
| 12 |
+
struct TORCH_API JITException : public std::runtime_error {
|
| 13 |
+
explicit JITException(
|
| 14 |
+
const std::string& msg,
|
| 15 |
+
std::optional<std::string> python_class_name = std::nullopt,
|
| 16 |
+
std::optional<std::string> original_msg = std::nullopt);
|
| 17 |
+
|
| 18 |
+
std::optional<std::string> getPythonClassName() const {
|
| 19 |
+
return python_class_name_;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
// the original msg if this is from a python exception. The interpreter has
|
| 23 |
+
// changed the original message by adding "The following operation failed in
|
| 24 |
+
// the TorchScript interpreter." in front of it in the handleError function.
|
| 25 |
+
std::optional<std::string> getOriginalMsg() const {
|
| 26 |
+
return original_msg_;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
static const std::string& getCaughtOriginalMsg();
|
| 30 |
+
static const std::string& getCaughtPythonClassName();
|
| 31 |
+
static void setCaughtOriginalMsg(const std::string& msg);
|
| 32 |
+
static void setCaughtPythonClassName(const std::string& pythonClassName);
|
| 33 |
+
|
| 34 |
+
private:
|
| 35 |
+
std::optional<std::string> python_class_name_;
|
| 36 |
+
std::optional<std::string> original_msg_;
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
+
} // namespace torch::jit
|
| 40 |
+
|
| 41 |
+
#else
|
| 42 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 43 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/jit_trace.h
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 3 |
+
#include <memory>
|
| 4 |
+
|
| 5 |
+
namespace torch::jit {
|
| 6 |
+
TORCH_API std::shared_ptr<Graph> TraceGraph(
|
| 7 |
+
const std::shared_ptr<Graph>& graph,
|
| 8 |
+
Stack& stack);
|
| 9 |
+
} // namespace torch::jit
|
| 10 |
+
|
| 11 |
+
#else
|
| 12 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 13 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/logging.h
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <chrono>
|
| 5 |
+
#include <mutex>
|
| 6 |
+
#include <string>
|
| 7 |
+
#include <unordered_map>
|
| 8 |
+
#include <vector>
|
| 9 |
+
|
| 10 |
+
#include <torch/csrc/Export.h>
|
| 11 |
+
|
| 12 |
+
namespace torch::jit::logging {
|
| 13 |
+
|
| 14 |
+
class LoggerBase {
|
| 15 |
+
public:
|
| 16 |
+
TORCH_API virtual void addStatValue(
|
| 17 |
+
const std::string& stat_name,
|
| 18 |
+
int64_t val) = 0;
|
| 19 |
+
virtual ~LoggerBase() = default;
|
| 20 |
+
};
|
| 21 |
+
|
| 22 |
+
TORCH_API LoggerBase* getLogger();
|
| 23 |
+
TORCH_API LoggerBase* setLogger(LoggerBase* logger);
|
| 24 |
+
|
| 25 |
+
// No-op logger. This is the default and is meant to incur almost no runtime
|
| 26 |
+
// overhead.
|
| 27 |
+
|
| 28 |
+
class NoopLogger : public LoggerBase {
|
| 29 |
+
public:
|
| 30 |
+
void addStatValue(
|
| 31 |
+
const std::string& stat_name [[maybe_unused]],
|
| 32 |
+
int64_t val [[maybe_unused]]) override {}
|
| 33 |
+
~NoopLogger() override = default;
|
| 34 |
+
};
|
| 35 |
+
|
| 36 |
+
// Trivial locking logger. Pass in an instance of this to setLogger() to use it.
|
| 37 |
+
// This keeps track of the sum of all statistics.
|
| 38 |
+
//
|
| 39 |
+
// NOTE: this is not written in a scalable way and should probably only be used
|
| 40 |
+
// in the single-threaded case or for testing.
|
| 41 |
+
class TORCH_API LockingLogger : public LoggerBase {
|
| 42 |
+
public:
|
| 43 |
+
void addStatValue(const std::string& stat_name, int64_t val) override;
|
| 44 |
+
virtual int64_t getCounterValue(const std::string& name) const;
|
| 45 |
+
enum class AggregationType { SUM = 0, AVG = 1 };
|
| 46 |
+
void setAggregationType(const std::string& stat_name, AggregationType type);
|
| 47 |
+
~LockingLogger() override = default;
|
| 48 |
+
|
| 49 |
+
private:
|
| 50 |
+
mutable std::mutex m;
|
| 51 |
+
struct RawCounter {
|
| 52 |
+
RawCounter() = default;
|
| 53 |
+
int64_t sum{0};
|
| 54 |
+
size_t count{0};
|
| 55 |
+
};
|
| 56 |
+
std::unordered_map<std::string, RawCounter> raw_counters;
|
| 57 |
+
std::unordered_map<std::string, AggregationType> agg_types;
|
| 58 |
+
};
|
| 59 |
+
|
| 60 |
+
// Make this struct so the timer internals are opaque to the user.
|
| 61 |
+
struct JITTimePoint {
|
| 62 |
+
std::chrono::time_point<std::chrono::high_resolution_clock> point;
|
| 63 |
+
};
|
| 64 |
+
|
| 65 |
+
TORCH_API JITTimePoint timePoint();
|
| 66 |
+
TORCH_API void recordDurationSince(
|
| 67 |
+
const std::string& name,
|
| 68 |
+
const JITTimePoint& tp);
|
| 69 |
+
|
| 70 |
+
namespace runtime_counters {
|
| 71 |
+
constexpr const char* GRAPH_EXECUTORS_CONSTRUCTED =
|
| 72 |
+
"pytorch_runtime.graph_executors_constructed";
|
| 73 |
+
constexpr const char* GRAPH_EXECUTOR_INVOCATIONS =
|
| 74 |
+
"pytorch_runtime.graph_executor_invocations";
|
| 75 |
+
constexpr const char* EXECUTION_PLAN_CACHE_HIT =
|
| 76 |
+
"pytorch_runtime.execution_plan_cache_hit";
|
| 77 |
+
constexpr const char* EXECUTION_PLAN_CACHE_MISS =
|
| 78 |
+
"pytorch_runtime.execution_plan_cache_miss";
|
| 79 |
+
|
| 80 |
+
inline std::vector<const char*> allRuntimeCounters() {
|
| 81 |
+
return {
|
| 82 |
+
GRAPH_EXECUTORS_CONSTRUCTED,
|
| 83 |
+
GRAPH_EXECUTOR_INVOCATIONS,
|
| 84 |
+
EXECUTION_PLAN_CACHE_HIT,
|
| 85 |
+
EXECUTION_PLAN_CACHE_MISS};
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
} // namespace runtime_counters
|
| 89 |
+
|
| 90 |
+
} // namespace torch::jit::logging
|
| 91 |
+
|
| 92 |
+
#else
|
| 93 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 94 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/operator.h
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
// in memory description of all ATen Ops similar to Caffe2 schema
|
| 3 |
+
// once C10 exists this can be removed, or stubbed out, but we need
|
| 4 |
+
// it now to implement correct semantic checking for script
|
| 5 |
+
#pragma once
|
| 6 |
+
|
| 7 |
+
#include <ATen/core/dispatch/Dispatcher.h>
|
| 8 |
+
#include <ATen/core/dispatch/OperatorOptions.h>
|
| 9 |
+
#include <ATen/core/op_registration/op_allowlist.h>
|
| 10 |
+
#include <ATen/core/stack.h>
|
| 11 |
+
#include <c10/util/Exception.h>
|
| 12 |
+
#include <c10/util/overloaded.h>
|
| 13 |
+
#include <torch/csrc/jit/frontend/function_schema_parser.h>
|
| 14 |
+
#include <torch/csrc/jit/runtime/operator_options.h>
|
| 15 |
+
#include <torch/library.h>
|
| 16 |
+
|
| 17 |
+
#include <ATen/core/function_schema.h>
|
| 18 |
+
#include <ATen/core/symbol.h>
|
| 19 |
+
|
| 20 |
+
#include <functional>
|
| 21 |
+
#include <initializer_list>
|
| 22 |
+
#include <memory>
|
| 23 |
+
#include <string>
|
| 24 |
+
#include <unordered_map>
|
| 25 |
+
#include <utility>
|
| 26 |
+
#include <variant>
|
| 27 |
+
#include <vector>
|
| 28 |
+
|
| 29 |
+
namespace torch::jit {
|
| 30 |
+
|
| 31 |
+
struct Node;
|
| 32 |
+
using ::c10::Argument;
|
| 33 |
+
using ::c10::FunctionSchema;
|
| 34 |
+
using ::c10::Symbol;
|
| 35 |
+
|
| 36 |
+
using OperationCreator = Operation (*)(const Node*);
|
| 37 |
+
|
| 38 |
+
namespace {
|
| 39 |
+
const std::array<at::Tag, 1> kJitOnlyOperatorTags = {
|
| 40 |
+
at::Tag::pt2_compliant_tag};
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
/*
|
| 44 |
+
* Note: JIT relies on Operator instances having static lifetime, because
|
| 45 |
+
* it for example stores a non-owning FunctionSchema* pointer in the Node class,
|
| 46 |
+
* which points to the function schema stored in the Operator instance.
|
| 47 |
+
* Also, jit::Operator is meant to store more operator related information like
|
| 48 |
+
* symbolic derivatives, which also requires them to have static lifetime
|
| 49 |
+
* so that changes to symbolic derivatives are remembered.
|
| 50 |
+
*
|
| 51 |
+
* Currently, the JIT operator library contains a jit::Operator instance
|
| 52 |
+
* with a wrapper for each c10 operator. The c10 operator library registers
|
| 53 |
+
* those wrappers using listeners in register_c10_ops.cpp.
|
| 54 |
+
* TODO Instead of doing it this way, we should only have pure-jit ops in
|
| 55 |
+
* the jit library but have the JIT operator lookup look into the c10 library
|
| 56 |
+
* too.
|
| 57 |
+
*/
|
| 58 |
+
|
| 59 |
+
// An Operator is a thin wrapper around either a pure JIT operator (e.g. prim
|
| 60 |
+
// ops) or a c10 operator, allowing some common operations and abstracting away
|
| 61 |
+
// the concrete operator nature.
|
| 62 |
+
struct TORCH_API Operator {
|
| 63 |
+
private:
|
| 64 |
+
struct C10Operator final {
|
| 65 |
+
c10::OperatorHandle handle_;
|
| 66 |
+
Operation op_;
|
| 67 |
+
};
|
| 68 |
+
struct UnparsedFunctionSchema final {
|
| 69 |
+
std::string schema_string_;
|
| 70 |
+
mutable std::optional<c10::AliasAnalysisKind> alias_analysis_;
|
| 71 |
+
};
|
| 72 |
+
struct JitOnlyOperator final {
|
| 73 |
+
// The only valid transition for schema_ is from right->left, i.e.
|
| 74 |
+
// when the schema gets parsed.
|
| 75 |
+
mutable std::variant<FunctionSchema, UnparsedFunctionSchema> schema_;
|
| 76 |
+
|
| 77 |
+
std::variant<Operation, OperationCreator> op_;
|
| 78 |
+
};
|
| 79 |
+
|
| 80 |
+
public:
|
| 81 |
+
Operator(c10::OperatorHandle opHandle, Operation operation)
|
| 82 |
+
: op_(C10Operator{std::move(opHandle), std::move(operation)}) {}
|
| 83 |
+
|
| 84 |
+
Operator(
|
| 85 |
+
std::string schema,
|
| 86 |
+
Operation op,
|
| 87 |
+
c10::AliasAnalysisKind alias_analysis)
|
| 88 |
+
: op_(JitOnlyOperator{
|
| 89 |
+
UnparsedFunctionSchema{std::move(schema), alias_analysis},
|
| 90 |
+
Operation(std::move(op))}) {}
|
| 91 |
+
|
| 92 |
+
Operator(
|
| 93 |
+
std::string name,
|
| 94 |
+
std::string overload_name,
|
| 95 |
+
std::vector<Argument> arguments,
|
| 96 |
+
std::vector<Argument> returns,
|
| 97 |
+
Operation op,
|
| 98 |
+
c10::AliasAnalysisKind alias_analysis)
|
| 99 |
+
: op_(JitOnlyOperator{
|
| 100 |
+
FunctionSchema(varArgSchemaWithName(
|
| 101 |
+
std::move(name),
|
| 102 |
+
std::move(overload_name),
|
| 103 |
+
std::move(arguments),
|
| 104 |
+
std::move(returns),
|
| 105 |
+
alias_analysis)),
|
| 106 |
+
std::move(op)}) {}
|
| 107 |
+
|
| 108 |
+
Operator(
|
| 109 |
+
std::string schema,
|
| 110 |
+
OperationCreator op_creator,
|
| 111 |
+
c10::AliasAnalysisKind alias_analysis)
|
| 112 |
+
: op_(JitOnlyOperator{
|
| 113 |
+
UnparsedFunctionSchema{std::move(schema), alias_analysis},
|
| 114 |
+
op_creator}) {}
|
| 115 |
+
|
| 116 |
+
// Helper constructor to register `op` to run
|
| 117 |
+
// run for _every_ IR Node where n.kind() == name, regardless of arguments.
|
| 118 |
+
// This is accomplished by marking the schema varargs and having no required
|
| 119 |
+
// arguments.
|
| 120 |
+
Operator(
|
| 121 |
+
Symbol name,
|
| 122 |
+
OperationCreator op_creator,
|
| 123 |
+
c10::AliasAnalysisKind alias_analysis)
|
| 124 |
+
: op_(JitOnlyOperator{
|
| 125 |
+
FunctionSchema(varArgSchemaWithName(name, alias_analysis)),
|
| 126 |
+
op_creator}) {}
|
| 127 |
+
|
| 128 |
+
Operation getOperation(const Node* node = nullptr) const {
|
| 129 |
+
return std::visit(
|
| 130 |
+
c10::overloaded(
|
| 131 |
+
[](const C10Operator& op) { return op.op_; },
|
| 132 |
+
[node](const JitOnlyOperator& op) {
|
| 133 |
+
return std::visit(
|
| 134 |
+
c10::overloaded(
|
| 135 |
+
[](const Operation& op) { return op; },
|
| 136 |
+
[node](const OperationCreator& op_creator) {
|
| 137 |
+
return op_creator(node);
|
| 138 |
+
}),
|
| 139 |
+
op.op_);
|
| 140 |
+
}),
|
| 141 |
+
op_);
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
Operation getOperationForDispatchKey(c10::DispatchKey dk) const {
|
| 145 |
+
// TODO: some sort of caching mechanism?
|
| 146 |
+
return std::visit(
|
| 147 |
+
c10::overloaded(
|
| 148 |
+
[dk](const C10Operator& op) {
|
| 149 |
+
return Operation([op, dk](Stack& stack) {
|
| 150 |
+
op.handle_.callBoxedForDispatchKey(dk, stack);
|
| 151 |
+
});
|
| 152 |
+
},
|
| 153 |
+
[](const JitOnlyOperator& op) {
|
| 154 |
+
TORCH_CHECK(
|
| 155 |
+
false,
|
| 156 |
+
"calling a JIT operator for dispatch key is not supported");
|
| 157 |
+
return Operation(nullptr);
|
| 158 |
+
}),
|
| 159 |
+
op_);
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
const FunctionSchema& schema() const {
|
| 163 |
+
return std::visit(
|
| 164 |
+
c10::overloaded(
|
| 165 |
+
[](const C10Operator& op) -> const FunctionSchema& {
|
| 166 |
+
return op.handle_.schema();
|
| 167 |
+
},
|
| 168 |
+
[](const JitOnlyOperator& op) -> const FunctionSchema& {
|
| 169 |
+
// we lazily parse schema initialized from strings so that
|
| 170 |
+
// we do less work during static operator registration
|
| 171 |
+
if (op.schema_.index() == 1) {
|
| 172 |
+
auto& unmaterializedSchema =
|
| 173 |
+
std::get<UnparsedFunctionSchema>(op.schema_);
|
| 174 |
+
FunctionSchema schema =
|
| 175 |
+
parseSchema(unmaterializedSchema.schema_string_);
|
| 176 |
+
if (unmaterializedSchema.alias_analysis_.has_value()) {
|
| 177 |
+
// TODO What if it gets set later?
|
| 178 |
+
schema.setAliasAnalysis(
|
| 179 |
+
*unmaterializedSchema.alias_analysis_);
|
| 180 |
+
}
|
| 181 |
+
op.schema_ = std::move(schema);
|
| 182 |
+
}
|
| 183 |
+
return std::get<FunctionSchema>(op.schema_);
|
| 184 |
+
}),
|
| 185 |
+
op_);
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
c10::ArrayRef<at::Tag> getTags() const {
|
| 189 |
+
return std::visit(
|
| 190 |
+
c10::overloaded(
|
| 191 |
+
[](const C10Operator& op) { return op.handle_.getTags(); },
|
| 192 |
+
[](const JitOnlyOperator& op) {
|
| 193 |
+
// JitOnlyOperators don't have an c10::OperatorHandle or a way to
|
| 194 |
+
// specify tags. We're grandfathering them all into
|
| 195 |
+
// pt2_compliant_tag, but for anything else, please just stop
|
| 196 |
+
// using JitOnlyOperator.
|
| 197 |
+
return c10::ArrayRef<at::Tag>(kJitOnlyOperatorTags);
|
| 198 |
+
}),
|
| 199 |
+
op_);
|
| 200 |
+
}
|
| 201 |
+
|
| 202 |
+
bool isC10Op() const {
|
| 203 |
+
return op_.index() == 0;
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
c10::AliasAnalysisKind aliasAnalysisKind() const {
|
| 207 |
+
const FunctionSchema& schemaRef = schema();
|
| 208 |
+
c10::AliasAnalysisKind alias_analysis = schemaRef.aliasAnalysis();
|
| 209 |
+
|
| 210 |
+
TORCH_CHECK(
|
| 211 |
+
alias_analysis == AliasAnalysisKind::FROM_SCHEMA ||
|
| 212 |
+
!schemaRef.hasAnyAliasInfo(),
|
| 213 |
+
"In operator registration: Tried to register operator ",
|
| 214 |
+
schemaRef,
|
| 215 |
+
" with aliasing information in the schema but without AliasAnalysisKind::FROM_SCHEMA.");
|
| 216 |
+
return alias_analysis;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
bool hasOperation() const {
|
| 220 |
+
return std::visit(
|
| 221 |
+
c10::overloaded(
|
| 222 |
+
[](const C10Operator&) { return true; },
|
| 223 |
+
[](const JitOnlyOperator& op) { return op.op_.index() == 0; }),
|
| 224 |
+
op_);
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
private:
|
| 228 |
+
static FunctionSchema varArgSchemaWithName(
|
| 229 |
+
Symbol name,
|
| 230 |
+
AliasAnalysisKind alias_analysis) {
|
| 231 |
+
auto result = FunctionSchema(
|
| 232 |
+
name,
|
| 233 |
+
"",
|
| 234 |
+
{},
|
| 235 |
+
{},
|
| 236 |
+
/*is_vararg*/ true,
|
| 237 |
+
/*is_varret*/ true);
|
| 238 |
+
result.setAliasAnalysis(alias_analysis);
|
| 239 |
+
return result;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
static FunctionSchema varArgSchemaWithName(
|
| 243 |
+
std::string name,
|
| 244 |
+
std::string overload_name,
|
| 245 |
+
std::vector<Argument> arguments,
|
| 246 |
+
std::vector<Argument> returns,
|
| 247 |
+
AliasAnalysisKind alias_analysis) {
|
| 248 |
+
auto result = FunctionSchema(
|
| 249 |
+
std::move(name),
|
| 250 |
+
std::move(overload_name),
|
| 251 |
+
std::move(arguments),
|
| 252 |
+
std::move(returns),
|
| 253 |
+
/*is_vararg*/ false,
|
| 254 |
+
/*is_varret*/ false);
|
| 255 |
+
result.setAliasAnalysis(alias_analysis);
|
| 256 |
+
return result;
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
std::variant<C10Operator, JitOnlyOperator> op_;
|
| 260 |
+
};
|
| 261 |
+
|
| 262 |
+
TORCH_API std::string canonicalSchemaString(const FunctionSchema& schema);
|
| 263 |
+
|
| 264 |
+
TORCH_API const std::vector<std::shared_ptr<Operator>> getAllOperators();
|
| 265 |
+
TORCH_API const std::vector<std::shared_ptr<Operator>>& getAllOperatorsFor(
|
| 266 |
+
Symbol name);
|
| 267 |
+
// Returns operators in the order which OpOverloadPacket resolves them.
|
| 268 |
+
TORCH_API std::vector<std::shared_ptr<Operator>> getAllSortedOperatorsFor(
|
| 269 |
+
Symbol name);
|
| 270 |
+
|
| 271 |
+
// given a operator with an overload name, find the specific operator related to
|
| 272 |
+
// it, may return nullptr if no operator exists.
|
| 273 |
+
TORCH_API std::shared_ptr<Operator> findOperatorFor(
|
| 274 |
+
const c10::OperatorName& full_name);
|
| 275 |
+
|
| 276 |
+
TORCH_API std::vector<Symbol> findSimilarOperators(Symbol input_op);
|
| 277 |
+
|
| 278 |
+
TORCH_API void registerOperator(Operator&& op);
|
| 279 |
+
TORCH_API void deregisterOperator(const FunctionSchema& schema);
|
| 280 |
+
|
| 281 |
+
// XXX: this function is meant to be used with string literals only!
|
| 282 |
+
TORCH_API std::shared_ptr<Operator> getOperatorForLiteral(
|
| 283 |
+
const char* signature);
|
| 284 |
+
|
| 285 |
+
// Ensure the thing that registers c10 ops is defined.
|
| 286 |
+
// Otherwise, our registry will not have c10 ops. You can run into this
|
| 287 |
+
// scenario if you're querying registered ops during static init.
|
| 288 |
+
//
|
| 289 |
+
// This fn is defined in register_c10_ops.cpp
|
| 290 |
+
TORCH_API void ensure_c10_registerer_defined();
|
| 291 |
+
|
| 292 |
+
// Used to assert that unschematized operators have an analysis method written
|
| 293 |
+
TORCH_API bool aliasAnalysisHasSpecialCaseFor(c10::Symbol sym);
|
| 294 |
+
|
| 295 |
+
// A factory function to generate an optional operator. It has two
|
| 296 |
+
// instantiations depending on the template bool arg value. The arg can be a
|
| 297 |
+
// compile-time function for the selective op registration based on schema
|
| 298 |
+
// string.
|
| 299 |
+
template <typename Func>
|
| 300 |
+
std::optional<Operator> OperatorGenerator(
|
| 301 |
+
const char* schema_str,
|
| 302 |
+
Func&& op,
|
| 303 |
+
AliasAnalysisKind alias_analysis) {
|
| 304 |
+
return std::optional<Operator>(Operator(
|
| 305 |
+
std::string(schema_str), std::forward<Func>(op), alias_analysis));
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
template <typename Func>
|
| 309 |
+
std::optional<Operator> OperatorGenerator(
|
| 310 |
+
torch::detail::SelectiveStr<true> schema_str,
|
| 311 |
+
Func&& op,
|
| 312 |
+
AliasAnalysisKind alias_analysis) {
|
| 313 |
+
return OperatorGenerator(
|
| 314 |
+
static_cast<const char*>(schema_str),
|
| 315 |
+
std::forward<Func>(op),
|
| 316 |
+
alias_analysis);
|
| 317 |
+
}
|
| 318 |
+
|
| 319 |
+
template <typename Func>
|
| 320 |
+
std::optional<Operator> OperatorGenerator(
|
| 321 |
+
torch::detail::SelectiveStr<false> schema_str,
|
| 322 |
+
Func&& op,
|
| 323 |
+
AliasAnalysisKind alias_analysis) {
|
| 324 |
+
return std::nullopt;
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
template <typename Func>
|
| 328 |
+
std::optional<Operator> OperatorGenerator(
|
| 329 |
+
const std::string name,
|
| 330 |
+
const std::string overload_name,
|
| 331 |
+
const std::vector<c10::Argument> arguments,
|
| 332 |
+
const std::vector<c10::Argument> returns,
|
| 333 |
+
Func&& op,
|
| 334 |
+
AliasAnalysisKind alias_analysis) {
|
| 335 |
+
return std::optional<Operator>(Operator(
|
| 336 |
+
name,
|
| 337 |
+
overload_name,
|
| 338 |
+
arguments,
|
| 339 |
+
returns,
|
| 340 |
+
std::forward<Func>(op),
|
| 341 |
+
alias_analysis));
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
} // namespace torch::jit
|
| 345 |
+
|
| 346 |
+
#else
|
| 347 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 348 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/operator_options.h
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <ATen/core/dispatch/OperatorOptions.h>
|
| 5 |
+
|
| 6 |
+
namespace torch::jit {
|
| 7 |
+
|
| 8 |
+
using AliasAnalysisKind = c10::AliasAnalysisKind;
|
| 9 |
+
|
| 10 |
+
} // namespace torch::jit
|
| 11 |
+
|
| 12 |
+
#else
|
| 13 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 14 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/print_handler.h
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/Export.h>
|
| 5 |
+
|
| 6 |
+
#include <string>
|
| 7 |
+
|
| 8 |
+
namespace torch::jit {
|
| 9 |
+
|
| 10 |
+
using PrintHandler = void (*)(const std::string&);
|
| 11 |
+
|
| 12 |
+
TORCH_API PrintHandler getDefaultPrintHandler();
|
| 13 |
+
TORCH_API PrintHandler getPrintHandler();
|
| 14 |
+
TORCH_API void setPrintHandler(PrintHandler ph);
|
| 15 |
+
|
| 16 |
+
} // namespace torch::jit
|
| 17 |
+
|
| 18 |
+
#else
|
| 19 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 20 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/profiling_graph_executor_impl.h
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <c10/util/Flags.h>
|
| 4 |
+
#include <torch/csrc/jit/api/module.h>
|
| 5 |
+
#include <torch/csrc/jit/runtime/graph_executor_impl.h>
|
| 6 |
+
|
| 7 |
+
TORCH_DECLARE_bool(torch_jit_static_then_dynamic);
|
| 8 |
+
|
| 9 |
+
TORCH_DECLARE_bool(torch_jit_always_dynamic);
|
| 10 |
+
|
| 11 |
+
C10_DECLARE_bool(torch_jit_input_independent_optimization);
|
| 12 |
+
C10_DECLARE_bool(torch_jit_release_profiling_graph_after_optimization);
|
| 13 |
+
C10_DECLARE_int32(torch_jit_release_profiling_graph_delay_in_seconds);
|
| 14 |
+
C10_DECLARE_int64(torch_jit_num_profiled_runs);
|
| 15 |
+
C10_DECLARE_int64(torch_jit_bailout_depth);
|
| 16 |
+
|
| 17 |
+
namespace torch::jit {
|
| 18 |
+
|
| 19 |
+
TORCH_API void runNooptPassPipeline(std::shared_ptr<Graph>& graph);
|
| 20 |
+
|
| 21 |
+
struct TORCH_API ProfilingGraphExecutorImpl : public GraphExecutorImplBase {
|
| 22 |
+
ProfilingGraphExecutorImpl(
|
| 23 |
+
const std::shared_ptr<Graph>& graph,
|
| 24 |
+
std::string function_name);
|
| 25 |
+
|
| 26 |
+
const ExecutionPlan& getPlanFor(
|
| 27 |
+
Stack& stack,
|
| 28 |
+
std::optional<size_t> remaining_bailout_depth) override;
|
| 29 |
+
const ExecutionPlan& getInputIndependentPlan() override;
|
| 30 |
+
GraphExecutorState getDebugState() override;
|
| 31 |
+
~ProfilingGraphExecutorImpl() override = default;
|
| 32 |
+
|
| 33 |
+
void debugFlushCompilationCache();
|
| 34 |
+
|
| 35 |
+
bool isOptimized() const override {
|
| 36 |
+
return optimized_plan_.has_value();
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
private:
|
| 40 |
+
const ExecutionPlan& getOptimizedPlanFor(
|
| 41 |
+
Stack& stack,
|
| 42 |
+
std::optional<size_t> remaining_bailout_depth);
|
| 43 |
+
// Input-independent optimization, assumes compile_mutex is held.
|
| 44 |
+
const ExecutionPlan& getInputIndependentPlanImpl();
|
| 45 |
+
void runProfilingInsensitiveOptimizations(std::shared_ptr<Graph>& graph);
|
| 46 |
+
void runProfilingOptimizations(
|
| 47 |
+
std::shared_ptr<Graph>& graph,
|
| 48 |
+
size_t remaining_depth);
|
| 49 |
+
void replaceFallbackGraphWithFallbackFunction(Block* b);
|
| 50 |
+
FusionBehavior getCurrentBehavior(size_t remaining_depth);
|
| 51 |
+
size_t getInstantiatedBailoutDepth();
|
| 52 |
+
void runNoGradOptimizations(
|
| 53 |
+
std::shared_ptr<Graph>& graph,
|
| 54 |
+
size_t remaining_bailout_depth);
|
| 55 |
+
void runFinalOptimizations(std::shared_ptr<Graph>& graph);
|
| 56 |
+
|
| 57 |
+
void clearTheGraphCompilationIntermediateGraphs();
|
| 58 |
+
|
| 59 |
+
std::unique_ptr<ProfilingRecord> pr_;
|
| 60 |
+
std::optional<ExecutionPlan>
|
| 61 |
+
profiling_plan_; // plan to run in order to profiling the code
|
| 62 |
+
std::optional<ExecutionPlan> optimized_plan_;
|
| 63 |
+
FusionStrategy fusion_strategy_;
|
| 64 |
+
|
| 65 |
+
// this plan is used if getGraphExecutorOptimize is unset
|
| 66 |
+
std::optional<ExecutionPlan> fallback_plan_;
|
| 67 |
+
// fallback functions are inserted for tensorexpr fusion groups
|
| 68 |
+
// and by specialize_autogradzero. Whenever, at runtime, input
|
| 69 |
+
// tensor don't match profiled properties, fallback functions are called
|
| 70 |
+
// They are the deoptimized version of the logic in fusion groups
|
| 71 |
+
// and/or autograd.
|
| 72 |
+
// The fallback functions are owned by a GraphExecutor instance
|
| 73 |
+
// They only exist in the optimized graph which is a private property
|
| 74 |
+
// of the GraphExecutor and only shared with InterpreterState
|
| 75 |
+
std::vector<std::unique_ptr<Function>> fallback_functions_;
|
| 76 |
+
std::optional<size_t> remaining_bailout_depth_;
|
| 77 |
+
// The time the optimized_plan_ is created.
|
| 78 |
+
int32_t time_optimized_plan_created_ = 0;
|
| 79 |
+
// Has the extra memory used by the graph for profiling is released?
|
| 80 |
+
bool is_graph_extra_memory_released_ = false;
|
| 81 |
+
};
|
| 82 |
+
|
| 83 |
+
} // namespace torch::jit
|
| 84 |
+
|
| 85 |
+
#else
|
| 86 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 87 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/profiling_record.h
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <ATen/ATen.h>
|
| 5 |
+
#include <ATen/core/ivalue.h>
|
| 6 |
+
#include <ATen/core/jit_type.h>
|
| 7 |
+
#include <ATen/core/stack.h>
|
| 8 |
+
#include <torch/csrc/Export.h>
|
| 9 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 10 |
+
|
| 11 |
+
#include <list>
|
| 12 |
+
#include <map>
|
| 13 |
+
#include <unordered_map>
|
| 14 |
+
#include <vector>
|
| 15 |
+
|
| 16 |
+
// We would like to assign each position/axis of a tensor an abstract size
|
| 17 |
+
// * For each `tensor` we have a profiled `Value` of a `TensorType` describing
|
| 18 |
+
// the properties of the `tensor`.
|
| 19 |
+
// * `TensorType` has a property called `symbolic_sizes_` to describe observed
|
| 20 |
+
// `tensor.sizes()`
|
| 21 |
+
// * `symbolic_sizes_` is a vector of abstract sizes (or
|
| 22 |
+
// `std::vector<ShapeSymbol>`) where
|
| 23 |
+
// * `ShapeSymbol`at `symbolic_sizes_[i]` describes the size value
|
| 24 |
+
// (`Dimension`) at `tensor.sizes()[i]`
|
| 25 |
+
// * We may see the same `Dimension` at different positions `i` in
|
| 26 |
+
// `tensor.sizes()` or even in different `tensor`
|
| 27 |
+
// * First, we would like associate the same `ShapeSymbol` to the same
|
| 28 |
+
// `Dimension` across **one** profiling execution or run of a TorchScript
|
| 29 |
+
// function.
|
| 30 |
+
// * The same `ShapeSymbol`s in different positions of `symbolic_shapes_` in
|
| 31 |
+
// possibly different `TensorType`s (i.e. `TensorType`s for different
|
| 32 |
+
// profiled values) form an implicit set. The elements of such a set are
|
| 33 |
+
// called *dimension locations*.
|
| 34 |
+
// * These sets allow us to track how the shapes of input arguments of some
|
| 35 |
+
// operation relate to operation's output shapes as the input and output
|
| 36 |
+
// shapes might share the same `ShapeSymbol`s
|
| 37 |
+
// * For **every** profiling run, we would like to maintain the invariant that
|
| 38 |
+
// *the same `ShapeSymbol` is always associated with the same `Dimension`*.
|
| 39 |
+
// * To maintain this invariant we merge the profiling information from all
|
| 40 |
+
// profiling runs,
|
| 41 |
+
// * For every two runs, we iterate over all `symbic_shapes_` and compare
|
| 42 |
+
// their `ShapeSymbol`s in the same position.
|
| 43 |
+
// * if we observe that for every dimension location that has
|
| 44 |
+
// the`ShapeSymbol S1` in run #1 there is **only one** `ShapeSymbol S2` in
|
| 45 |
+
// the same dimension location in run #2, we conclude that the invariant
|
| 46 |
+
// holds.
|
| 47 |
+
// * However, if we observe some dimension locations in run #2 have
|
| 48 |
+
// `ShapeSymbol S2` and the other ones have `ShapeSymbol S3` we would like
|
| 49 |
+
// to partition the virtual set of dimension locations associated with
|
| 50 |
+
// `ShapeSymbol S1` into two new subsets, so the invariant holds.
|
| 51 |
+
// * The partitioning works by assigning a new symbol to the dimension
|
| 52 |
+
// locations (associated with `ShapeSymbol S1`) that have `ShapeSymbol S2`
|
| 53 |
+
// and another new symbol to the dimension locations that have `ShapeSymbol
|
| 54 |
+
// S3`. In other words,
|
| 55 |
+
// * Subset #1 will consist of the dimension locations that in run #2 have
|
| 56 |
+
// `ShapeSymbol S2` and will have `ShapeSymbol S4` in those dimension
|
| 57 |
+
// locations
|
| 58 |
+
// * Subset #2 will consist of the dimension locations that in run #2 have
|
| 59 |
+
// `ShapeSymbol S4` and will have `ShapeSymbol S5` in those dimension
|
| 60 |
+
// locations
|
| 61 |
+
// * The effective result of merging the profiling information from two runs
|
| 62 |
+
// is new `TensorTypes` whose `symbolic_sizes_` /dimension locations have
|
| 63 |
+
// either `ShapeSymbol S4` or `ShapeSymbol S5`.
|
| 64 |
+
// * Partitioning can be done even before we have seen all the dimension
|
| 65 |
+
// locations associated with `ShapeSymbol S1`
|
| 66 |
+
// * We use `getSymbolInSet` of `ShapeSymbolTable` to remember all
|
| 67 |
+
// `ShapeSymbols` from run #2 we observed in the dimension locations
|
| 68 |
+
// associated with `ShapeSymbol S1` .
|
| 69 |
+
// * For every `ShapeSymbol` from run #2 in the dimension location
|
| 70 |
+
// associated with `ShapeSymbol S1` `getSymbolInSet` returns a symbol
|
| 71 |
+
// that we assign to the dimension location in a new TensorType.
|
| 72 |
+
// * It's important to point out that the same `ShapeSymbol S2` from run
|
| 73 |
+
// #2 in two dimension locations that have different `ShapeSymbol`s in
|
| 74 |
+
// run #1 are different! These dimension locations will belong to
|
| 75 |
+
// different subsets and have different `ShapeSymbol`s after merge.
|
| 76 |
+
// * On the other hand, for the same `ShapeSymbol S2` in two dimension
|
| 77 |
+
// locations that have `ShapeSymbol S1` in run #1`getSymbolInSet` will
|
| 78 |
+
// return the same symbol.
|
| 79 |
+
|
| 80 |
+
namespace torch::jit {
|
| 81 |
+
|
| 82 |
+
using ::c10::TensorTypePtr;
|
| 83 |
+
using Dimension = int64_t;
|
| 84 |
+
|
| 85 |
+
TORCH_API void RegisterProfilingNode(
|
| 86 |
+
const std::function<bool(const Node*)>& /*func*/);
|
| 87 |
+
|
| 88 |
+
struct ProfilingRecord;
|
| 89 |
+
|
| 90 |
+
// `SetPartitioningHelper` is used to maintain the following invariant:
|
| 91 |
+
// For **every** profiling run, *the same `ShapeSymbol` is always associated
|
| 92 |
+
// with the same `Dimension`*.
|
| 93 |
+
// while merging the profiling information from multiple runs.
|
| 94 |
+
struct SetPartitioningHelper {
|
| 95 |
+
std::map<c10::ShapeSymbol, std::map<Dimension, c10::ShapeSymbol>>
|
| 96 |
+
sets2subsets_;
|
| 97 |
+
|
| 98 |
+
// `partitionSetByDimension` partitions a virtual set
|
| 99 |
+
// of dimension locations associated with ShapeSymbol `symbol` into subsets.
|
| 100 |
+
// Partitioning is equivalent to giving (or renaming) a particular
|
| 101 |
+
// dimension location a new `ShapeSymbol`.
|
| 102 |
+
// The same `Dimension` value in different dimension locations
|
| 103 |
+
// that used to have `symbol` will receive the same
|
| 104 |
+
// new `ShapeSymbol`, effectively forming a new set.
|
| 105 |
+
c10::ShapeSymbol partitionSetByDimension(
|
| 106 |
+
Dimension new_size,
|
| 107 |
+
c10::ShapeSymbol symbol) {
|
| 108 |
+
auto& dims2symbols = getSetForSymbol(symbol);
|
| 109 |
+
|
| 110 |
+
if (dims2symbols.count(new_size) == 0) {
|
| 111 |
+
auto new_sym = c10::ShapeSymbol::newSymbol();
|
| 112 |
+
dims2symbols[new_size] = new_sym;
|
| 113 |
+
return new_sym;
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
return dims2symbols[new_size];
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
private:
|
| 120 |
+
std::map<Dimension, c10::ShapeSymbol>& getSetForSymbol(c10::ShapeSymbol s) {
|
| 121 |
+
auto& set = sets2subsets_[s];
|
| 122 |
+
// N.B. adding a mapping { s.static_size(), s }
|
| 123 |
+
// makes sure we preserve the fact that
|
| 124 |
+
// some dimension values remain the same
|
| 125 |
+
// across all profiled runs
|
| 126 |
+
if (s.is_static()) {
|
| 127 |
+
set.insert({s.static_size(), s});
|
| 128 |
+
}
|
| 129 |
+
return set;
|
| 130 |
+
}
|
| 131 |
+
};
|
| 132 |
+
|
| 133 |
+
// ShapeSymbolTable is used by Interpreter
|
| 134 |
+
// to assign dimension values to ShapeSymbols
|
| 135 |
+
// and fail a guard if the same symbol
|
| 136 |
+
// is assigned more than one dimension value.
|
| 137 |
+
struct ShapeSymbolTable {
|
| 138 |
+
// N.B. we treat static symbols as always assigned
|
| 139 |
+
// to themselves
|
| 140 |
+
bool isBound(c10::ShapeSymbol s) {
|
| 141 |
+
if (s.is_static()) {
|
| 142 |
+
return true;
|
| 143 |
+
}
|
| 144 |
+
return data_.count(s) != 0;
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
// N.B. we treat static symbols as always assigned
|
| 148 |
+
// to themselves
|
| 149 |
+
Dimension getValue(c10::ShapeSymbol s) {
|
| 150 |
+
if (s.is_static()) {
|
| 151 |
+
return s.static_size();
|
| 152 |
+
}
|
| 153 |
+
return data_[s];
|
| 154 |
+
}
|
| 155 |
+
void assign(c10::ShapeSymbol s, Dimension v) {
|
| 156 |
+
TORCH_INTERNAL_ASSERT(!s.is_static());
|
| 157 |
+
data_[s] = v;
|
| 158 |
+
}
|
| 159 |
+
std::map<c10::ShapeSymbol, Dimension> data_;
|
| 160 |
+
// Tries to assign dimension values from `new_sizes` to
|
| 161 |
+
// `ShapeSymbol`s `sym_shapes`.
|
| 162 |
+
// Returns `true` if every dimension value from `new_sizes`
|
| 163 |
+
// can be assigned to the corresponding `ShapeSymbol` from
|
| 164 |
+
// `sym_shapes`
|
| 165 |
+
// A dimension value can be assigned to a `ShapeSymbol`
|
| 166 |
+
// * if the symbol isn't assigned yet any dimension value
|
| 167 |
+
// * if the symbol is assigned and its value is equal to
|
| 168 |
+
// the dimension value from `new_sizes`
|
| 169 |
+
bool bindSymbolicShapes(
|
| 170 |
+
at::IntArrayRef new_sizes,
|
| 171 |
+
const c10::SymbolicShape& sym_shapes);
|
| 172 |
+
};
|
| 173 |
+
|
| 174 |
+
struct ProfilingRecord {
|
| 175 |
+
// N.B. ProfilingRecord's copy and move c-tor are disabled, so we won't
|
| 176 |
+
// end up accidentally copying or moving ProfilingRecords whose addresses
|
| 177 |
+
// are captured in callbacks_
|
| 178 |
+
ProfilingRecord(const ProfilingRecord&) = delete;
|
| 179 |
+
ProfilingRecord(ProfilingRecord&&) noexcept = delete;
|
| 180 |
+
TORCH_API static std::unique_ptr<ProfilingRecord> instrumentGraph(
|
| 181 |
+
const std::shared_ptr<Graph>& graph);
|
| 182 |
+
TORCH_API static void removeProfilingNodes(Block* b);
|
| 183 |
+
TORCH_API static void removeProfileCounter(Block* b);
|
| 184 |
+
|
| 185 |
+
std::shared_ptr<Graph> profiled_graph_;
|
| 186 |
+
mutable std::mutex mutex_;
|
| 187 |
+
size_t profiling_count_;
|
| 188 |
+
|
| 189 |
+
bool ready() const;
|
| 190 |
+
|
| 191 |
+
std::shared_ptr<Graph> graph() const {
|
| 192 |
+
return profiled_graph_;
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
TORCH_API ProfileIValueOp* createProfileIValueNode(Value* in_val);
|
| 196 |
+
TORCH_API ProfileIValueOp* createProfileIValueNode(ArrayRef<Value*> inputs);
|
| 197 |
+
|
| 198 |
+
private:
|
| 199 |
+
ProfileOp* createProfileNode(
|
| 200 |
+
const std::function<void(Stack&)>& fp,
|
| 201 |
+
at::ArrayRef<Value*> inputs);
|
| 202 |
+
void instrumentBlock(Block* block);
|
| 203 |
+
void insertShapeProfile(Node* n, size_t offset, const TypePtr& input_type);
|
| 204 |
+
ProfilingRecord(std::shared_ptr<Graph> g);
|
| 205 |
+
};
|
| 206 |
+
|
| 207 |
+
} // namespace torch::jit
|
| 208 |
+
|
| 209 |
+
#else
|
| 210 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 211 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/register_ops_utils.h
ADDED
|
@@ -0,0 +1,888 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <ATen/Context.h>
|
| 5 |
+
#include <c10/core/DeviceType.h>
|
| 6 |
+
#include <torch/csrc/autograd/autograd.h>
|
| 7 |
+
#include <torch/csrc/autograd/edge.h>
|
| 8 |
+
#include <torch/csrc/autograd/function.h>
|
| 9 |
+
#include <torch/csrc/autograd/generated/variable_factories.h>
|
| 10 |
+
#include <torch/csrc/autograd/variable.h>
|
| 11 |
+
#include <torch/csrc/jit/api/compilation_unit.h>
|
| 12 |
+
#include <torch/csrc/jit/api/module.h>
|
| 13 |
+
#include <torch/csrc/jit/frontend/error_report.h>
|
| 14 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 15 |
+
#include <torch/csrc/jit/mobile/register_ops_common_utils.h>
|
| 16 |
+
#include <torch/csrc/jit/runtime/custom_operator.h>
|
| 17 |
+
#include <torch/csrc/jit/runtime/graph_executor.h>
|
| 18 |
+
#include <torch/csrc/jit/runtime/jit_exception.h>
|
| 19 |
+
#include <torch/csrc/jit/runtime/logging.h>
|
| 20 |
+
#include <torch/csrc/jit/runtime/operator.h>
|
| 21 |
+
#include <torch/csrc/jit/runtime/print_handler.h>
|
| 22 |
+
#include <torch/csrc/jit/runtime/profiling_record.h>
|
| 23 |
+
#include <torch/csrc/jit/runtime/vararg_functions.h>
|
| 24 |
+
#include <torch/csrc/jit/serialization/pickle.h>
|
| 25 |
+
|
| 26 |
+
#include <ATen/ExpandUtils.h>
|
| 27 |
+
#include <ATen/Parallel.h>
|
| 28 |
+
#include <ATen/WrapDimUtils.h>
|
| 29 |
+
#include <ATen/core/Dict.h>
|
| 30 |
+
#include <ATen/core/Generator.h>
|
| 31 |
+
#include <ATen/core/ivalue.h>
|
| 32 |
+
#include <c10/core/Device.h>
|
| 33 |
+
#include <c10/core/thread_pool.h>
|
| 34 |
+
#include <c10/util/SmallVector.h>
|
| 35 |
+
#include <c10/util/irange.h>
|
| 36 |
+
|
| 37 |
+
namespace torch::jit {
|
| 38 |
+
constexpr inline c10::AliasAnalysisKind aliasAnalysisFromSchema() {
|
| 39 |
+
return c10::AliasAnalysisKind::FROM_SCHEMA;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
constexpr inline c10::AliasAnalysisKind aliasAnalysisConservative() {
|
| 43 |
+
return c10::AliasAnalysisKind::CONSERVATIVE;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
constexpr inline c10::AliasAnalysisKind aliasAnalysisSpecialCase() {
|
| 47 |
+
return c10::AliasAnalysisKind::INTERNAL_SPECIAL_CASE;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
template <class T>
|
| 51 |
+
c10::List<T> make_result_list(const TypePtr& elemType) {
|
| 52 |
+
return c10::List<T>();
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
template <>
|
| 56 |
+
c10::impl::GenericList make_result_list<IValue>(const TypePtr& elemType);
|
| 57 |
+
|
| 58 |
+
// As described in https://docs.python.org/3/library/functions.html#round
|
| 59 |
+
// When a number is exactly halfway between two integers, python builtin round
|
| 60 |
+
// function will round to even number. We use round(x/2)*2 to handle the
|
| 61 |
+
// special halfway case. For positive 'x', round(x/2)*2 =
|
| 62 |
+
// round((x_e + x_r)/2)*2 = x_e + round(x_r/2)*2, where x_e is an even integer,
|
| 63 |
+
// x_r is either 0.5 of 1.5, round(x_r/2)*2 results a 0 or 2, so the final
|
| 64 |
+
// result will always be a even number. Due to symmetricity, it also applies to
|
| 65 |
+
// negative cases.
|
| 66 |
+
inline double round_to_even(double a) {
|
| 67 |
+
return a - std::floor(a) == 0.5 ? (std::round(a * 0.5) * 2.0) : std::round(a);
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
// using the rules from python_arg_parser FunctionParameter::check
|
| 71 |
+
// tensor cannot have grad set, tensor must be 0 dim,
|
| 72 |
+
// and if the dest is an int the source must be integral type
|
| 73 |
+
void checkImplicitTensorToNum(const at::Tensor& t, bool toInt);
|
| 74 |
+
|
| 75 |
+
[[maybe_unused]] static int64_t floordiv(int64_t a, int64_t b) {
|
| 76 |
+
if (b == 0) {
|
| 77 |
+
throw std::runtime_error("division by 0");
|
| 78 |
+
}
|
| 79 |
+
if ((a > 0) == (b > 0)) {
|
| 80 |
+
// simple case, both have same sign
|
| 81 |
+
return a / b;
|
| 82 |
+
} else {
|
| 83 |
+
// in python division rounds down, it doesn't not truncate like in c++
|
| 84 |
+
auto r = lldiv(a, b);
|
| 85 |
+
return (r.rem) ? r.quot - 1 : r.quot;
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
TORCH_API void checkDoubleInRange(double a);
|
| 89 |
+
[[maybe_unused]] static int64_t floor(double a) {
|
| 90 |
+
checkDoubleInRange(a);
|
| 91 |
+
return std::floor(a);
|
| 92 |
+
}
|
| 93 |
+
[[maybe_unused]] static int64_t ceil(double a) {
|
| 94 |
+
checkDoubleInRange(a);
|
| 95 |
+
return std::ceil(a);
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
[[maybe_unused]] static int64_t gcd(int64_t a, int64_t b) {
|
| 99 |
+
while (b != 0) {
|
| 100 |
+
int64_t r = a % b;
|
| 101 |
+
a = b;
|
| 102 |
+
b = r;
|
| 103 |
+
}
|
| 104 |
+
// in python gcd returns non-negative values
|
| 105 |
+
return std::abs(a);
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
int64_t partProduct(int n, int m);
|
| 109 |
+
|
| 110 |
+
void loop(int n, int64_t& p, int64_t& r);
|
| 111 |
+
|
| 112 |
+
int nminussumofbits(int v);
|
| 113 |
+
|
| 114 |
+
int64_t factorial(int n);
|
| 115 |
+
static const double degToRad = std::acos(-1.0) / 180.0;
|
| 116 |
+
static const double radToDeg = 180.0 / std::acos(-1.0);
|
| 117 |
+
double degrees(double x);
|
| 118 |
+
double radians(double x);
|
| 119 |
+
|
| 120 |
+
// Convert an python index (which may be negative) into an index usable for a
|
| 121 |
+
// C++ container
|
| 122 |
+
|
| 123 |
+
// Equivalent to list.at(idx)
|
| 124 |
+
template <typename T>
|
| 125 |
+
auto getItem(const c10::List<T>& list, int64_t idx) {
|
| 126 |
+
const int64_t list_size = list.size();
|
| 127 |
+
const int64_t normalized_idx = normalizeIndex(idx, list_size);
|
| 128 |
+
if (normalized_idx < 0 || normalized_idx >= list_size) {
|
| 129 |
+
throw std::out_of_range("list index out of range");
|
| 130 |
+
}
|
| 131 |
+
return list.get(normalized_idx);
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
template <typename T>
|
| 135 |
+
void setItem(const c10::List<T>& list, int64_t idx, T&& value) {
|
| 136 |
+
const int64_t list_size = list.size();
|
| 137 |
+
const int64_t normalized_idx = normalizeIndex(idx, list_size);
|
| 138 |
+
if (normalized_idx < 0 || normalized_idx >= list_size) {
|
| 139 |
+
throw std::out_of_range("list index out of range");
|
| 140 |
+
}
|
| 141 |
+
list.set(normalized_idx, std::forward<T>(value));
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
void listAppend(Stack& stack);
|
| 145 |
+
|
| 146 |
+
void listReverse(Stack& stack);
|
| 147 |
+
|
| 148 |
+
template <typename T>
|
| 149 |
+
void minList(Stack& stack) {
|
| 150 |
+
c10::List<T> a = pop(stack).to<c10::List<T>>();
|
| 151 |
+
c10::List<T> b = pop(stack).to<c10::List<T>>();
|
| 152 |
+
|
| 153 |
+
size_t min_size = std::min(a.size(), b.size());
|
| 154 |
+
for (const auto i : c10::irange(min_size)) {
|
| 155 |
+
if (a[i] == b[i]) {
|
| 156 |
+
continue;
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
push(stack, a[i] < b[i] ? a : b);
|
| 160 |
+
return;
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
push(stack, b.size() < a.size() ? b : a);
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
template <typename T>
|
| 167 |
+
void maxList(Stack& stack) {
|
| 168 |
+
c10::List<T> a = pop(stack).to<c10::List<T>>();
|
| 169 |
+
c10::List<T> b = pop(stack).to<c10::List<T>>();
|
| 170 |
+
|
| 171 |
+
size_t min_size = std::min(a.size(), b.size());
|
| 172 |
+
for (const auto i : c10::irange(min_size)) {
|
| 173 |
+
if (a[i] == b[i]) {
|
| 174 |
+
continue;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
push(stack, a[i] > b[i] ? a : b);
|
| 178 |
+
return;
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
push(stack, b.size() > a.size() ? b : a);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
void listPopImpl(Stack& stack, const char* empty_message);
|
| 185 |
+
|
| 186 |
+
void listPop(Stack& stack);
|
| 187 |
+
|
| 188 |
+
void listClear(Stack& stack);
|
| 189 |
+
|
| 190 |
+
void listDelete(Stack& stack);
|
| 191 |
+
|
| 192 |
+
void listInsert(Stack& stack);
|
| 193 |
+
|
| 194 |
+
template <typename T>
|
| 195 |
+
void listRemove(Stack& stack) {
|
| 196 |
+
T elem = pop(stack).to<T>();
|
| 197 |
+
c10::List<T> list = pop(stack).to<c10::List<T>>();
|
| 198 |
+
|
| 199 |
+
auto pos = std::find(list.begin(), list.end(), elem);
|
| 200 |
+
|
| 201 |
+
if (pos != list.end()) {
|
| 202 |
+
list.erase(pos);
|
| 203 |
+
} else {
|
| 204 |
+
TORCH_CHECK(false, "list.remove(x): x not in list");
|
| 205 |
+
}
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
template <typename T>
|
| 209 |
+
void listMin(Stack& stack) {
|
| 210 |
+
c10::List<T> list = pop(stack).to<c10::List<T>>();
|
| 211 |
+
size_t list_size = list.size();
|
| 212 |
+
if (list_size == 0) {
|
| 213 |
+
throw std::runtime_error("min() arg is an empty sequence");
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
T min_elem = list[0];
|
| 217 |
+
for (const auto i : c10::irange(1, list_size)) {
|
| 218 |
+
T elem = list[i];
|
| 219 |
+
min_elem = elem < min_elem ? elem : min_elem;
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
stack.push_back(min_elem);
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
template <typename T>
|
| 226 |
+
void listMax(Stack& stack) {
|
| 227 |
+
c10::List<T> list = pop(stack).to<c10::List<T>>();
|
| 228 |
+
size_t list_size = list.size();
|
| 229 |
+
if (list_size == 0) {
|
| 230 |
+
throw std::runtime_error("max() arg is an empty sequence");
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
T max_elem = list[0];
|
| 234 |
+
for (const auto i : c10::irange(1, list_size)) {
|
| 235 |
+
T elem = list[i];
|
| 236 |
+
max_elem = elem > max_elem ? elem : max_elem;
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
stack.push_back(max_elem);
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
template <>
|
| 243 |
+
void listRemove<at::Tensor>(Stack& stack);
|
| 244 |
+
|
| 245 |
+
template <typename T>
|
| 246 |
+
void listIndex(Stack& stack) {
|
| 247 |
+
T elem = pop(stack).to<T>();
|
| 248 |
+
c10::List<T> list = pop(stack).to<c10::List<T>>();
|
| 249 |
+
|
| 250 |
+
auto pos = std::find(list.begin(), list.end(), elem);
|
| 251 |
+
|
| 252 |
+
if (pos != list.end()) {
|
| 253 |
+
push(stack, static_cast<int64_t>(std::distance(list.begin(), pos)));
|
| 254 |
+
} else {
|
| 255 |
+
TORCH_CHECK(false, "'", elem, "' is not in list");
|
| 256 |
+
}
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
template <>
|
| 260 |
+
void listIndex<at::Tensor>(Stack& stack);
|
| 261 |
+
|
| 262 |
+
template <typename T>
|
| 263 |
+
void listCount(Stack& stack) {
|
| 264 |
+
T elem = pop(stack).to<T>();
|
| 265 |
+
c10::List<T> list = pop(stack).to<c10::List<T>>();
|
| 266 |
+
|
| 267 |
+
const int64_t count = std::count(list.begin(), list.end(), elem);
|
| 268 |
+
push(stack, count);
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
template <>
|
| 272 |
+
void listCount<at::Tensor>(Stack& stack);
|
| 273 |
+
|
| 274 |
+
void listExtend(Stack& stack);
|
| 275 |
+
|
| 276 |
+
void listCopy(Stack& stack);
|
| 277 |
+
|
| 278 |
+
void listSelect(Stack& stack);
|
| 279 |
+
|
| 280 |
+
void listLen(Stack& stack);
|
| 281 |
+
|
| 282 |
+
template <typename T>
|
| 283 |
+
void listEq(Stack& stack) {
|
| 284 |
+
c10::List<T> b = pop(stack).to<c10::List<T>>();
|
| 285 |
+
c10::List<T> a = pop(stack).to<c10::List<T>>();
|
| 286 |
+
push(stack, a == b);
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
template <typename T>
|
| 290 |
+
void listNe(Stack& stack) {
|
| 291 |
+
c10::List<T> b = pop(stack).to<c10::List<T>>();
|
| 292 |
+
c10::List<T> a = pop(stack).to<c10::List<T>>();
|
| 293 |
+
push(stack, a != b);
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
inline bool tensor_list_equal(
|
| 297 |
+
const c10::List<at::Tensor>& a,
|
| 298 |
+
const c10::List<at::Tensor>& b) {
|
| 299 |
+
if (a.size() != b.size()) {
|
| 300 |
+
return false;
|
| 301 |
+
}
|
| 302 |
+
|
| 303 |
+
for (const auto i : c10::irange(a.size())) {
|
| 304 |
+
const at::Tensor& a_element = a[i];
|
| 305 |
+
const at::Tensor& b_element = b[i];
|
| 306 |
+
// This preserves Python's semantics, which uses eq() to compare two
|
| 307 |
+
// elements, then passes the result to bool().
|
| 308 |
+
// see: https://docs.python.org/3.4/reference/datamodel.html#object.__ge__
|
| 309 |
+
const auto cmp_result = a_element.eq(b_element);
|
| 310 |
+
if (!at::native::is_nonzero(cmp_result)) {
|
| 311 |
+
return false;
|
| 312 |
+
}
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
return true;
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
// Specialization for at::Tensor, since it doesn't define operator==
|
| 319 |
+
template <>
|
| 320 |
+
void listEq<at::Tensor>(Stack& stack);
|
| 321 |
+
|
| 322 |
+
// Specialization for at::Tensor, since it doesn't define operator==
|
| 323 |
+
template <>
|
| 324 |
+
void listNe<at::Tensor>(Stack& stack);
|
| 325 |
+
|
| 326 |
+
void listList(Stack& stack);
|
| 327 |
+
|
| 328 |
+
template <typename T>
|
| 329 |
+
void listContains(Stack& stack) {
|
| 330 |
+
auto key = pop(stack).to<T>();
|
| 331 |
+
auto list = pop(stack).to<c10::List<T>>();
|
| 332 |
+
// NOLINTNEXTLINE(performance-implicit-conversion-in-loop)
|
| 333 |
+
for (const T& item : list) {
|
| 334 |
+
if (item == key) {
|
| 335 |
+
push(stack, true);
|
| 336 |
+
return;
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
push(stack, false);
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
void listAdd(Stack& stack);
|
| 343 |
+
|
| 344 |
+
void listInplaceAdd(Stack& stack);
|
| 345 |
+
|
| 346 |
+
void listMulIntLeftInPlace(Stack& stack);
|
| 347 |
+
|
| 348 |
+
void listMulIntLeft(Stack& stack);
|
| 349 |
+
|
| 350 |
+
void listMulIntRight(Stack& stack);
|
| 351 |
+
|
| 352 |
+
void listSlice(Stack& stack);
|
| 353 |
+
|
| 354 |
+
template <typename T>
|
| 355 |
+
void listSort(Stack& stack) {
|
| 356 |
+
bool reverse = pop(stack).toBool();
|
| 357 |
+
c10::List<T> list = pop(stack).to<c10::List<T>>();
|
| 358 |
+
std::sort(list.begin(), list.end(), [reverse](const T& a, const T& b) {
|
| 359 |
+
// FBCode errors without this check - "strict weak ordering"
|
| 360 |
+
// TODO: remove when possible, since it just slows down
|
| 361 |
+
// sorting and doesn't do anything useful
|
| 362 |
+
if (a == b) {
|
| 363 |
+
return false;
|
| 364 |
+
}
|
| 365 |
+
return (a < b) != reverse;
|
| 366 |
+
});
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
// Specialization for at::Tensor
|
| 370 |
+
template <>
|
| 371 |
+
void listSort<at::Tensor>(Stack& stack);
|
| 372 |
+
|
| 373 |
+
template <typename T>
|
| 374 |
+
void listCopyAndSort(Stack& stack) {
|
| 375 |
+
c10::List<T> list = pop(stack).to<c10::List<T>>();
|
| 376 |
+
auto list_copied = list.copy();
|
| 377 |
+
std::sort(list_copied.begin(), list_copied.end(), [](const T& a, const T& b) {
|
| 378 |
+
// "strict weak ordering" issue - see other sort
|
| 379 |
+
if (a == b) {
|
| 380 |
+
return false;
|
| 381 |
+
}
|
| 382 |
+
return a < b;
|
| 383 |
+
});
|
| 384 |
+
push(stack, list_copied);
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
// Specialization for at::Tensor
|
| 388 |
+
template <>
|
| 389 |
+
void listCopyAndSort<at::Tensor>(Stack& stack);
|
| 390 |
+
|
| 391 |
+
void listSetItem(Stack& stack);
|
| 392 |
+
|
| 393 |
+
struct OperatorGeneratorArgs {
|
| 394 |
+
const char* schema_str;
|
| 395 |
+
bool isOperationCreator;
|
| 396 |
+
union {
|
| 397 |
+
void (*operation)(Stack&);
|
| 398 |
+
OperationCreator operationCreator;
|
| 399 |
+
};
|
| 400 |
+
AliasAnalysisKind aliasAnalysis;
|
| 401 |
+
|
| 402 |
+
explicit constexpr OperatorGeneratorArgs(
|
| 403 |
+
torch::detail::SelectiveStr<true> schema_str,
|
| 404 |
+
void (*op)(Stack&),
|
| 405 |
+
AliasAnalysisKind aa)
|
| 406 |
+
: schema_str(schema_str),
|
| 407 |
+
isOperationCreator(false),
|
| 408 |
+
operation(op),
|
| 409 |
+
aliasAnalysis(aa) {}
|
| 410 |
+
|
| 411 |
+
explicit constexpr OperatorGeneratorArgs(
|
| 412 |
+
torch::detail::SelectiveStr<true> schema_str,
|
| 413 |
+
OperationCreator opCreator,
|
| 414 |
+
AliasAnalysisKind aa)
|
| 415 |
+
: schema_str(schema_str),
|
| 416 |
+
isOperationCreator(true),
|
| 417 |
+
operationCreator(opCreator),
|
| 418 |
+
aliasAnalysis(aa) {}
|
| 419 |
+
|
| 420 |
+
template <typename... Args>
|
| 421 |
+
explicit constexpr OperatorGeneratorArgs(
|
| 422 |
+
torch::detail::SelectiveStr<false> /*unused*/,
|
| 423 |
+
Args... /*unused*/)
|
| 424 |
+
: schema_str(nullptr),
|
| 425 |
+
isOperationCreator(false),
|
| 426 |
+
operation(nullptr),
|
| 427 |
+
aliasAnalysis(AliasAnalysisKind::INTERNAL_SPECIAL_CASE) {}
|
| 428 |
+
};
|
| 429 |
+
|
| 430 |
+
#define DEFINE_GENERIC_BINARY_OP( \
|
| 431 |
+
aten_op, op, int_float_result, complex_result) \
|
| 432 |
+
OperatorGeneratorArgs( \
|
| 433 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op \
|
| 434 |
+
".int_int(int a, int b) -> " #int_float_result), \
|
| 435 |
+
[](Stack& stack) { \
|
| 436 |
+
int64_t a, b; \
|
| 437 |
+
pop(stack, a, b); \
|
| 438 |
+
push(stack, op); \
|
| 439 |
+
}, \
|
| 440 |
+
aliasAnalysisFromSchema()), \
|
| 441 |
+
OperatorGeneratorArgs( \
|
| 442 |
+
TORCH_SELECTIVE_SCHEMA( \
|
| 443 |
+
#aten_op \
|
| 444 |
+
".float_float(float a, float b) -> " #int_float_result), \
|
| 445 |
+
[](Stack& stack) { \
|
| 446 |
+
double a, b; \
|
| 447 |
+
pop(stack, a, b); \
|
| 448 |
+
push(stack, op); \
|
| 449 |
+
}, \
|
| 450 |
+
aliasAnalysisFromSchema()), \
|
| 451 |
+
OperatorGeneratorArgs( \
|
| 452 |
+
TORCH_SELECTIVE_SCHEMA( \
|
| 453 |
+
#aten_op \
|
| 454 |
+
".complex_complex(complex a, complex b) -> " #complex_result), \
|
| 455 |
+
[](Stack& stack) { \
|
| 456 |
+
c10::complex<double> a, b; \
|
| 457 |
+
pop(stack, a, b); \
|
| 458 |
+
push(stack, op); \
|
| 459 |
+
}, \
|
| 460 |
+
aliasAnalysisFromSchema())
|
| 461 |
+
|
| 462 |
+
// define implementations for primitive number ops
|
| 463 |
+
#define DEFINE_GENERIC_OP(aten_op, int_op, float_op, int_result, float_result) \
|
| 464 |
+
OperatorGeneratorArgs( \
|
| 465 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".int(int a, int b) -> " #int_result), \
|
| 466 |
+
[](Stack& stack) { \
|
| 467 |
+
int64_t a, b; \
|
| 468 |
+
pop(stack, a, b); \
|
| 469 |
+
push(stack, int_op); \
|
| 470 |
+
}, \
|
| 471 |
+
aliasAnalysisFromSchema()), \
|
| 472 |
+
OperatorGeneratorArgs( \
|
| 473 |
+
TORCH_SELECTIVE_SCHEMA( \
|
| 474 |
+
#aten_op ".float(float a, float b) -> " #float_result), \
|
| 475 |
+
[](Stack& stack) { \
|
| 476 |
+
double a, b; \
|
| 477 |
+
pop(stack, a, b); \
|
| 478 |
+
push(stack, float_op); \
|
| 479 |
+
}, \
|
| 480 |
+
aliasAnalysisFromSchema())
|
| 481 |
+
|
| 482 |
+
#define DEFINE_INT_FLOAT_OP(aten_op, op, result) \
|
| 483 |
+
OperatorGeneratorArgs( \
|
| 484 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op \
|
| 485 |
+
".int_float(int a, float b) -> " #result), \
|
| 486 |
+
[](Stack& stack) { \
|
| 487 |
+
int64_t a; \
|
| 488 |
+
double b; \
|
| 489 |
+
pop(stack, a, b); \
|
| 490 |
+
push(stack, op); \
|
| 491 |
+
}, \
|
| 492 |
+
aliasAnalysisFromSchema()), \
|
| 493 |
+
OperatorGeneratorArgs( \
|
| 494 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op \
|
| 495 |
+
".float_int(float a, int b) -> " #result), \
|
| 496 |
+
[](Stack& stack) { \
|
| 497 |
+
double a; \
|
| 498 |
+
int64_t b; \
|
| 499 |
+
pop(stack, a, b); \
|
| 500 |
+
push(stack, op); \
|
| 501 |
+
}, \
|
| 502 |
+
aliasAnalysisFromSchema())
|
| 503 |
+
|
| 504 |
+
#define DEFINE_INT_OP(aten_op, op) \
|
| 505 |
+
OperatorGeneratorArgs( \
|
| 506 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".int(int a, int b) -> int"), \
|
| 507 |
+
[](Stack& stack) { \
|
| 508 |
+
int64_t a, b; \
|
| 509 |
+
pop(stack, a, b); \
|
| 510 |
+
push(stack, op); /* NOLINT(hicpp-signed-bitwise) */ \
|
| 511 |
+
}, \
|
| 512 |
+
aliasAnalysisFromSchema())
|
| 513 |
+
|
| 514 |
+
#define DEFINE_STR_CMP_OP(aten_op, op) \
|
| 515 |
+
OperatorGeneratorArgs( \
|
| 516 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".str(str a, str b) -> bool"), \
|
| 517 |
+
[](Stack& stack) { \
|
| 518 |
+
auto b = pop(stack).toStringRef(); \
|
| 519 |
+
auto a = pop(stack).toStringRef(); \
|
| 520 |
+
push(stack, op); \
|
| 521 |
+
}, \
|
| 522 |
+
aliasAnalysisFromSchema())
|
| 523 |
+
|
| 524 |
+
// define a primitive op over Scalar operands.
|
| 525 |
+
// it's necessary to register this overload following
|
| 526 |
+
// int/float variations to avoid trapping Scalar args
|
| 527 |
+
// in unintended implicit conversions
|
| 528 |
+
#define DEFINE_SCALAR_BINARY_OP_AVOID_COLLISION_GENERIC( \
|
| 529 |
+
aten_op, int_op, float_op, result, string_val) \
|
| 530 |
+
OperatorGeneratorArgs( \
|
| 531 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op string_val \
|
| 532 |
+
"(Scalar a, Scalar b) -> " #result), \
|
| 533 |
+
[](Stack& stack) { \
|
| 534 |
+
IValue x, y; \
|
| 535 |
+
pop(stack, x, y); \
|
| 536 |
+
if (x.isDouble()) { \
|
| 537 |
+
if (y.isDouble()) { \
|
| 538 |
+
double a = x.toDouble(); \
|
| 539 |
+
double b = y.toDouble(); \
|
| 540 |
+
push(stack, float_op); \
|
| 541 |
+
} else { \
|
| 542 |
+
double a = x.toDouble(); \
|
| 543 |
+
int64_t b = y.toInt(); \
|
| 544 |
+
push(stack, float_op); \
|
| 545 |
+
} \
|
| 546 |
+
} else { \
|
| 547 |
+
if (y.isDouble()) { \
|
| 548 |
+
int64_t a = x.toInt(); \
|
| 549 |
+
double b = y.toDouble(); \
|
| 550 |
+
push(stack, float_op); \
|
| 551 |
+
} else { \
|
| 552 |
+
int64_t a = x.toInt(); \
|
| 553 |
+
int64_t b = y.toInt(); \
|
| 554 |
+
push(stack, int_op); \
|
| 555 |
+
} \
|
| 556 |
+
} \
|
| 557 |
+
}, \
|
| 558 |
+
aliasAnalysisFromSchema())
|
| 559 |
+
|
| 560 |
+
#define DEFINE_SCALAR_BINARY_OP(aten_op, int_op, float_op, result) \
|
| 561 |
+
DEFINE_SCALAR_BINARY_OP_AVOID_COLLISION_GENERIC( \
|
| 562 |
+
aten_op, int_op, float_op, result, "")
|
| 563 |
+
|
| 564 |
+
#define DEFINE_SCALAR_BINARY_OP_AVOID_COLLISION( \
|
| 565 |
+
aten_op, int_op, float_op, result) \
|
| 566 |
+
DEFINE_SCALAR_BINARY_OP_AVOID_COLLISION_GENERIC( \
|
| 567 |
+
aten_op, int_op, float_op, result, ".Scalar_Scalar")
|
| 568 |
+
|
| 569 |
+
#define DEFINE_BINARY_OP(aten_op, op) \
|
| 570 |
+
DEFINE_GENERIC_OP(aten_op, op, op, int, float), \
|
| 571 |
+
DEFINE_INT_FLOAT_OP(aten_op, op, float), \
|
| 572 |
+
DEFINE_SCALAR_BINARY_OP(aten_op, op, op, Scalar)
|
| 573 |
+
|
| 574 |
+
#define DEFINE_BINARY_FLOAT_OP(aten_op, op) \
|
| 575 |
+
DEFINE_GENERIC_OP(aten_op, op, op, float, float), \
|
| 576 |
+
DEFINE_INT_FLOAT_OP(aten_op, op, float), \
|
| 577 |
+
DEFINE_SCALAR_BINARY_OP(aten_op, op, op, float)
|
| 578 |
+
|
| 579 |
+
#define DEFINE_COMPARISON_OP(aten_op, op) \
|
| 580 |
+
DEFINE_GENERIC_OP(aten_op, op, op, bool, bool), \
|
| 581 |
+
DEFINE_INT_FLOAT_OP(aten_op, op, bool), \
|
| 582 |
+
DEFINE_SCALAR_BINARY_OP(aten_op, op, op, bool), \
|
| 583 |
+
DEFINE_STR_CMP_OP(aten_op, op)
|
| 584 |
+
|
| 585 |
+
#define DEFINE_UNARY_INT_OP(aten_op, op, result) \
|
| 586 |
+
OperatorGeneratorArgs( \
|
| 587 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".int(int a) -> " #result), \
|
| 588 |
+
[](Stack& stack) { \
|
| 589 |
+
int64_t a; \
|
| 590 |
+
pop(stack, a); \
|
| 591 |
+
push(stack, op); \
|
| 592 |
+
}, \
|
| 593 |
+
aliasAnalysisFromSchema())
|
| 594 |
+
|
| 595 |
+
#define DEFINE_UNARY_FLOAT_OP(aten_op, op, result) \
|
| 596 |
+
OperatorGeneratorArgs( \
|
| 597 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".float(float a) -> " #result), \
|
| 598 |
+
[](Stack& stack) { \
|
| 599 |
+
double a; \
|
| 600 |
+
pop(stack, a); \
|
| 601 |
+
push(stack, op); \
|
| 602 |
+
}, \
|
| 603 |
+
aliasAnalysisFromSchema())
|
| 604 |
+
|
| 605 |
+
#define DEFINE_UNARY_OP(aten_op, op, int_result, float_result) \
|
| 606 |
+
DEFINE_UNARY_INT_OP(aten_op, op, int_result), \
|
| 607 |
+
DEFINE_UNARY_FLOAT_OP(aten_op, op, float_result), \
|
| 608 |
+
OperatorGeneratorArgs( \
|
| 609 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".Scalar(Scalar a) -> Scalar"), \
|
| 610 |
+
[](Stack& stack) { \
|
| 611 |
+
IValue x; \
|
| 612 |
+
pop(stack, x); \
|
| 613 |
+
if (x.isDouble()) { \
|
| 614 |
+
double a = x.toDouble(); \
|
| 615 |
+
push(stack, static_cast<float_result>(op)); \
|
| 616 |
+
} else { \
|
| 617 |
+
int64_t a = x.toInt(); \
|
| 618 |
+
push(stack, static_cast<int_result>(op)); \
|
| 619 |
+
} \
|
| 620 |
+
}, \
|
| 621 |
+
aliasAnalysisFromSchema())
|
| 622 |
+
#define DEFINE_BOOL_OP(aten_op, op) \
|
| 623 |
+
OperatorGeneratorArgs( \
|
| 624 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".bool(bool a, bool b) -> bool"), \
|
| 625 |
+
[](Stack& stack) { \
|
| 626 |
+
bool a, b; \
|
| 627 |
+
pop(stack, a, b); \
|
| 628 |
+
push(stack, op); \
|
| 629 |
+
}, \
|
| 630 |
+
aliasAnalysisFromSchema())
|
| 631 |
+
#define DEFINE_STRING_OP(op_name, string_op, result) \
|
| 632 |
+
OperatorGeneratorArgs( \
|
| 633 |
+
TORCH_SELECTIVE_SCHEMA(#op_name ".str(str a, str b) ->" #result), \
|
| 634 |
+
[](Stack& stack) { \
|
| 635 |
+
auto b = pop(stack).toStringRef(); \
|
| 636 |
+
auto a = pop(stack).toStringRef(); \
|
| 637 |
+
push(stack, string_op); \
|
| 638 |
+
}, \
|
| 639 |
+
aliasAnalysisFromSchema())
|
| 640 |
+
|
| 641 |
+
//-----------------------------------------------------------------------------
|
| 642 |
+
//-----------------------------------------------------------------------------
|
| 643 |
+
//-----------------------------------------------------------------------------
|
| 644 |
+
//-----------------------------------------------------------------------------
|
| 645 |
+
#define DEFINE_UNARY_COMPLEX_OP(aten_op, op, result) \
|
| 646 |
+
OperatorGeneratorArgs( \
|
| 647 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".complex(complex a) -> " #result), \
|
| 648 |
+
[](Stack& stack) { \
|
| 649 |
+
c10::complex<double> a; \
|
| 650 |
+
pop(stack, a); \
|
| 651 |
+
push(stack, op); \
|
| 652 |
+
}, \
|
| 653 |
+
aliasAnalysisFromSchema())
|
| 654 |
+
|
| 655 |
+
// Some complex unary ops (like abs, angle) return real valued output, but most
|
| 656 |
+
// other unary ops return complex valued output. So, this macro is used in the
|
| 657 |
+
// former case where we can explicitly pass complex_result_cast argument, which
|
| 658 |
+
// is set to c10::complex<float> in the macro `DEFINE_UNARY_OP_WITH_COMPLEX`
|
| 659 |
+
// defined below.
|
| 660 |
+
#define DEFINE_UNARY_OP_WITH_COMPLEX_CAST( \
|
| 661 |
+
aten_op, \
|
| 662 |
+
op, \
|
| 663 |
+
int_result, \
|
| 664 |
+
float_result, \
|
| 665 |
+
complex_result, \
|
| 666 |
+
complex_result_cast) \
|
| 667 |
+
DEFINE_UNARY_INT_OP(aten_op, op, int_result), \
|
| 668 |
+
DEFINE_UNARY_FLOAT_OP(aten_op, op, float_result), \
|
| 669 |
+
DEFINE_UNARY_COMPLEX_OP(aten_op, op, complex_result), \
|
| 670 |
+
OperatorGeneratorArgs( \
|
| 671 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".Scalar(Scalar a) -> Scalar"), \
|
| 672 |
+
[](Stack& stack) { \
|
| 673 |
+
IValue x; \
|
| 674 |
+
pop(stack, x); \
|
| 675 |
+
if (x.isDouble()) { \
|
| 676 |
+
double a = x.toDouble(); \
|
| 677 |
+
push(stack, static_cast<float_result>(op)); \
|
| 678 |
+
} else if (x.isComplexDouble()) { \
|
| 679 |
+
c10::complex<double> a = x.toComplexDouble(); \
|
| 680 |
+
push(stack, static_cast<complex_result_cast>(op)); \
|
| 681 |
+
} else { \
|
| 682 |
+
int64_t a = x.toInt(); \
|
| 683 |
+
push(stack, static_cast<int_result>(op)); \
|
| 684 |
+
} \
|
| 685 |
+
}, \
|
| 686 |
+
aliasAnalysisFromSchema())
|
| 687 |
+
|
| 688 |
+
#define DEFINE_UNARY_OP_WITH_COMPLEX(aten_op, op, int_result, float_result) \
|
| 689 |
+
DEFINE_UNARY_OP_WITH_COMPLEX_CAST( \
|
| 690 |
+
aten_op, op, int_result, float_result, complex, c10::complex<double>)
|
| 691 |
+
|
| 692 |
+
#define DEFINE_GENERIC_OP_WITH_COMPLEX( \
|
| 693 |
+
aten_op, \
|
| 694 |
+
int_op, \
|
| 695 |
+
float_op, \
|
| 696 |
+
complex_op, \
|
| 697 |
+
int_result, \
|
| 698 |
+
float_result, \
|
| 699 |
+
complex_result) \
|
| 700 |
+
OperatorGeneratorArgs( \
|
| 701 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op ".int(int a, int b) -> " #int_result), \
|
| 702 |
+
[](Stack& stack) { \
|
| 703 |
+
int64_t a, b; \
|
| 704 |
+
pop(stack, a, b); \
|
| 705 |
+
push(stack, int_op); \
|
| 706 |
+
}, \
|
| 707 |
+
aliasAnalysisFromSchema()), \
|
| 708 |
+
OperatorGeneratorArgs( \
|
| 709 |
+
TORCH_SELECTIVE_SCHEMA( \
|
| 710 |
+
#aten_op ".complex(complex a, complex b) -> " #complex_result), \
|
| 711 |
+
[](Stack& stack) { \
|
| 712 |
+
c10::complex<double> a, b; \
|
| 713 |
+
pop(stack, a, b); \
|
| 714 |
+
push(stack, complex_op); \
|
| 715 |
+
}, \
|
| 716 |
+
aliasAnalysisFromSchema()), \
|
| 717 |
+
OperatorGeneratorArgs( \
|
| 718 |
+
TORCH_SELECTIVE_SCHEMA( \
|
| 719 |
+
#aten_op ".float(float a, float b) -> " #float_result), \
|
| 720 |
+
[](Stack& stack) { \
|
| 721 |
+
double a, b; \
|
| 722 |
+
pop(stack, a, b); \
|
| 723 |
+
push(stack, float_op); \
|
| 724 |
+
}, \
|
| 725 |
+
aliasAnalysisFromSchema())
|
| 726 |
+
|
| 727 |
+
#define DEFINE_INT_COMPLEX_OP(aten_op, op, result) \
|
| 728 |
+
OperatorGeneratorArgs( \
|
| 729 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op \
|
| 730 |
+
".int_complex(int a, complex b) -> " #result), \
|
| 731 |
+
[](Stack& stack) { \
|
| 732 |
+
int64_t a; \
|
| 733 |
+
c10::complex<double> b; \
|
| 734 |
+
pop(stack, a, b); \
|
| 735 |
+
push(stack, op); \
|
| 736 |
+
}, \
|
| 737 |
+
aliasAnalysisFromSchema()), \
|
| 738 |
+
OperatorGeneratorArgs( \
|
| 739 |
+
TORCH_SELECTIVE_SCHEMA( \
|
| 740 |
+
#aten_op ".complex_int(complex a, int b) -> " #result), \
|
| 741 |
+
[](Stack& stack) { \
|
| 742 |
+
c10::complex<double> a; \
|
| 743 |
+
int64_t b; \
|
| 744 |
+
pop(stack, a, b); \
|
| 745 |
+
push(stack, op); \
|
| 746 |
+
}, \
|
| 747 |
+
aliasAnalysisFromSchema())
|
| 748 |
+
|
| 749 |
+
#define DEFINE_FLOAT_COMPLEX_OP(aten_op, op, result) \
|
| 750 |
+
OperatorGeneratorArgs( \
|
| 751 |
+
TORCH_SELECTIVE_SCHEMA( \
|
| 752 |
+
#aten_op ".float_complex(float a, complex b) -> " #result), \
|
| 753 |
+
[](Stack& stack) { \
|
| 754 |
+
double a; \
|
| 755 |
+
c10::complex<double> b; \
|
| 756 |
+
pop(stack, a, b); \
|
| 757 |
+
push(stack, op); \
|
| 758 |
+
}, \
|
| 759 |
+
aliasAnalysisFromSchema()), \
|
| 760 |
+
OperatorGeneratorArgs( \
|
| 761 |
+
TORCH_SELECTIVE_SCHEMA( \
|
| 762 |
+
#aten_op ".complex_float(complex a, float b) -> " #result), \
|
| 763 |
+
[](Stack& stack) { \
|
| 764 |
+
c10::complex<double> a; \
|
| 765 |
+
double b; \
|
| 766 |
+
pop(stack, a, b); \
|
| 767 |
+
push(stack, op); \
|
| 768 |
+
}, \
|
| 769 |
+
aliasAnalysisFromSchema())
|
| 770 |
+
|
| 771 |
+
#define DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX_AVOID_COLLISION_GENERIC( \
|
| 772 |
+
aten_op, int_op, float_op, complex_op, result, string_val) \
|
| 773 |
+
OperatorGeneratorArgs( \
|
| 774 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op string_val \
|
| 775 |
+
"(Scalar a, Scalar b) -> " #result), \
|
| 776 |
+
[](Stack& stack) { \
|
| 777 |
+
IValue x, y; \
|
| 778 |
+
pop(stack, x, y); \
|
| 779 |
+
if (x.isComplexDouble()) { \
|
| 780 |
+
c10::complex<double> a = x.toComplexDouble(); \
|
| 781 |
+
if (y.isComplexDouble()) { \
|
| 782 |
+
c10::complex<double> b = y.toComplexDouble(); \
|
| 783 |
+
push(stack, complex_op); \
|
| 784 |
+
} else if (y.isDouble()) { \
|
| 785 |
+
double b = y.toDouble(); \
|
| 786 |
+
push(stack, complex_op); \
|
| 787 |
+
} else { \
|
| 788 |
+
int64_t b = y.toInt(); \
|
| 789 |
+
push(stack, complex_op); \
|
| 790 |
+
} \
|
| 791 |
+
} else if (x.isDouble()) { \
|
| 792 |
+
double a = x.toDouble(); \
|
| 793 |
+
if (y.isComplexDouble()) { \
|
| 794 |
+
c10::complex<double> b = y.toComplexDouble(); \
|
| 795 |
+
push(stack, complex_op); \
|
| 796 |
+
} else if (y.isDouble()) { \
|
| 797 |
+
double b = y.toDouble(); \
|
| 798 |
+
push(stack, float_op); \
|
| 799 |
+
} else { \
|
| 800 |
+
int64_t b = y.toInt(); \
|
| 801 |
+
push(stack, float_op); \
|
| 802 |
+
} \
|
| 803 |
+
} else { \
|
| 804 |
+
int64_t a = x.toInt(); \
|
| 805 |
+
if (y.isComplexDouble()) { \
|
| 806 |
+
c10::complex<double> b = y.toComplexDouble(); \
|
| 807 |
+
push(stack, complex_op); \
|
| 808 |
+
} else if (y.isDouble()) { \
|
| 809 |
+
double b = y.toDouble(); \
|
| 810 |
+
push(stack, float_op); \
|
| 811 |
+
} else { \
|
| 812 |
+
int64_t b = y.toInt(); \
|
| 813 |
+
push(stack, int_op); \
|
| 814 |
+
} \
|
| 815 |
+
} \
|
| 816 |
+
}, \
|
| 817 |
+
aliasAnalysisFromSchema())
|
| 818 |
+
|
| 819 |
+
#define DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX_WITHOUT_INT_COMPLEX_PAIR( \
|
| 820 |
+
aten_op, int_op, float_op, complex_op, result) \
|
| 821 |
+
OperatorGeneratorArgs( \
|
| 822 |
+
TORCH_SELECTIVE_SCHEMA(#aten_op "(Scalar a, Scalar b) -> " #result), \
|
| 823 |
+
[](Stack& stack) { \
|
| 824 |
+
IValue x, y; \
|
| 825 |
+
pop(stack, x, y); \
|
| 826 |
+
if (x.isComplexDouble()) { \
|
| 827 |
+
c10::complex<double> a = x.toComplexDouble(); \
|
| 828 |
+
if (y.isComplexDouble()) { \
|
| 829 |
+
c10::complex<double> b = y.toComplexDouble(); \
|
| 830 |
+
push(stack, complex_op); \
|
| 831 |
+
} else if (y.isDouble()) { \
|
| 832 |
+
double b = y.toDouble(); \
|
| 833 |
+
push(stack, complex_op); \
|
| 834 |
+
} \
|
| 835 |
+
} else if (x.isDouble()) { \
|
| 836 |
+
double a = x.toDouble(); \
|
| 837 |
+
if (y.isComplexDouble()) { \
|
| 838 |
+
c10::complex<double> b = y.toComplexDouble(); \
|
| 839 |
+
push(stack, complex_op); \
|
| 840 |
+
} else if (y.isDouble()) { \
|
| 841 |
+
double b = y.toDouble(); \
|
| 842 |
+
push(stack, float_op); \
|
| 843 |
+
} else { \
|
| 844 |
+
int64_t b = y.toInt(); \
|
| 845 |
+
push(stack, float_op); \
|
| 846 |
+
} \
|
| 847 |
+
} else { \
|
| 848 |
+
int64_t a = x.toInt(); \
|
| 849 |
+
if (y.isDouble()) { \
|
| 850 |
+
double b = y.toDouble(); \
|
| 851 |
+
push(stack, float_op); \
|
| 852 |
+
} else if (y.isInt()) { \
|
| 853 |
+
int64_t b = y.toInt(); \
|
| 854 |
+
push(stack, int_op); \
|
| 855 |
+
} \
|
| 856 |
+
} \
|
| 857 |
+
}, \
|
| 858 |
+
aliasAnalysisFromSchema())
|
| 859 |
+
|
| 860 |
+
#define DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX( \
|
| 861 |
+
aten_op, int_op, float_op, complex_op, result) \
|
| 862 |
+
DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX_AVOID_COLLISION_GENERIC( \
|
| 863 |
+
aten_op, int_op, float_op, complex_op, result, "")
|
| 864 |
+
|
| 865 |
+
#define DEFINE_BINARY_OP_WITH_COMPLEX(aten_op, op) \
|
| 866 |
+
DEFINE_GENERIC_OP_WITH_COMPLEX(aten_op, op, op, op, int, float, complex), \
|
| 867 |
+
DEFINE_INT_COMPLEX_OP(aten_op, op, complex), \
|
| 868 |
+
DEFINE_FLOAT_COMPLEX_OP(aten_op, op, complex), \
|
| 869 |
+
DEFINE_INT_FLOAT_OP(aten_op, op, float), \
|
| 870 |
+
DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX(aten_op, op, op, op, Scalar)
|
| 871 |
+
|
| 872 |
+
#define DEFINE_COMPARISON_OP_WITH_COMPLEX(aten_op, op) \
|
| 873 |
+
DEFINE_GENERIC_OP_WITH_COMPLEX(aten_op, op, op, op, bool, bool, bool), \
|
| 874 |
+
DEFINE_INT_FLOAT_OP(aten_op, op, bool), \
|
| 875 |
+
DEFINE_FLOAT_COMPLEX_OP(aten_op, op, bool), \
|
| 876 |
+
DEFINE_SCALAR_BINARY_OP_WITH_COMPLEX_WITHOUT_INT_COMPLEX_PAIR( \
|
| 877 |
+
aten_op, op, op, op, bool), \
|
| 878 |
+
DEFINE_STR_CMP_OP(aten_op, op)
|
| 879 |
+
|
| 880 |
+
TORCH_API at::Generator make_generator_for_device(
|
| 881 |
+
c10::Device device,
|
| 882 |
+
std::optional<int64_t> seed = std::nullopt);
|
| 883 |
+
|
| 884 |
+
} // namespace torch::jit
|
| 885 |
+
|
| 886 |
+
#else
|
| 887 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 888 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/script_profile.h
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <chrono>
|
| 5 |
+
#include <map>
|
| 6 |
+
#include <string>
|
| 7 |
+
|
| 8 |
+
#include <ATen/core/ivalue.h>
|
| 9 |
+
#include <c10/macros/Macros.h>
|
| 10 |
+
#include <torch/csrc/jit/frontend/source_ref.h>
|
| 11 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 12 |
+
|
| 13 |
+
namespace torch::jit {
|
| 14 |
+
namespace profiling {
|
| 15 |
+
|
| 16 |
+
struct Datapoint {
|
| 17 |
+
using Timepoint = std::chrono::time_point<std::chrono::steady_clock>;
|
| 18 |
+
SourceRange sourceRange;
|
| 19 |
+
Timepoint start;
|
| 20 |
+
Timepoint end;
|
| 21 |
+
|
| 22 |
+
explicit Datapoint(SourceRange sr)
|
| 23 |
+
: sourceRange(std::move(sr)), start(std::chrono::steady_clock::now()) {}
|
| 24 |
+
};
|
| 25 |
+
|
| 26 |
+
class TORCH_API InstructionSpan {
|
| 27 |
+
public:
|
| 28 |
+
explicit InstructionSpan(Node& /*node*/);
|
| 29 |
+
~InstructionSpan();
|
| 30 |
+
InstructionSpan(InstructionSpan&&) = delete;
|
| 31 |
+
InstructionSpan& operator=(InstructionSpan&&) = delete;
|
| 32 |
+
|
| 33 |
+
private:
|
| 34 |
+
std::unique_ptr<Datapoint> datapoint_;
|
| 35 |
+
};
|
| 36 |
+
|
| 37 |
+
bool TORCH_API isProfilingOngoing();
|
| 38 |
+
|
| 39 |
+
} // namespace profiling
|
| 40 |
+
|
| 41 |
+
struct TORCH_API InstructionStats : public CustomClassHolder {
|
| 42 |
+
int64_t count{0};
|
| 43 |
+
std::chrono::nanoseconds duration{0};
|
| 44 |
+
};
|
| 45 |
+
|
| 46 |
+
class TORCH_API SourceStats : public CustomClassHolder {
|
| 47 |
+
public:
|
| 48 |
+
using LineMap = c10::Dict<int64_t, c10::intrusive_ptr<InstructionStats>>;
|
| 49 |
+
|
| 50 |
+
SourceStats(SourceRef source, const LineMap& lineMap)
|
| 51 |
+
: source_(std::move(source)), lineMap_(lineMap) {}
|
| 52 |
+
|
| 53 |
+
const SourceRef& getSourceRef() const {
|
| 54 |
+
return source_;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
const LineMap& getLineMap() const {
|
| 58 |
+
return lineMap_;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
private:
|
| 62 |
+
SourceRef source_;
|
| 63 |
+
LineMap lineMap_;
|
| 64 |
+
};
|
| 65 |
+
|
| 66 |
+
/**
|
| 67 |
+
* ScriptProfile is an underlying C++ implementation for TorchScript profiling.
|
| 68 |
+
* The profiling section is specified by calling enable() and disable():
|
| 69 |
+
*
|
| 70 |
+
* ...
|
| 71 |
+
* scriptProfile.enable();
|
| 72 |
+
* ...
|
| 73 |
+
* (scripts)
|
| 74 |
+
* ...
|
| 75 |
+
* scriptProfile.disable();
|
| 76 |
+
* ...
|
| 77 |
+
*
|
| 78 |
+
* NOTE: you cannot attach the profiler while the script is running.
|
| 79 |
+
*
|
| 80 |
+
* To retrieve collected runtime data, users may call dumpStats() and do
|
| 81 |
+
* arbitrary filtering on the data they want. Note that dumpStats() should
|
| 82 |
+
* not be called inside a profiling section.
|
| 83 |
+
* In general, stats are aggregated per source function body, and then by line
|
| 84 |
+
* number.
|
| 85 |
+
*/
|
| 86 |
+
class TORCH_API ScriptProfile : public CustomClassHolder {
|
| 87 |
+
// Aggregates datapoints by function source id, then by line number.
|
| 88 |
+
using LineMap = std::map<int64_t, InstructionStats>;
|
| 89 |
+
using SourceMap = std::map<SourceRef, LineMap, std::less<>>;
|
| 90 |
+
|
| 91 |
+
public:
|
| 92 |
+
void enable();
|
| 93 |
+
void disable();
|
| 94 |
+
const SourceMap& dumpStats();
|
| 95 |
+
void addDatapoint(std::shared_ptr<profiling::Datapoint> /*datapoint*/);
|
| 96 |
+
~ScriptProfile() override;
|
| 97 |
+
|
| 98 |
+
private:
|
| 99 |
+
bool enabled_{false};
|
| 100 |
+
std::vector<std::shared_ptr<profiling::Datapoint>> datapoints_;
|
| 101 |
+
SourceMap sourceMap_;
|
| 102 |
+
};
|
| 103 |
+
|
| 104 |
+
} // namespace torch::jit
|
| 105 |
+
|
| 106 |
+
#else
|
| 107 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 108 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/serialized_shape_function_registry.h
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/Export.h>
|
| 5 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 6 |
+
|
| 7 |
+
namespace torch::jit {
|
| 8 |
+
|
| 9 |
+
TORCH_API const std::string& GetSerializedShapeFunctions();
|
| 10 |
+
|
| 11 |
+
TORCH_API const OperatorMap<std::string>& GetShapeFunctionMappings();
|
| 12 |
+
|
| 13 |
+
TORCH_API const OperatorMap<std::pair<std::string, std::string>>&
|
| 14 |
+
GetBoundedShapeMappings();
|
| 15 |
+
|
| 16 |
+
} // namespace torch::jit
|
| 17 |
+
|
| 18 |
+
#else
|
| 19 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 20 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/shape_function_registry.h
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/Export.h>
|
| 5 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 6 |
+
|
| 7 |
+
namespace torch::jit {
|
| 8 |
+
|
| 9 |
+
TORCH_API const std::string& GetSerializedFuncs();
|
| 10 |
+
|
| 11 |
+
TORCH_API const OperatorMap<std::string>& GetFuncMapping();
|
| 12 |
+
|
| 13 |
+
} // namespace torch::jit
|
| 14 |
+
|
| 15 |
+
#else
|
| 16 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 17 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/simple_graph_executor_impl.h
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <c10/util/Flags.h>
|
| 4 |
+
#include <torch/csrc/jit/api/module.h>
|
| 5 |
+
#include <torch/csrc/jit/runtime/graph_executor_impl.h>
|
| 6 |
+
|
| 7 |
+
namespace torch::jit {
|
| 8 |
+
|
| 9 |
+
struct TORCH_API SimpleGraphExecutorImpl : public GraphExecutorImplBase {
|
| 10 |
+
SimpleGraphExecutorImpl(
|
| 11 |
+
const std::shared_ptr<Graph>& graph,
|
| 12 |
+
std::string function_name);
|
| 13 |
+
|
| 14 |
+
const ExecutionPlan& getPlanFor(
|
| 15 |
+
Stack& stack,
|
| 16 |
+
std::optional<size_t> remaining_bailout_depth) override;
|
| 17 |
+
const ExecutionPlan& getInputIndependentPlan() override;
|
| 18 |
+
GraphExecutorState getDebugState() override;
|
| 19 |
+
~SimpleGraphExecutorImpl() override = default;
|
| 20 |
+
|
| 21 |
+
private:
|
| 22 |
+
const ExecutionPlan& getInputIndependentPlanImpl();
|
| 23 |
+
|
| 24 |
+
std::optional<ExecutionPlan> execution_plan_;
|
| 25 |
+
};
|
| 26 |
+
|
| 27 |
+
} // namespace torch::jit
|
| 28 |
+
|
| 29 |
+
#else
|
| 30 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 31 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/slice_indices_adjust.h
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/Export.h>
|
| 5 |
+
#include <cstddef>
|
| 6 |
+
#include <cstdint>
|
| 7 |
+
|
| 8 |
+
namespace torch::jit {
|
| 9 |
+
|
| 10 |
+
// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
| 11 |
+
// 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software
|
| 12 |
+
// Foundation; All Rights Reserved
|
| 13 |
+
//
|
| 14 |
+
// Stolen (with appropriate modifications) by @agolynski
|
| 15 |
+
// (https://github.com/pytorch/pytorch/pull/33019) from cpython repo
|
| 16 |
+
// Objects/sliceobject.c with comment: this is harder to get right than you
|
| 17 |
+
// might think
|
| 18 |
+
//
|
| 19 |
+
// This adjusts indexes according to python list semantics and returns number
|
| 20 |
+
// of elements in the resulting list.
|
| 21 |
+
TORCH_API int64_t slice_indices_adjust(
|
| 22 |
+
int64_t length,
|
| 23 |
+
int64_t* start,
|
| 24 |
+
int64_t* stop,
|
| 25 |
+
int64_t step);
|
| 26 |
+
|
| 27 |
+
} // namespace torch::jit
|
| 28 |
+
|
| 29 |
+
#else
|
| 30 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 31 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/ProcessedNodeInputs.h
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <cstddef>
|
| 5 |
+
#include <cstdint>
|
| 6 |
+
#include <cstring>
|
| 7 |
+
|
| 8 |
+
#include <memory>
|
| 9 |
+
|
| 10 |
+
#include <c10/macros/Macros.h>
|
| 11 |
+
#include <c10/util/Logging.h>
|
| 12 |
+
|
| 13 |
+
/**
|
| 14 |
+
* Packed representation of input indices for ProcessedNode.
|
| 15 |
+
*/
|
| 16 |
+
class ProcessedNodeInputs {
|
| 17 |
+
private:
|
| 18 |
+
// This keeps the size usage for inputs + outputs down to 16 bytes;
|
| 19 |
+
// we use 12 bytes, and then two 2-byte integers are used to store
|
| 20 |
+
// the outputs.
|
| 21 |
+
static constexpr size_t kMaxInlineInputs = 5;
|
| 22 |
+
|
| 23 |
+
public:
|
| 24 |
+
ProcessedNodeInputs() : ProcessedNodeInputs(0) {}
|
| 25 |
+
|
| 26 |
+
explicit ProcessedNodeInputs(size_t size) {
|
| 27 |
+
TORCH_DCHECK_LT(size, (1 << 16));
|
| 28 |
+
if (size <= kMaxInlineInputs) {
|
| 29 |
+
repr_.inline_repr_.size = size;
|
| 30 |
+
} else {
|
| 31 |
+
new (&repr_.outline_repr_) HeapArrayPtr(size);
|
| 32 |
+
}
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
uint16_t operator[](uint16_t idx) const {
|
| 36 |
+
// NOLINTNEXTLINE(*const-cast*)
|
| 37 |
+
return (*const_cast<ProcessedNodeInputs*>(this))[idx];
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
uint16_t& operator[](uint16_t idx) {
|
| 41 |
+
if (C10_LIKELY(repr_.is_inline())) {
|
| 42 |
+
TORCH_DCHECK_LT(idx, repr_.inline_repr_.size);
|
| 43 |
+
return repr_.inline_repr_.inputs[idx];
|
| 44 |
+
} else {
|
| 45 |
+
return repr_.outline_repr_[idx];
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
[[nodiscard]] uint16_t size() const {
|
| 50 |
+
if (C10_LIKELY(repr_.is_inline())) {
|
| 51 |
+
return repr_.inline_repr_.size;
|
| 52 |
+
} else {
|
| 53 |
+
return repr_.outline_repr_.size();
|
| 54 |
+
}
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
[[nodiscard]] bool empty() const {
|
| 58 |
+
return size() == 0;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
private:
|
| 62 |
+
class HeapArrayPtr {
|
| 63 |
+
public:
|
| 64 |
+
HeapArrayPtr() = default;
|
| 65 |
+
~HeapArrayPtr() = default;
|
| 66 |
+
|
| 67 |
+
explicit HeapArrayPtr(uint16_t size) : array_(alloc(size)) {}
|
| 68 |
+
|
| 69 |
+
HeapArrayPtr(const HeapArrayPtr& rhs) : array_(alloc(rhs.size())) {
|
| 70 |
+
if (rhs.array_) {
|
| 71 |
+
std::memcpy(
|
| 72 |
+
array_.get(),
|
| 73 |
+
rhs.array_.get(),
|
| 74 |
+
(rhs.size() + 1) * sizeof(uint16_t));
|
| 75 |
+
}
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
HeapArrayPtr& operator=(const HeapArrayPtr& rhs) {
|
| 79 |
+
if (&rhs == this) {
|
| 80 |
+
return *this;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
if (size() != rhs.size()) {
|
| 84 |
+
array_ = alloc(rhs.size());
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
if (rhs.array_) {
|
| 88 |
+
std::memcpy(
|
| 89 |
+
array_.get(),
|
| 90 |
+
rhs.array_.get(),
|
| 91 |
+
(rhs.size() + 1) * sizeof(uint16_t));
|
| 92 |
+
}
|
| 93 |
+
return *this;
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
HeapArrayPtr(HeapArrayPtr&&) noexcept = default;
|
| 97 |
+
HeapArrayPtr& operator=(HeapArrayPtr&&) noexcept = default;
|
| 98 |
+
|
| 99 |
+
[[nodiscard]] bool empty() const {
|
| 100 |
+
return size() != 0;
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
[[nodiscard]] uint16_t size() const {
|
| 104 |
+
return array_ ? array_[0] : 0;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
uint16_t operator[](uint16_t idx) const {
|
| 108 |
+
TORCH_DCHECK_LT(idx, size());
|
| 109 |
+
return array_[idx + 1];
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
uint16_t& operator[](uint16_t idx) {
|
| 113 |
+
TORCH_DCHECK_LT(idx, size());
|
| 114 |
+
return array_[idx + 1];
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
private:
|
| 118 |
+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
| 119 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
|
| 120 |
+
std::unique_ptr<uint16_t[]> array_;
|
| 121 |
+
|
| 122 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
|
| 123 |
+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
| 124 |
+
static std::unique_ptr<uint16_t[]> alloc(uint16_t num_elts) {
|
| 125 |
+
if (num_elts) {
|
| 126 |
+
auto result = std::make_unique<uint16_t[]>(num_elts + 1);
|
| 127 |
+
result[0] = num_elts;
|
| 128 |
+
return result;
|
| 129 |
+
} else {
|
| 130 |
+
return nullptr;
|
| 131 |
+
}
|
| 132 |
+
}
|
| 133 |
+
};
|
| 134 |
+
|
| 135 |
+
// We want ProcessedNode to be able to pack two more `uint16_t`
|
| 136 |
+
// fields after its ProcessedNodeInputs, and we'll end up being
|
| 137 |
+
// aligned to an 8-byte boundary anyway. We could avoid this pragma
|
| 138 |
+
// at the cost of having to move ProcessedNode::outputs_offset_ and
|
| 139 |
+
// ProcessedNode::num_outputs_ into this class, which would be
|
| 140 |
+
// awkward.
|
| 141 |
+
#pragma pack(push, 2)
|
| 142 |
+
union Repr {
|
| 143 |
+
[[nodiscard]] bool is_inline() const {
|
| 144 |
+
uint8_t tag = 0;
|
| 145 |
+
// Use of reinterpret_cast to pointer to char or unsigned char
|
| 146 |
+
// is defined behavior; see
|
| 147 |
+
// https://en.cppreference.com/w/cpp/language/reinterpret_cast .
|
| 148 |
+
std::memcpy(&tag, reinterpret_cast<const uint8_t*>(this), 1);
|
| 149 |
+
// HeapArrayPtr will be represented as a plain old pointer,
|
| 150 |
+
// which will have alignment to at least a 2-byte boundary
|
| 151 |
+
// (because it's uint16_t*) and more likely an 8- or 16-byte
|
| 152 |
+
// boundary because malloc will tend to just align everything to
|
| 153 |
+
// one of those. So, we just set tag to 1 when inline_repr_ is
|
| 154 |
+
// active so as to be able to differentiate the two.
|
| 155 |
+
return (tag & 1) != 0;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
// NOLINTNEXTLINE(modernize-use-equals-default)
|
| 159 |
+
Repr() {}
|
| 160 |
+
|
| 161 |
+
~Repr() {
|
| 162 |
+
destroyIfOutline();
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
Repr(const Repr& rhs) {
|
| 166 |
+
if (rhs.is_inline()) {
|
| 167 |
+
std::memcpy(&inline_repr_, &rhs.inline_repr_, sizeof(inline_repr_));
|
| 168 |
+
} else {
|
| 169 |
+
new (&outline_repr_) OutlineRepr(rhs.outline_repr_);
|
| 170 |
+
}
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
Repr& operator=(const Repr& rhs) {
|
| 174 |
+
if (&rhs == this) {
|
| 175 |
+
return *this;
|
| 176 |
+
}
|
| 177 |
+
if (rhs.is_inline()) {
|
| 178 |
+
destroyIfOutline();
|
| 179 |
+
new (&inline_repr_) InlineRepr();
|
| 180 |
+
std::memcpy(&inline_repr_, &rhs.inline_repr_, sizeof(inline_repr_));
|
| 181 |
+
} else {
|
| 182 |
+
if (is_inline()) {
|
| 183 |
+
new (&outline_repr_) OutlineRepr(rhs.outline_repr_);
|
| 184 |
+
} else {
|
| 185 |
+
outline_repr_ = rhs.outline_repr_;
|
| 186 |
+
}
|
| 187 |
+
}
|
| 188 |
+
return *this;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
Repr(Repr&& rhs) noexcept {
|
| 192 |
+
if (rhs.is_inline()) {
|
| 193 |
+
std::memcpy(&inline_repr_, &rhs.inline_repr_, sizeof(inline_repr_));
|
| 194 |
+
} else {
|
| 195 |
+
new (&outline_repr_) OutlineRepr(std::move(rhs.outline_repr_));
|
| 196 |
+
}
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
Repr& operator=(Repr&& rhs) noexcept {
|
| 200 |
+
if (&rhs == this) {
|
| 201 |
+
return *this;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
if (rhs.is_inline()) {
|
| 205 |
+
destroyIfOutline();
|
| 206 |
+
new (&inline_repr_) InlineRepr();
|
| 207 |
+
std::memcpy(&inline_repr_, &rhs.inline_repr_, sizeof(inline_repr_));
|
| 208 |
+
} else {
|
| 209 |
+
if (is_inline()) {
|
| 210 |
+
new (&outline_repr_) OutlineRepr(std::move(rhs.outline_repr_));
|
| 211 |
+
} else {
|
| 212 |
+
outline_repr_ = std::move(rhs.outline_repr_);
|
| 213 |
+
}
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
return *this;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
struct InlineRepr {
|
| 220 |
+
uint8_t tag = 0x1;
|
| 221 |
+
uint8_t size{};
|
| 222 |
+
uint16_t inputs[kMaxInlineInputs]{};
|
| 223 |
+
};
|
| 224 |
+
|
| 225 |
+
using OutlineRepr = HeapArrayPtr;
|
| 226 |
+
|
| 227 |
+
InlineRepr inline_repr_{};
|
| 228 |
+
OutlineRepr outline_repr_;
|
| 229 |
+
|
| 230 |
+
private:
|
| 231 |
+
void destroyIfOutline() {
|
| 232 |
+
if (!is_inline()) {
|
| 233 |
+
outline_repr_.~OutlineRepr();
|
| 234 |
+
}
|
| 235 |
+
}
|
| 236 |
+
} repr_;
|
| 237 |
+
#pragma pack(pop)
|
| 238 |
+
};
|
| 239 |
+
|
| 240 |
+
static_assert(
|
| 241 |
+
sizeof(ProcessedNodeInputs) == 12,
|
| 242 |
+
"ProcessedNodeInputs has the wrong size!");
|
| 243 |
+
|
| 244 |
+
#else
|
| 245 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 246 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/fusion.h
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 5 |
+
|
| 6 |
+
namespace torch::jit {
|
| 7 |
+
|
| 8 |
+
TORCH_API void fuseStaticSubgraphs(
|
| 9 |
+
std::shared_ptr<Graph> graph,
|
| 10 |
+
size_t min_size);
|
| 11 |
+
|
| 12 |
+
TORCH_API void performTensorExprFusion(
|
| 13 |
+
std::shared_ptr<Graph> graph,
|
| 14 |
+
std::vector<IValue> sample_inputs);
|
| 15 |
+
|
| 16 |
+
} // namespace torch::jit
|
| 17 |
+
|
| 18 |
+
#else
|
| 19 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 20 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/impl.h
ADDED
|
@@ -0,0 +1,1152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <ATen/core/ivalue.h>
|
| 4 |
+
#include <ATen/core/symbol.h>
|
| 5 |
+
#include <c10/core/CPUAllocator.h>
|
| 6 |
+
#include <c10/macros/Macros.h>
|
| 7 |
+
#include <c10/util/ArrayRef.h>
|
| 8 |
+
#include <c10/util/FbcodeMaps.h>
|
| 9 |
+
#include <torch/csrc/jit/api/module.h>
|
| 10 |
+
#include <torch/csrc/jit/ir/graph_node_list.h>
|
| 11 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 12 |
+
#include <torch/csrc/jit/passes/constant_propagation.h>
|
| 13 |
+
#include <torch/csrc/jit/passes/freeze_module.h>
|
| 14 |
+
#include <torch/csrc/jit/passes/inliner.h>
|
| 15 |
+
#include <torch/csrc/jit/runtime/static/ProcessedNodeInputs.h>
|
| 16 |
+
#include <torch/custom_class.h>
|
| 17 |
+
#include <limits>
|
| 18 |
+
|
| 19 |
+
#ifdef FBCODE_CAFFE2
|
| 20 |
+
#include <folly/container/F14Map.h>
|
| 21 |
+
#include <folly/container/F14Set.h>
|
| 22 |
+
#endif
|
| 23 |
+
|
| 24 |
+
namespace torch::jit {
|
| 25 |
+
|
| 26 |
+
TORCH_API bool canEnableStaticRuntime(
|
| 27 |
+
const std::shared_ptr<torch::jit::Graph>& graph);
|
| 28 |
+
|
| 29 |
+
TORCH_API std::string dumpValueSet(
|
| 30 |
+
const c10::FastSet<const Value*>& value_set,
|
| 31 |
+
const char* set_name = "");
|
| 32 |
+
|
| 33 |
+
inline bool doesNotHeapAllocateWhenStoredInIValue(const Type& type) {
|
| 34 |
+
switch (type.kind()) {
|
| 35 |
+
// NOTE: NumberType may allocate because it includes complex.
|
| 36 |
+
case TypeKind::NoneType:
|
| 37 |
+
case TypeKind::IntType:
|
| 38 |
+
case TypeKind::FloatType:
|
| 39 |
+
case TypeKind::BoolType:
|
| 40 |
+
case TypeKind::DeviceObjType:
|
| 41 |
+
case TypeKind::StreamObjType:
|
| 42 |
+
return true;
|
| 43 |
+
default:
|
| 44 |
+
return false;
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
inline c10::Symbol getStaticRuntimeMetadataSymbol() {
|
| 49 |
+
return Symbol::attr("static_runtime::metadata");
|
| 50 |
+
}
|
| 51 |
+
|
| 52 |
+
inline bool borrowsOutputs(c10::Symbol kind) {
|
| 53 |
+
static const std::array<c10::Symbol, 4> symbols_with_borrowed_outputs = {
|
| 54 |
+
c10::Symbol::fromQualString("static_runtime::select_tensor"),
|
| 55 |
+
c10::Symbol::fromQualString("static_runtime::dict_unpack"),
|
| 56 |
+
c10::Symbol::fromQualString("static_runtime::VarTupleUnpack"),
|
| 57 |
+
c10::Symbol::fromQualString("prim::IfThenElse"),
|
| 58 |
+
};
|
| 59 |
+
return std::find(
|
| 60 |
+
symbols_with_borrowed_outputs.begin(),
|
| 61 |
+
symbols_with_borrowed_outputs.end(),
|
| 62 |
+
kind) != symbols_with_borrowed_outputs.end();
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
// Group values used by `graph` into three categories:
|
| 66 |
+
//
|
| 67 |
+
// - output_aliases:
|
| 68 |
+
// values that are either outputs or contain aliases of outputs
|
| 69 |
+
// - external_aliases:
|
| 70 |
+
// values that are inputs, constants, or their aliases.
|
| 71 |
+
// The output aliases that end up here are as a result of aliasDb failing to
|
| 72 |
+
// recognize them as outputs due to collection object (e.g., Tuple) aliasing
|
| 73 |
+
// inputs.
|
| 74 |
+
// Values that don't show up in output_aliases or external_aliases are created
|
| 75 |
+
// and consumed within the graph.
|
| 76 |
+
class ValueGroup {
|
| 77 |
+
public:
|
| 78 |
+
explicit ValueGroup() = default;
|
| 79 |
+
void init(const Block& block, const AliasDb& db);
|
| 80 |
+
|
| 81 |
+
bool isExternalAlias(const Value* value) const {
|
| 82 |
+
return external_aliases_.find(value) != external_aliases_.end();
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
bool isOutputAlias(const Value* value) const {
|
| 86 |
+
return output_aliases_.find(value) != output_aliases_.end();
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
bool isAlwaysAlive(const Value* value) const {
|
| 90 |
+
return isExternalAlias(value) || isOutputAlias(value);
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
std::string toString() const {
|
| 94 |
+
return c10::str(
|
| 95 |
+
dumpValueSet(output_aliases_, "ValueGroup::output_aliases_"),
|
| 96 |
+
"\n",
|
| 97 |
+
dumpValueSet(external_aliases_, "ValueGroup::external_aliases_"));
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
private:
|
| 101 |
+
c10::FastSet<const Value*> output_aliases_;
|
| 102 |
+
c10::FastSet<const Value*> external_aliases_;
|
| 103 |
+
};
|
| 104 |
+
|
| 105 |
+
class TORCH_API ManagedTensorRanges {
|
| 106 |
+
public:
|
| 107 |
+
ManagedTensorRanges() = default;
|
| 108 |
+
ManagedTensorRanges(
|
| 109 |
+
Block& block,
|
| 110 |
+
const AliasDb& alias_db,
|
| 111 |
+
const c10::FastSet<const Value*>& managed_tensor_values);
|
| 112 |
+
|
| 113 |
+
// If true, then this node is the last use of at least one
|
| 114 |
+
// managed tensor. availableTensorValuesAfterNode(node) will return a vector
|
| 115 |
+
// of the managed tensors that are available for reuse
|
| 116 |
+
// in the nodes following this one.
|
| 117 |
+
bool nodeFreesManagedTensors(Node* node) const;
|
| 118 |
+
const std::vector<const Value*>& availableTensorValuesAfterNode(
|
| 119 |
+
Node* node) const;
|
| 120 |
+
|
| 121 |
+
// For testing. True if v1 and v2 are both mutable types and have lifetimes
|
| 122 |
+
// that overlap.
|
| 123 |
+
bool lifetimesOverlap(const Value* v1, const Value* v2) const;
|
| 124 |
+
|
| 125 |
+
private:
|
| 126 |
+
struct Lifetime {
|
| 127 |
+
Lifetime(size_t start_, size_t end_) : start(start_), end(end_) {}
|
| 128 |
+
size_t start;
|
| 129 |
+
size_t end;
|
| 130 |
+
};
|
| 131 |
+
|
| 132 |
+
// Returns nullptr if we are not tracking the lifetime of value
|
| 133 |
+
Lifetime* getLifetime(const Value* value);
|
| 134 |
+
const Lifetime* getLifetime(const Value* value) const;
|
| 135 |
+
// Collect all values in the input that have tracked lifetimes.
|
| 136 |
+
// A value's lifetime may not be tracked if it is a graph input
|
| 137 |
+
// or immutable type (containers with at least one mutable
|
| 138 |
+
// type are mutable)
|
| 139 |
+
std::vector<const Value*> collectValuesWithTrackedLifetimes(
|
| 140 |
+
at::ArrayRef<const Value*> values);
|
| 141 |
+
void extendLifetime(Value* input, size_t new_end);
|
| 142 |
+
void extendInputLifetime(Node* node, size_t new_end);
|
| 143 |
+
|
| 144 |
+
// Maps Node* to the set of managed tensors that are now available
|
| 145 |
+
// for reuse after this node.
|
| 146 |
+
c10::FastMap<Node*, std::vector<const Value*>> node_to_newly_free_tensors_;
|
| 147 |
+
// Maps each Value* to its lifetime (start node index, end node index)
|
| 148 |
+
c10::FastMap<const Value*, Lifetime> value_lifetimes_;
|
| 149 |
+
};
|
| 150 |
+
|
| 151 |
+
struct TORCH_API StaticModuleOptions {
|
| 152 |
+
// enabling out variant allows Static Runtime to do memory planning
|
| 153 |
+
bool enable_out_variant{true};
|
| 154 |
+
// to reuse tensor storage for tensors whose live-range do not overlap to
|
| 155 |
+
// reduce memory footprint (enable_out_variant must be true)
|
| 156 |
+
bool optimize_memory{true};
|
| 157 |
+
// to batch allocate tensor storage for output tensors of the
|
| 158 |
+
// graph, where storage is deallocated outside static runtime
|
| 159 |
+
// (enable_out_variant must be true)
|
| 160 |
+
bool manage_output_tensors{false};
|
| 161 |
+
// Gates the ReplaceWithCopy pass, which replaces ops that
|
| 162 |
+
// sometimes alias their outputs with out variants that
|
| 163 |
+
// always copy (so the output may participate in memory planning).
|
| 164 |
+
// Since replacing with copies is done after TensorExpr fusion, the
|
| 165 |
+
// resulting graph does not conform to the assumptions made in the fuser.
|
| 166 |
+
// So, even if this flag is turned on, the ReplaceWithCopy pass will not
|
| 167 |
+
// be executed if TensorExpr fusion is enabled.
|
| 168 |
+
bool use_copy_variants{true};
|
| 169 |
+
// Gates the ReplaceWithMaybeCopy pass, which replaces ops that
|
| 170 |
+
// sometimes alias their outputs with subgraphs that include an out
|
| 171 |
+
// variant.
|
| 172 |
+
// For the same reason as `use_copy_variants`, the ReplaceWithMaybeCopy pass
|
| 173 |
+
// will not be executed if TensorExpr fusion is enabled, even if this flag
|
| 174 |
+
// is turned on.
|
| 175 |
+
bool use_maybe_copy_variants{true};
|
| 176 |
+
// enable TensorExpr fusion of ops at model loading time
|
| 177 |
+
bool enable_tensorexpr_fusion{false};
|
| 178 |
+
};
|
| 179 |
+
|
| 180 |
+
/*
|
| 181 |
+
Responsible for plugging StaticRuntime metadata onto the
|
| 182 |
+
IR nodes. StaticRuntimeMetdata extends CustomClassHolder
|
| 183 |
+
which can be casted to IValue and attached to IR node.
|
| 184 |
+
This is needed to pass parent graph metadata to forked
|
| 185 |
+
graph in presence of prim::fork operator
|
| 186 |
+
*/
|
| 187 |
+
class TORCH_API StaticRuntimeMetadata : public torch::CustomClassHolder {
|
| 188 |
+
public:
|
| 189 |
+
explicit StaticRuntimeMetadata(const StaticModuleOptions& opts)
|
| 190 |
+
: opts_(opts) {}
|
| 191 |
+
|
| 192 |
+
const StaticModuleOptions& get_opts() {
|
| 193 |
+
return opts_;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
private:
|
| 197 |
+
StaticModuleOptions opts_;
|
| 198 |
+
};
|
| 199 |
+
|
| 200 |
+
/// The static runime supports two execution modes.
|
| 201 |
+
///
|
| 202 |
+
/// Mode 1: single-threaded with no parallelism except for intra-op parallelism
|
| 203 |
+
/// For this mode, you can do either:
|
| 204 |
+
/// @code
|
| 205 |
+
/// // m is a TorchScript module
|
| 206 |
+
/// auto module = StaticModule(m, opts);
|
| 207 |
+
/// auto output = module(args, kwargs);
|
| 208 |
+
/// @endcode
|
| 209 |
+
///
|
| 210 |
+
/// or
|
| 211 |
+
///
|
| 212 |
+
/// @code
|
| 213 |
+
/// // g is the TorchScript graph
|
| 214 |
+
/// auto module = StaticModule(g, opts);
|
| 215 |
+
/// auto output = module(args, kwargs);
|
| 216 |
+
/// @endcode
|
| 217 |
+
///
|
| 218 |
+
/// Mode 2: similar to data parallelism, run the same model for different inputs
|
| 219 |
+
/// on different threads at the same time.
|
| 220 |
+
/// You should have one StaticModule per model, and one StaticRuntime instance
|
| 221 |
+
/// per running thread. To avoiding creating StaticRuntimes on the fly, use a
|
| 222 |
+
/// synchronized stack (i.e. boost::lockfree::stack) to cache all the
|
| 223 |
+
/// StaticRuntime instances in your code.
|
| 224 |
+
/// @code
|
| 225 |
+
/// // initialization
|
| 226 |
+
/// auto module = std::make_shared<StaticModule>(m, opts);
|
| 227 |
+
///
|
| 228 |
+
/// // 128 is good for most cases. Pick a number that works for you
|
| 229 |
+
/// boost::lockfree::stack<std::shared_ptr<StaticRuntime>,
|
| 230 |
+
/// boost::lockfree::fixed_sized<true>> pool(128);
|
| 231 |
+
///
|
| 232 |
+
/// // inference
|
| 233 |
+
/// std::shared_ptr<StaticRuntime> runtime = nullptr;
|
| 234 |
+
/// pool.pop(runtime);
|
| 235 |
+
/// if (!runtime) {
|
| 236 |
+
/// // holds a reference to the underlying module
|
| 237 |
+
/// // but does its own memory management
|
| 238 |
+
/// runtime = std::make_shared<StaticRuntime>(*module);
|
| 239 |
+
/// }
|
| 240 |
+
/// auto output = runtime(args, kwargs);
|
| 241 |
+
/// pool.push(runtime);
|
| 242 |
+
/// @endcode
|
| 243 |
+
///
|
| 244 |
+
class MemoryPlanner;
|
| 245 |
+
class ProcessedNode;
|
| 246 |
+
class StaticRuntime;
|
| 247 |
+
|
| 248 |
+
using SROperator = std::function<void(ProcessedNode*)>;
|
| 249 |
+
|
| 250 |
+
#ifdef FBCODE_CAFFE2
|
| 251 |
+
struct TORCH_API SROperatorObserver {
|
| 252 |
+
using OperatorCallback = void (*)(const Node*);
|
| 253 |
+
OperatorCallback startCb = nullptr;
|
| 254 |
+
OperatorCallback endCb = nullptr;
|
| 255 |
+
|
| 256 |
+
static void setCurrentThreadObserver(SROperatorObserver* observer);
|
| 257 |
+
static SROperatorObserver* getCurrentThreadObserver();
|
| 258 |
+
static void onStart(const Node* name);
|
| 259 |
+
static void onEnd(const Node* name);
|
| 260 |
+
};
|
| 261 |
+
#endif
|
| 262 |
+
|
| 263 |
+
class TORCH_API ProcessedFunction {
|
| 264 |
+
public:
|
| 265 |
+
ProcessedFunction(
|
| 266 |
+
Node* node,
|
| 267 |
+
bool enable_out_variant,
|
| 268 |
+
bool check_memory_overlap);
|
| 269 |
+
|
| 270 |
+
enum class Kind : uint8_t {
|
| 271 |
+
kOutVariant,
|
| 272 |
+
kNativeFunction,
|
| 273 |
+
kInterpreterFallback,
|
| 274 |
+
};
|
| 275 |
+
|
| 276 |
+
void run(ProcessedNode* pnode) const {
|
| 277 |
+
return f_(pnode);
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
Kind kind() const {
|
| 281 |
+
return kind_;
|
| 282 |
+
}
|
| 283 |
+
|
| 284 |
+
bool checkMemoryOverlap() const {
|
| 285 |
+
return check_memory_overlap_;
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
size_t num_outputs() const {
|
| 289 |
+
return num_outputs_;
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
private:
|
| 293 |
+
SROperator f_;
|
| 294 |
+
Kind kind_{ProcessedFunction::Kind::kOutVariant};
|
| 295 |
+
bool check_memory_overlap_{false};
|
| 296 |
+
size_t num_outputs_{0};
|
| 297 |
+
};
|
| 298 |
+
|
| 299 |
+
class TORCH_API StaticNodeInfo {
|
| 300 |
+
public:
|
| 301 |
+
StaticNodeInfo(
|
| 302 |
+
Node* n,
|
| 303 |
+
ProcessedFunction* fn,
|
| 304 |
+
ProcessedNodeInputs inputs,
|
| 305 |
+
uint16_t outputs_offset);
|
| 306 |
+
|
| 307 |
+
Node* node() const {
|
| 308 |
+
return node_;
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
size_t num_outputs() const {
|
| 312 |
+
DCHECK(fn_ != nullptr);
|
| 313 |
+
return fn_->num_outputs();
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
bool has_out_variant() const {
|
| 317 |
+
return fn_->kind() == ProcessedFunction::Kind::kOutVariant;
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
private:
|
| 321 |
+
friend class ProcessedNode;
|
| 322 |
+
|
| 323 |
+
Node* node_;
|
| 324 |
+
const ProcessedFunction* fn_;
|
| 325 |
+
ProcessedNodeInputs inputs_;
|
| 326 |
+
uint16_t outputs_offset_;
|
| 327 |
+
};
|
| 328 |
+
|
| 329 |
+
// A `BlockInfo` instance stores all of the shared state that each
|
| 330 |
+
// `BlockRunner` will need to access. Most of this information is
|
| 331 |
+
// read-only and shared between threads.
|
| 332 |
+
// - Each `BlockInfo` corresponds to one block in the graph.
|
| 333 |
+
// - Each `BlockInfo` may be used by multiple block runners (when there are many
|
| 334 |
+
// threads).
|
| 335 |
+
// - All of the `BlockInfo`s are stored in a vector in the `StaticModule` and
|
| 336 |
+
// are initialized during `StaticModule` construction.
|
| 337 |
+
// - Most of the information stored is used to initialize the block's memory
|
| 338 |
+
// planner.
|
| 339 |
+
class BlockInfo {
|
| 340 |
+
public:
|
| 341 |
+
BlockInfo(uint32_t input_idx, Block& block);
|
| 342 |
+
|
| 343 |
+
void set_nodes(
|
| 344 |
+
std::vector<StaticNodeInfo> nodes,
|
| 345 |
+
const c10::FastMap<Node*, bool>& node_has_out_variant);
|
| 346 |
+
|
| 347 |
+
const std::vector<StaticNodeInfo>& nodes() const {
|
| 348 |
+
return nodes_;
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
size_t num_nodes() const;
|
| 352 |
+
|
| 353 |
+
size_t num_inputs() const {
|
| 354 |
+
return block_.inputs().size();
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
size_t num_outputs() const {
|
| 358 |
+
return block_.outputs().size();
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
graph_node_list node_ptrs() const {
|
| 362 |
+
return block_.nodes();
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
void set_output_indices(std::vector<uint16_t> indices) {
|
| 366 |
+
output_indices_ = std::move(indices);
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
const std::vector<uint16_t>& block_output_indices() const {
|
| 370 |
+
return output_indices_;
|
| 371 |
+
}
|
| 372 |
+
|
| 373 |
+
auto block_inputs_idx() const {
|
| 374 |
+
return input_idx_;
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
bool node_is_optimizable_container_type(const Node* node) const {
|
| 378 |
+
return node_is_optimizable_container_type_.find(node) !=
|
| 379 |
+
node_is_optimizable_container_type_.end();
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
bool value_is_managed_tensor(const Value* value) const {
|
| 383 |
+
return managed_tensor_values_.find(value) != managed_tensor_values_.end();
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
bool value_is_leaked_container(const Value* value) const {
|
| 387 |
+
return leaked_values_.find(value) != leaked_values_.end();
|
| 388 |
+
}
|
| 389 |
+
|
| 390 |
+
const ValueGroup& value_group() const {
|
| 391 |
+
return value_group_;
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
const ManagedTensorRanges& managed_tensor_ranges() const {
|
| 395 |
+
return managed_tensor_ranges_;
|
| 396 |
+
}
|
| 397 |
+
|
| 398 |
+
void init_value_group(const AliasDb& alias_db) {
|
| 399 |
+
value_group_.init(block_, alias_db);
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
void prepare_for_memory_planner(
|
| 403 |
+
const AliasDb& alias_db,
|
| 404 |
+
const StaticModuleOptions& opt);
|
| 405 |
+
|
| 406 |
+
const auto& managed_output_tensor_values() const {
|
| 407 |
+
return managed_output_tensor_values_;
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
const auto& managed_tensor_values() const {
|
| 411 |
+
return managed_tensor_values_;
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
const auto& leaked_values() const {
|
| 415 |
+
return leaked_values_;
|
| 416 |
+
}
|
| 417 |
+
|
| 418 |
+
private:
|
| 419 |
+
std::vector<StaticNodeInfo> nodes_;
|
| 420 |
+
|
| 421 |
+
ValueGroup value_group_;
|
| 422 |
+
|
| 423 |
+
c10::FastSet<const Node*> node_is_optimizable_container_type_;
|
| 424 |
+
c10::FastSet<const Value*> managed_tensor_values_;
|
| 425 |
+
c10::FastSet<const Value*> managed_output_tensor_values_;
|
| 426 |
+
c10::FastSet<const Value*> leaked_values_;
|
| 427 |
+
|
| 428 |
+
ManagedTensorRanges managed_tensor_ranges_;
|
| 429 |
+
|
| 430 |
+
// The index of this block's inputs in the shared values_ array.
|
| 431 |
+
const uint16_t input_idx_;
|
| 432 |
+
// The indices of this block's outputs in the shared values_ array.
|
| 433 |
+
std::vector<uint16_t> output_indices_;
|
| 434 |
+
Block& block_;
|
| 435 |
+
};
|
| 436 |
+
|
| 437 |
+
class TORCH_API StaticModule {
|
| 438 |
+
public:
|
| 439 |
+
explicit StaticModule(
|
| 440 |
+
const std::shared_ptr<torch::jit::Graph>& g,
|
| 441 |
+
const StaticModuleOptions& opts = StaticModuleOptions(),
|
| 442 |
+
std::vector<IValue> sample_inputs = {});
|
| 443 |
+
|
| 444 |
+
explicit StaticModule(
|
| 445 |
+
const torch::jit::Module& m,
|
| 446 |
+
bool is_frozen = false,
|
| 447 |
+
const StaticModuleOptions& opts = StaticModuleOptions(),
|
| 448 |
+
std::vector<IValue> sample_inputs = {});
|
| 449 |
+
|
| 450 |
+
private:
|
| 451 |
+
explicit StaticModule(
|
| 452 |
+
std::pair<std::shared_ptr<torch::jit::Graph>, std::optional<Module>>
|
| 453 |
+
graph_and_module,
|
| 454 |
+
const StaticModuleOptions& opts);
|
| 455 |
+
|
| 456 |
+
public:
|
| 457 |
+
using KeywordArgs = std::unordered_map<std::string, c10::IValue>;
|
| 458 |
+
c10::IValue operator()(
|
| 459 |
+
const std::vector<c10::IValue>& args,
|
| 460 |
+
const KeywordArgs& kwargs = KeywordArgs());
|
| 461 |
+
c10::IValue operator()(
|
| 462 |
+
std::vector<c10::IValue>&& args,
|
| 463 |
+
const KeywordArgs& kwargs = KeywordArgs());
|
| 464 |
+
|
| 465 |
+
const Graph& graph() const {
|
| 466 |
+
return *graph_;
|
| 467 |
+
}
|
| 468 |
+
|
| 469 |
+
const Module& module() const {
|
| 470 |
+
DCHECK(module_.has_value());
|
| 471 |
+
return *module_;
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
const StaticModuleOptions& opts() const;
|
| 475 |
+
|
| 476 |
+
size_t num_inputs() const;
|
| 477 |
+
size_t num_outputs() const;
|
| 478 |
+
|
| 479 |
+
size_t num_constants() const {
|
| 480 |
+
return constants_.size();
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
size_t num_intermediate_values() const {
|
| 484 |
+
return num_intermediate_values_;
|
| 485 |
+
}
|
| 486 |
+
|
| 487 |
+
size_t total_num_values() const {
|
| 488 |
+
return num_inputs() + num_constants() + num_intermediate_values();
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
[[nodiscard]] const std::vector<uint16_t>& output_indices() const {
|
| 492 |
+
return output_indices_;
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
const std::vector<IValue>& constants() const {
|
| 496 |
+
return constants_;
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
const BlockInfo& block_info(Block* block) const {
|
| 500 |
+
return block_infos_.at(block);
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
Block* root_block() const {
|
| 504 |
+
return graph_->block();
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
private:
|
| 508 |
+
friend class StaticRuntime;
|
| 509 |
+
friend class BlockRunner;
|
| 510 |
+
|
| 511 |
+
public:
|
| 512 |
+
auto num_nodes() const {
|
| 513 |
+
return std::accumulate(
|
| 514 |
+
block_infos_.begin(),
|
| 515 |
+
block_infos_.end(),
|
| 516 |
+
0,
|
| 517 |
+
[](size_t sum, const auto& block_and_info) {
|
| 518 |
+
auto& block_info = block_and_info.second;
|
| 519 |
+
return sum + block_info.num_nodes();
|
| 520 |
+
});
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
[[nodiscard]] Node* findNodeWithKindForTesting(const std::string& kind) const;
|
| 524 |
+
|
| 525 |
+
const std::optional<c10::FunctionSchema>& schema() const {
|
| 526 |
+
return schema_;
|
| 527 |
+
}
|
| 528 |
+
|
| 529 |
+
bool first_input_is_self() const {
|
| 530 |
+
return module_.has_value();
|
| 531 |
+
}
|
| 532 |
+
|
| 533 |
+
StaticRuntime& runtime();
|
| 534 |
+
|
| 535 |
+
// See [Shared values array]
|
| 536 |
+
size_t value_buffer_size() const {
|
| 537 |
+
return value_buffer_size_;
|
| 538 |
+
}
|
| 539 |
+
|
| 540 |
+
private:
|
| 541 |
+
// Recursively prepares the BlockInfo array.
|
| 542 |
+
// - Populates `value_to_index` with the indices of each intermediate value
|
| 543 |
+
// - Returns the number of Value* processed, including sub-blocks.
|
| 544 |
+
size_t prepareBlockInfo(
|
| 545 |
+
Block* block,
|
| 546 |
+
const size_t start_idx,
|
| 547 |
+
c10::FastMap<const Value*, uint32_t>& value_to_index);
|
| 548 |
+
|
| 549 |
+
void prepareFunctionsAndConstants(
|
| 550 |
+
Block* block,
|
| 551 |
+
const AliasDb& alias_db,
|
| 552 |
+
c10::FastMap<const Value*, uint32_t>& value_to_index);
|
| 553 |
+
|
| 554 |
+
// Recursively traverse the graph and attach SR metadata
|
| 555 |
+
// to the prim::fork nodes as additional attributes
|
| 556 |
+
void attachNodeMetadata(Block* block);
|
| 557 |
+
|
| 558 |
+
// Recurses on sub-blocks and populates the array of ProcessedNodes
|
| 559 |
+
// Returns (number of nodes processed, number of blocks processed)
|
| 560 |
+
size_t prepareStaticNodeInfos(
|
| 561 |
+
Block* block,
|
| 562 |
+
const c10::FastMap<const Value*, uint32_t>& value_to_index,
|
| 563 |
+
const AliasDb& alias_db,
|
| 564 |
+
size_t node_idx = 0);
|
| 565 |
+
|
| 566 |
+
// Initialize various attributes that the memory planner will need.
|
| 567 |
+
// To be called at the tail of the ctor.
|
| 568 |
+
void prepareForMemoryPlanner();
|
| 569 |
+
|
| 570 |
+
StaticModuleOptions opts_;
|
| 571 |
+
// metadata that is stored in IR nodes as attribute
|
| 572 |
+
at::intrusive_ptr<jit::StaticRuntimeMetadata> sr_metadata_;
|
| 573 |
+
std::shared_ptr<torch::jit::Graph> graph_;
|
| 574 |
+
std::optional<torch::jit::Module> module_;
|
| 575 |
+
std::optional<c10::FunctionSchema> schema_;
|
| 576 |
+
std::unique_ptr<StaticRuntime> cached_runtime_;
|
| 577 |
+
|
| 578 |
+
// Bookkeeping for creating new StaticRuntime instances
|
| 579 |
+
// IValue table (defined by prim::Constant nodes)
|
| 580 |
+
std::vector<IValue> constants_;
|
| 581 |
+
// The functions to be called by corresponding ProcessedNode.
|
| 582 |
+
std::vector<ProcessedFunction> functions_;
|
| 583 |
+
// A list of pre-processed nodes from which ProcessedNode are created per
|
| 584 |
+
// StaticRuntime instance.
|
| 585 |
+
std::vector<StaticNodeInfo> nodes_;
|
| 586 |
+
// Indices of graph outputs in the single values array.
|
| 587 |
+
std::vector<uint16_t> output_indices_;
|
| 588 |
+
|
| 589 |
+
size_t num_intermediate_values_ = 0;
|
| 590 |
+
|
| 591 |
+
// Includes self if module_ != std::nullopt.
|
| 592 |
+
// Note that we might have num_inputs_ == 0 even if the schema has a `self`
|
| 593 |
+
// argument. In this case, `self` isn't used in the graph, but the schema
|
| 594 |
+
// includes it anyways to be consistent with the JIT interpreter.
|
| 595 |
+
size_t num_inputs_;
|
| 596 |
+
// See `BlockInfo` definition. The blocks are stored in depth-first order.
|
| 597 |
+
c10::FastMap<Block*, BlockInfo> block_infos_;
|
| 598 |
+
size_t value_buffer_size_ = 0;
|
| 599 |
+
};
|
| 600 |
+
|
| 601 |
+
// `BlockRunner` contains the core runtime logic. Each block runner
|
| 602 |
+
// corresponds to one block in the graph and has its own memory planner.
|
| 603 |
+
// `StaticRuntime` will initialize all `BlockRunner`s
|
| 604 |
+
// upon construction. Each block runner only directly executes nodes from its
|
| 605 |
+
// block. Special ops with sub-blocks like `prim::If` may have
|
| 606 |
+
// `BlockRunner`s stored in their `ProcessedNode`s; these
|
| 607 |
+
// sub-blocks get executed in the op's implementation.
|
| 608 |
+
// `StaticRuntime` stores a vector of IValues that all
|
| 609 |
+
// `BlockRunner`s share. This vector is used to store all
|
| 610 |
+
// constants, inputs, and intermediate tensors.
|
| 611 |
+
class TORCH_API BlockRunner {
|
| 612 |
+
public:
|
| 613 |
+
BlockRunner(
|
| 614 |
+
const StaticModule& sm,
|
| 615 |
+
IValue* values,
|
| 616 |
+
Block* block,
|
| 617 |
+
torch::jit::TaskLauncher* launcher,
|
| 618 |
+
bool is_root_block = false);
|
| 619 |
+
BlockRunner(BlockRunner&&) noexcept;
|
| 620 |
+
BlockRunner& operator=(BlockRunner&&) = delete;
|
| 621 |
+
~BlockRunner();
|
| 622 |
+
|
| 623 |
+
C10_DISABLE_COPY_AND_ASSIGN(BlockRunner);
|
| 624 |
+
|
| 625 |
+
using KeywordArgs = std::unordered_map<std::string, c10::IValue>;
|
| 626 |
+
c10::IValue operator()(
|
| 627 |
+
const std::vector<c10::IValue>& args,
|
| 628 |
+
const KeywordArgs& kwargs = KeywordArgs());
|
| 629 |
+
c10::IValue operator()(
|
| 630 |
+
std::vector<c10::IValue>&& args,
|
| 631 |
+
const KeywordArgs& kwargs = KeywordArgs());
|
| 632 |
+
|
| 633 |
+
c10::intrusive_ptr<c10::ivalue::Future> runAsync(
|
| 634 |
+
const std::vector<c10::IValue>& args,
|
| 635 |
+
const KeywordArgs& kwargs);
|
| 636 |
+
|
| 637 |
+
c10::intrusive_ptr<c10::ivalue::Future> runAsync(
|
| 638 |
+
std::vector<c10::IValue>&& args,
|
| 639 |
+
const KeywordArgs& kwargs);
|
| 640 |
+
|
| 641 |
+
void benchmark(
|
| 642 |
+
const std::vector<std::vector<c10::IValue>>& args_list,
|
| 643 |
+
const std::vector<KeywordArgs>& kwargs_list,
|
| 644 |
+
const uint32_t warmup_runs,
|
| 645 |
+
const uint32_t main_runs,
|
| 646 |
+
bool print_per_node_time = false,
|
| 647 |
+
bool generate_ai_pep_output = false);
|
| 648 |
+
|
| 649 |
+
struct IndividualMetrics {
|
| 650 |
+
float setup_time{0.0};
|
| 651 |
+
float memory_alloc_time{0.0};
|
| 652 |
+
float memory_dealloc_time{0.0};
|
| 653 |
+
float output_dealloc_time{0.0};
|
| 654 |
+
float first_iter_time{0.0};
|
| 655 |
+
float total_time{0.0};
|
| 656 |
+
size_t out_nodes_count{0};
|
| 657 |
+
size_t total_nodes_count{0};
|
| 658 |
+
std::vector<float> time_per_node;
|
| 659 |
+
std::unordered_map<std::string, float> time_per_node_type;
|
| 660 |
+
std::unordered_map<std::string, float> percent_per_node_type;
|
| 661 |
+
std::unordered_map<std::string, int> instances_per_node_type;
|
| 662 |
+
std::unordered_set<std::string> out_nodes;
|
| 663 |
+
std::unordered_set<std::string> native_nodes;
|
| 664 |
+
};
|
| 665 |
+
|
| 666 |
+
IndividualMetrics benchmark_individual_ops(
|
| 667 |
+
const std::vector<std::vector<c10::IValue>>& args_list,
|
| 668 |
+
const std::vector<KeywordArgs>& kwargs_list,
|
| 669 |
+
const uint32_t warmup_runs,
|
| 670 |
+
const uint32_t main_runs);
|
| 671 |
+
|
| 672 |
+
// Input is readwrite
|
| 673 |
+
IValue& Input(uint32_t i) {
|
| 674 |
+
TORCH_DCHECK_LT(i, block_info_.num_inputs());
|
| 675 |
+
return values_[i + block_info_.block_inputs_idx()];
|
| 676 |
+
}
|
| 677 |
+
|
| 678 |
+
// Output is readonly. The writing process happens inside ProcessedNodes
|
| 679 |
+
[[nodiscard]] const IValue& Output(uint32_t i) const {
|
| 680 |
+
DCHECK(i < outputs_.size());
|
| 681 |
+
return *outputs_[i];
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
const std::vector<IValue*> outputs() const {
|
| 685 |
+
return outputs_;
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
const std::vector<ProcessedNode>& nodes() const {
|
| 689 |
+
return nodes_;
|
| 690 |
+
}
|
| 691 |
+
|
| 692 |
+
std::vector<ProcessedNode>& nodes() {
|
| 693 |
+
return nodes_;
|
| 694 |
+
}
|
| 695 |
+
|
| 696 |
+
graph_node_list node_ptrs() const {
|
| 697 |
+
return block_info_.node_ptrs();
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
const Graph& graph() const {
|
| 701 |
+
return static_module_.graph();
|
| 702 |
+
}
|
| 703 |
+
|
| 704 |
+
const MemoryPlanner* get_memory_planner() const {
|
| 705 |
+
return planner_.get();
|
| 706 |
+
}
|
| 707 |
+
|
| 708 |
+
bool check_for_memory_leak(
|
| 709 |
+
bool output_returned = true,
|
| 710 |
+
bool recurse_on_sub_blocks = false);
|
| 711 |
+
|
| 712 |
+
// WARNING: Deallocate managed output tensors. A client receiving Static
|
| 713 |
+
// Runtime-managed Tensors needs to be very careful to call
|
| 714 |
+
// `StaticRuntime::deallocateOutputTensors` after all references of output
|
| 715 |
+
// Tensors are gone.
|
| 716 |
+
void deallocateOutputTensors();
|
| 717 |
+
|
| 718 |
+
bool checkOutputTensorMemoryLeaks();
|
| 719 |
+
|
| 720 |
+
bool isManagedOutputTensor(const IValue& ivalue) const;
|
| 721 |
+
bool isManagedOutputTensorValue(const Value* value) const;
|
| 722 |
+
|
| 723 |
+
void disableManageOutputTensors();
|
| 724 |
+
|
| 725 |
+
// This is the fallback path taken if we can't construct the memory planner
|
| 726 |
+
// on the first iteration.
|
| 727 |
+
// IMPORTANT: Nothing here should be able to throw!!!
|
| 728 |
+
// This function can be called from the (implicitly) `noexcept` destructor
|
| 729 |
+
// of Deallocator, meaning that std::terminate will be called
|
| 730 |
+
// if any exception escapes. Even if resetMemory and ~Deallocator were
|
| 731 |
+
// `noexcept(false)`, it's possible that when ~Deallocator is called, the
|
| 732 |
+
// stack is already unwinding, so there's still danger of calling
|
| 733 |
+
// std::terminate.
|
| 734 |
+
void resetMemory() noexcept;
|
| 735 |
+
|
| 736 |
+
private:
|
| 737 |
+
// A helper object that invokes memory planner deallocation code
|
| 738 |
+
// when destructed.
|
| 739 |
+
class Deallocator {
|
| 740 |
+
public:
|
| 741 |
+
explicit Deallocator(BlockRunner& block_runner)
|
| 742 |
+
: block_runner_(block_runner) {}
|
| 743 |
+
|
| 744 |
+
Deallocator(Deallocator&&) = default;
|
| 745 |
+
Deallocator(const Deallocator&) = default;
|
| 746 |
+
Deallocator& operator=(const Deallocator&) = delete;
|
| 747 |
+
Deallocator& operator=(Deallocator&&) = delete;
|
| 748 |
+
~Deallocator();
|
| 749 |
+
|
| 750 |
+
void setFinished() {
|
| 751 |
+
finished_ = true;
|
| 752 |
+
}
|
| 753 |
+
|
| 754 |
+
private:
|
| 755 |
+
void cleanupImpl();
|
| 756 |
+
|
| 757 |
+
bool finished_ = false;
|
| 758 |
+
BlockRunner& block_runner_;
|
| 759 |
+
};
|
| 760 |
+
|
| 761 |
+
template <typename IValueList>
|
| 762 |
+
c10::IValue run_impl(IValueList&& args, const KeywordArgs& kwargs);
|
| 763 |
+
|
| 764 |
+
template <typename IValueList>
|
| 765 |
+
c10::IValue run_impl_record_functions(
|
| 766 |
+
IValueList&& args,
|
| 767 |
+
const KeywordArgs& kwargs);
|
| 768 |
+
|
| 769 |
+
template <typename IValueList>
|
| 770 |
+
c10::intrusive_ptr<c10::ivalue::Future> run_impl_async(
|
| 771 |
+
IValueList&& args,
|
| 772 |
+
const KeywordArgs& kwargs);
|
| 773 |
+
|
| 774 |
+
template <typename IValueList>
|
| 775 |
+
c10::intrusive_ptr<c10::ivalue::Future> run_impl_record_functions_async(
|
| 776 |
+
IValueList&& args,
|
| 777 |
+
const KeywordArgs& kwargs);
|
| 778 |
+
|
| 779 |
+
// helper method for copying input args/kwargs into inputs_
|
| 780 |
+
template <typename IValueList>
|
| 781 |
+
void set_inputs(IValueList&& args, const KeywordArgs& kwargs);
|
| 782 |
+
|
| 783 |
+
// Set Input(idx) to args[idx]. Invoked by set_inputs. Copies or moves
|
| 784 |
+
// depending on overload.
|
| 785 |
+
void set_arg(const size_t idx, std::vector<IValue>&& args);
|
| 786 |
+
void set_arg(const size_t idx, const std::vector<IValue>& args);
|
| 787 |
+
|
| 788 |
+
// Set Input(idx) to arg. Always copies. Used for kwargs.
|
| 789 |
+
void set_arg(const size_t idx, const IValue& arg);
|
| 790 |
+
|
| 791 |
+
bool fast_check_and_correct_overlap_with(
|
| 792 |
+
ProcessedNode& n,
|
| 793 |
+
c10::IValue& tensor_ival);
|
| 794 |
+
void verify_and_correct_memory_overlap(ProcessedNode& n);
|
| 795 |
+
|
| 796 |
+
// clean up owning refs of input IValues
|
| 797 |
+
void clean_up_input_ivalues() noexcept {
|
| 798 |
+
for (const auto idx : c10::irange(block_info_.num_inputs())) {
|
| 799 |
+
values_[idx + inputs_begin_] = IValue();
|
| 800 |
+
}
|
| 801 |
+
}
|
| 802 |
+
|
| 803 |
+
void clean_up_intermediate_ivalues() noexcept;
|
| 804 |
+
|
| 805 |
+
IValue move_outputs_to_tuple(uint32_t num_outputs);
|
| 806 |
+
|
| 807 |
+
void create_memory_planner();
|
| 808 |
+
|
| 809 |
+
float benchmark_model(
|
| 810 |
+
const std::vector<std::vector<c10::IValue>>& args_list,
|
| 811 |
+
const std::vector<KeywordArgs>& kwargs_list,
|
| 812 |
+
const uint32_t warmup_runs,
|
| 813 |
+
const uint32_t main_runs);
|
| 814 |
+
|
| 815 |
+
void display_nodes(
|
| 816 |
+
const std::vector<c10::IValue>& args,
|
| 817 |
+
const KeywordArgs& kwargs);
|
| 818 |
+
|
| 819 |
+
const StaticModule& static_module_;
|
| 820 |
+
const BlockInfo& block_info_;
|
| 821 |
+
|
| 822 |
+
const bool is_root_block_;
|
| 823 |
+
// Cache this so we don't have to call static_module_.first_input_is_self()
|
| 824 |
+
const bool first_input_is_self_;
|
| 825 |
+
// Index of the start of this blocks inputs in the shared values_ array.
|
| 826 |
+
const uint16_t inputs_begin_;
|
| 827 |
+
|
| 828 |
+
bool manage_output_tensors_enabled_ = false;
|
| 829 |
+
std::unique_ptr<MemoryPlanner> planner_;
|
| 830 |
+
// [Shared values array]
|
| 831 |
+
// ProcessedNodes reference their inputs and outputs with
|
| 832 |
+
// offsets into this array, which saves memory.
|
| 833 |
+
// All BlockRunners share the same array. The layout is as
|
| 834 |
+
// follows:
|
| 835 |
+
// [constants][block_0][block_1]...[block_N]
|
| 836 |
+
// Note that constants from all blocks are pooled together at the start.
|
| 837 |
+
// The block ordering is depth-first.
|
| 838 |
+
// Each block is further divided into inputs and intermediates:
|
| 839 |
+
// [block_i] = [inputs_i][intermediates_i]
|
| 840 |
+
// Each BlockRunner knows where its inputs start. Each ProcessedNode
|
| 841 |
+
// knows how to find the indices of its outputs/inputs in this array.
|
| 842 |
+
IValue* values_;
|
| 843 |
+
|
| 844 |
+
std::vector<IValue*> outputs_;
|
| 845 |
+
std::vector<ProcessedNode> nodes_;
|
| 846 |
+
};
|
| 847 |
+
|
| 848 |
+
inline size_t BlockInfo::num_nodes() const {
|
| 849 |
+
return nodes_.size();
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
/*
|
| 853 |
+
ProcessedNodeMetadata class wraps the possible metadata
|
| 854 |
+
for ProcessedNode. Depending upon the nature of op, processedNode
|
| 855 |
+
can have one of the below possibilities of metadata:
|
| 856 |
+
- prim::If/prim::Loop ops contains block_runners_ as their metadata
|
| 857 |
+
- prim::fork op contains TaskLauncher (std::function) responsible for
|
| 858 |
+
execution of forked subgraph
|
| 859 |
+
*/
|
| 860 |
+
class TORCH_API ProcessedNodeMetadata {
|
| 861 |
+
public:
|
| 862 |
+
ProcessedNodeMetadata(
|
| 863 |
+
std::vector<BlockRunner> runners,
|
| 864 |
+
torch::jit::TaskLauncher* launcher)
|
| 865 |
+
: block_runners_(std::move(runners)), launcher_(launcher) {}
|
| 866 |
+
|
| 867 |
+
ProcessedNodeMetadata() : launcher_(nullptr) {}
|
| 868 |
+
|
| 869 |
+
// deleted copy ctor/assignment as standard containers (vector) always
|
| 870 |
+
// have copy constructors, but their instantiation is not well-formed
|
| 871 |
+
// if the contained type (BlockRunner) is not copyable
|
| 872 |
+
ProcessedNodeMetadata(const ProcessedNodeMetadata&) = delete;
|
| 873 |
+
ProcessedNodeMetadata& operator=(const ProcessedNodeMetadata&) = delete;
|
| 874 |
+
ProcessedNodeMetadata(ProcessedNodeMetadata&&) = delete;
|
| 875 |
+
ProcessedNodeMetadata&& operator=(ProcessedNodeMetadata&&) = delete;
|
| 876 |
+
~ProcessedNodeMetadata() = default;
|
| 877 |
+
|
| 878 |
+
std::vector<BlockRunner>& block_runners() {
|
| 879 |
+
return block_runners_;
|
| 880 |
+
}
|
| 881 |
+
|
| 882 |
+
void set_block_runners(std::vector<BlockRunner> runners) {
|
| 883 |
+
block_runners_ = std::move(runners);
|
| 884 |
+
}
|
| 885 |
+
|
| 886 |
+
void set_launcher(torch::jit::TaskLauncher* launcher) {
|
| 887 |
+
launcher_ = launcher;
|
| 888 |
+
}
|
| 889 |
+
|
| 890 |
+
torch::jit::TaskLauncher* launcher() {
|
| 891 |
+
return launcher_;
|
| 892 |
+
}
|
| 893 |
+
|
| 894 |
+
private:
|
| 895 |
+
std::vector<BlockRunner> block_runners_;
|
| 896 |
+
torch::jit::TaskLauncher* launcher_;
|
| 897 |
+
};
|
| 898 |
+
|
| 899 |
+
class TORCH_API ProcessedNode {
|
| 900 |
+
public:
|
| 901 |
+
ProcessedNode() = default;
|
| 902 |
+
|
| 903 |
+
ProcessedNode(const StaticNodeInfo& other, IValue* values)
|
| 904 |
+
: node_(other.node_),
|
| 905 |
+
fn_(other.fn_),
|
| 906 |
+
inputs_(other.inputs_),
|
| 907 |
+
outputs_offset_(other.outputs_offset_),
|
| 908 |
+
values_(values),
|
| 909 |
+
metadata_(nullptr) {}
|
| 910 |
+
|
| 911 |
+
// These should be noexcept, but some Android build is failing
|
| 912 |
+
// saying the noexcept specification doesn't match the calculated
|
| 913 |
+
// one. Maybe std::variant is throwing it off?
|
| 914 |
+
ProcessedNode(ProcessedNode&&) = default;
|
| 915 |
+
|
| 916 |
+
ProcessedNode(const ProcessedNode&) = delete;
|
| 917 |
+
ProcessedNode& operator=(const ProcessedNode& other) = delete;
|
| 918 |
+
ProcessedNode& operator=(ProcessedNode&&) = default;
|
| 919 |
+
~ProcessedNode() = default;
|
| 920 |
+
|
| 921 |
+
void run();
|
| 922 |
+
|
| 923 |
+
Node* node() const {
|
| 924 |
+
return node_;
|
| 925 |
+
}
|
| 926 |
+
|
| 927 |
+
// Input is readonly
|
| 928 |
+
[[nodiscard]] const IValue& Input(uint32_t i) const {
|
| 929 |
+
return values_[inputs_[i]];
|
| 930 |
+
}
|
| 931 |
+
|
| 932 |
+
// Output is readwrite
|
| 933 |
+
IValue& Output(uint32_t i) {
|
| 934 |
+
DCHECK(i < num_outputs());
|
| 935 |
+
return values_[outputs_offset_ + i];
|
| 936 |
+
}
|
| 937 |
+
|
| 938 |
+
[[nodiscard]] const IValue& Output(uint32_t i) const {
|
| 939 |
+
DCHECK(i < num_outputs());
|
| 940 |
+
return values_[outputs_offset_ + i];
|
| 941 |
+
}
|
| 942 |
+
|
| 943 |
+
uint32_t num_outputs() const {
|
| 944 |
+
DCHECK(fn_ != nullptr);
|
| 945 |
+
return static_cast<uint32_t>(fn_->num_outputs());
|
| 946 |
+
}
|
| 947 |
+
|
| 948 |
+
[[nodiscard]] c10::ArrayRef<const IValue> outputs() const {
|
| 949 |
+
return c10::ArrayRef<const IValue>(
|
| 950 |
+
values_ + outputs_offset_, num_outputs());
|
| 951 |
+
}
|
| 952 |
+
|
| 953 |
+
[[nodiscard]] uint16_t num_inputs() const {
|
| 954 |
+
return inputs_.size();
|
| 955 |
+
}
|
| 956 |
+
|
| 957 |
+
std::vector<IValue> inputs_ivalue_vec() const;
|
| 958 |
+
|
| 959 |
+
bool has_out_variant() const {
|
| 960 |
+
return fn_->kind() == ProcessedFunction::Kind::kOutVariant;
|
| 961 |
+
}
|
| 962 |
+
|
| 963 |
+
bool has_native() const {
|
| 964 |
+
return fn_->kind() == ProcessedFunction::Kind::kNativeFunction;
|
| 965 |
+
}
|
| 966 |
+
|
| 967 |
+
#ifndef PYTORCH_DISABLE_PER_OP_PROFILING
|
| 968 |
+
const char* get_op_name() const {
|
| 969 |
+
return node_->kind().toQualString();
|
| 970 |
+
}
|
| 971 |
+
#endif
|
| 972 |
+
|
| 973 |
+
bool check_outputs_for_memory_overlap() const {
|
| 974 |
+
return fn_->checkMemoryOverlap();
|
| 975 |
+
}
|
| 976 |
+
|
| 977 |
+
void set_outputs_memory_overlap_detected() {
|
| 978 |
+
overlap_detected_ = true;
|
| 979 |
+
}
|
| 980 |
+
|
| 981 |
+
bool outputs_memory_overlap_detected() {
|
| 982 |
+
return overlap_detected_;
|
| 983 |
+
}
|
| 984 |
+
|
| 985 |
+
bool check_and_correct_overlap_with(
|
| 986 |
+
const at::Tensor& input,
|
| 987 |
+
c10::IValue& output);
|
| 988 |
+
void verify_and_correct_memory_overlap();
|
| 989 |
+
|
| 990 |
+
void set_values(IValue* values) {
|
| 991 |
+
DCHECK(values_ == nullptr);
|
| 992 |
+
values_ = values;
|
| 993 |
+
}
|
| 994 |
+
|
| 995 |
+
[[nodiscard]] uint16_t output_ivalue_index(uint16_t i) const {
|
| 996 |
+
DCHECK(i < num_outputs());
|
| 997 |
+
return outputs_offset_ + i;
|
| 998 |
+
}
|
| 999 |
+
// used in debug mode
|
| 1000 |
+
bool verify_no_memory_overlap(bool force_check = false) const;
|
| 1001 |
+
|
| 1002 |
+
// returns pointer to ProcessedNodeMetadata or nullptr if no object is owned
|
| 1003 |
+
ProcessedNodeMetadata* metadata() {
|
| 1004 |
+
return metadata_.get();
|
| 1005 |
+
}
|
| 1006 |
+
|
| 1007 |
+
// attach block_runner to metadata of ProcessedNode
|
| 1008 |
+
void set_metadata(std::vector<BlockRunner> block_runners) {
|
| 1009 |
+
if (metadata_ == nullptr) {
|
| 1010 |
+
metadata_ = std::make_unique<ProcessedNodeMetadata>();
|
| 1011 |
+
}
|
| 1012 |
+
metadata_->set_block_runners(std::move(block_runners));
|
| 1013 |
+
}
|
| 1014 |
+
|
| 1015 |
+
// attach TaskLauncher to metadata of ProcessedNode
|
| 1016 |
+
void set_metadata(torch::jit::TaskLauncher* launcher) {
|
| 1017 |
+
if (metadata_ == nullptr) {
|
| 1018 |
+
metadata_ = std::make_unique<ProcessedNodeMetadata>();
|
| 1019 |
+
}
|
| 1020 |
+
metadata_->set_launcher(launcher);
|
| 1021 |
+
}
|
| 1022 |
+
|
| 1023 |
+
private:
|
| 1024 |
+
[[nodiscard]] bool verify_outputs_dont_overlap_each_other() const;
|
| 1025 |
+
|
| 1026 |
+
[[nodiscard]] bool verify_inputs_dont_overlap_outputs(bool force_check) const;
|
| 1027 |
+
|
| 1028 |
+
Node* node_{nullptr};
|
| 1029 |
+
const ProcessedFunction* fn_{nullptr};
|
| 1030 |
+
ProcessedNodeInputs inputs_;
|
| 1031 |
+
uint16_t outputs_offset_{0};
|
| 1032 |
+
bool overlap_detected_{false};
|
| 1033 |
+
IValue* values_ = nullptr; // unowned
|
| 1034 |
+
// Metadata for ProcessedNode.
|
| 1035 |
+
// 1. prim::If/Loop nodes contains sub-blocks as metadata
|
| 1036 |
+
// 2. prim::fork nodes contains custom executor for async execution
|
| 1037 |
+
std::unique_ptr<ProcessedNodeMetadata> metadata_;
|
| 1038 |
+
};
|
| 1039 |
+
|
| 1040 |
+
// `StaticRuntime` is the owner of the array of IValues (used for constants,
|
| 1041 |
+
// inputs, and intermediate tensors) that all `BlockRunner`s share.
|
| 1042 |
+
// Upon construction, it initializes all block runners. `operator()` simply
|
| 1043 |
+
// forwards the inputs to the top-level block runner. Each `StaticRuntime`
|
| 1044 |
+
// instance corresponds to one `StaticModule`. Multiple `StaticRuntime`
|
| 1045 |
+
// instances can be created; this is useful for multi-threaded execution, since
|
| 1046 |
+
// `operator()` is not thread-safe.
|
| 1047 |
+
class TORCH_API StaticRuntime {
|
| 1048 |
+
public:
|
| 1049 |
+
explicit StaticRuntime(const StaticModule& sm);
|
| 1050 |
+
|
| 1051 |
+
using KeywordArgs = std::unordered_map<std::string, c10::IValue>;
|
| 1052 |
+
c10::IValue operator()(
|
| 1053 |
+
const std::vector<c10::IValue>& args,
|
| 1054 |
+
const KeywordArgs& kwargs = KeywordArgs());
|
| 1055 |
+
c10::IValue operator()(
|
| 1056 |
+
std::vector<c10::IValue>&& args,
|
| 1057 |
+
const KeywordArgs& kwargs = KeywordArgs());
|
| 1058 |
+
|
| 1059 |
+
// runAsync performs inline execution of graph on
|
| 1060 |
+
// caller thread and async execution on taskLauncher
|
| 1061 |
+
// If no custom taskLauncher is specified, execution is done
|
| 1062 |
+
// on inter-op thread pool.
|
| 1063 |
+
c10::intrusive_ptr<c10::ivalue::Future> runAsync(
|
| 1064 |
+
const std::vector<c10::IValue>& args,
|
| 1065 |
+
const KeywordArgs& kwargs = KeywordArgs(),
|
| 1066 |
+
torch::jit::TaskLauncher taskLauncher = at::launch);
|
| 1067 |
+
|
| 1068 |
+
c10::intrusive_ptr<c10::ivalue::Future> runAsync(
|
| 1069 |
+
std::vector<c10::IValue>&& args,
|
| 1070 |
+
const KeywordArgs& kwargs = KeywordArgs(),
|
| 1071 |
+
torch::jit::TaskLauncher taskLauncher = at::launch);
|
| 1072 |
+
|
| 1073 |
+
bool check_for_memory_leak(bool output_returned = true);
|
| 1074 |
+
bool checkOutputTensorMemoryLeaks();
|
| 1075 |
+
|
| 1076 |
+
void deallocateOutputTensors();
|
| 1077 |
+
bool isManagedOutputTensor(const IValue& ivalue) const;
|
| 1078 |
+
void disableManageOutputTensors();
|
| 1079 |
+
|
| 1080 |
+
// Gets the top-level memory planner. Used for testing.
|
| 1081 |
+
const MemoryPlanner* get_memory_planner() const;
|
| 1082 |
+
|
| 1083 |
+
void benchmark(
|
| 1084 |
+
const std::vector<std::vector<c10::IValue>>& args_list,
|
| 1085 |
+
const std::vector<KeywordArgs>& kwargs_list,
|
| 1086 |
+
const uint32_t warmup_runs,
|
| 1087 |
+
const uint32_t main_runs,
|
| 1088 |
+
bool print_per_node_time = false,
|
| 1089 |
+
bool generate_ai_pep_output = false) {
|
| 1090 |
+
block_->benchmark(
|
| 1091 |
+
args_list,
|
| 1092 |
+
kwargs_list,
|
| 1093 |
+
warmup_runs,
|
| 1094 |
+
main_runs,
|
| 1095 |
+
print_per_node_time,
|
| 1096 |
+
generate_ai_pep_output);
|
| 1097 |
+
}
|
| 1098 |
+
|
| 1099 |
+
using IndividualMetrics = BlockRunner::IndividualMetrics;
|
| 1100 |
+
|
| 1101 |
+
IndividualMetrics benchmark_individual_ops(
|
| 1102 |
+
const std::vector<std::vector<c10::IValue>>& args_list,
|
| 1103 |
+
const std::vector<KeywordArgs>& kwargs_list,
|
| 1104 |
+
const int warmup_runs,
|
| 1105 |
+
const int main_runs) {
|
| 1106 |
+
return block_->benchmark_individual_ops(
|
| 1107 |
+
args_list, kwargs_list, warmup_runs, main_runs);
|
| 1108 |
+
}
|
| 1109 |
+
|
| 1110 |
+
private:
|
| 1111 |
+
// An array of IValues with unchanging size/data ptr.
|
| 1112 |
+
class IValueArray {
|
| 1113 |
+
public:
|
| 1114 |
+
IValueArray() = default;
|
| 1115 |
+
explicit IValueArray(size_t size) : array_(allocate(size)), size_(size) {}
|
| 1116 |
+
|
| 1117 |
+
IValue* data() const {
|
| 1118 |
+
return array_.get();
|
| 1119 |
+
}
|
| 1120 |
+
|
| 1121 |
+
size_t size() const {
|
| 1122 |
+
return size_;
|
| 1123 |
+
}
|
| 1124 |
+
|
| 1125 |
+
private:
|
| 1126 |
+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
| 1127 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
|
| 1128 |
+
static std::unique_ptr<IValue[]> allocate(size_t size) {
|
| 1129 |
+
if (size) {
|
| 1130 |
+
return std::make_unique<IValue[]>(size);
|
| 1131 |
+
}
|
| 1132 |
+
return nullptr;
|
| 1133 |
+
}
|
| 1134 |
+
|
| 1135 |
+
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
| 1136 |
+
// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays)
|
| 1137 |
+
std::unique_ptr<IValue[]> array_ = nullptr;
|
| 1138 |
+
size_t size_ = 0;
|
| 1139 |
+
};
|
| 1140 |
+
|
| 1141 |
+
std::unique_ptr<BlockRunner> block_;
|
| 1142 |
+
// for execution of async operations present in graph
|
| 1143 |
+
torch::jit::TaskLauncher async_task_launcher_;
|
| 1144 |
+
IValueArray values_;
|
| 1145 |
+
};
|
| 1146 |
+
|
| 1147 |
+
} // namespace torch::jit
|
| 1148 |
+
C10_DECLARE_bool(static_runtime_disable_debug_memory_overlap_check);
|
| 1149 |
+
|
| 1150 |
+
#else
|
| 1151 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 1152 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/init.h
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#include <torch/csrc/jit/python/pybind_utils.h>
|
| 3 |
+
|
| 4 |
+
namespace torch::jit {
|
| 5 |
+
|
| 6 |
+
void initStaticModuleBindings(PyObject* module);
|
| 7 |
+
|
| 8 |
+
} // namespace torch::jit
|
| 9 |
+
|
| 10 |
+
#else
|
| 11 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 12 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/memory_planner.h
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/jit/runtime/static/impl.h>
|
| 5 |
+
|
| 6 |
+
namespace torch::jit {
|
| 7 |
+
|
| 8 |
+
// A StorageGroup represents a collection of tensors that share backing storage.
|
| 9 |
+
class StorageGroup {
|
| 10 |
+
public:
|
| 11 |
+
// Every storage group must contain at least one tensor.
|
| 12 |
+
explicit StorageGroup(at::Tensor* tensor) : group_{tensor} {}
|
| 13 |
+
|
| 14 |
+
void addTensor(at::Tensor* tensor) {
|
| 15 |
+
group_.push_back(tensor);
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
const std::vector<at::Tensor*>& group() const {
|
| 19 |
+
return group_;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
size_t maxTensorSize() const {
|
| 23 |
+
return max_tensor_size_;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
void setMaxTensorSize(size_t new_size) {
|
| 27 |
+
max_tensor_size_ = new_size;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
size_t numManagedTensors() const {
|
| 31 |
+
return group_.size();
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
private:
|
| 35 |
+
// The size attribute represents the amount of memory that will be
|
| 36 |
+
// allocated for all tensors in this storage group. Initially it
|
| 37 |
+
// is zero, eventually it gets updated by the MemoryPlanner.
|
| 38 |
+
size_t max_tensor_size_ = 0;
|
| 39 |
+
std::vector<at::Tensor*> group_;
|
| 40 |
+
};
|
| 41 |
+
|
| 42 |
+
// A contiguous buffer of `StorageImpl`s
|
| 43 |
+
class ManagedStorages {
|
| 44 |
+
public:
|
| 45 |
+
ManagedStorages();
|
| 46 |
+
|
| 47 |
+
~ManagedStorages();
|
| 48 |
+
|
| 49 |
+
void allocate(size_t capacity);
|
| 50 |
+
|
| 51 |
+
void deallocate();
|
| 52 |
+
|
| 53 |
+
bool is_allocated() const {
|
| 54 |
+
return storages_ != nullptr;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
// Append a new StorageImpl to the buffer. The new StorageImpl is given the
|
| 58 |
+
// same size and allocator as `storageImpl` argument
|
| 59 |
+
void append(at::StorageImpl& storageImpl);
|
| 60 |
+
|
| 61 |
+
at::StorageImpl& operator[](size_t idx) {
|
| 62 |
+
TORCH_INTERNAL_ASSERT(storages_ != nullptr);
|
| 63 |
+
return storages_[idx];
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
const at::StorageImpl& operator[](size_t idx) const {
|
| 67 |
+
TORCH_INTERNAL_ASSERT(storages_ != nullptr);
|
| 68 |
+
return storages_[idx];
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
size_t size() const {
|
| 72 |
+
return size_;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
bool empty() const {
|
| 76 |
+
return size_ == 0;
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
size_t capacity() const {
|
| 80 |
+
return capacity_;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
private:
|
| 84 |
+
// We will use placement-new to add new storages to this buffer
|
| 85 |
+
at::StorageImpl* storages_{nullptr};
|
| 86 |
+
|
| 87 |
+
// Current number of storages that have been placed into the storage buffer
|
| 88 |
+
size_t size_{0};
|
| 89 |
+
|
| 90 |
+
// Total allocated capacity of the storage buffer
|
| 91 |
+
size_t capacity_{0};
|
| 92 |
+
};
|
| 93 |
+
|
| 94 |
+
TORCH_API std::vector<StorageGroup> assignStorageToManagedTensors(
|
| 95 |
+
graph_node_list nodes,
|
| 96 |
+
const ManagedTensorRanges& ranges,
|
| 97 |
+
const c10::FastMap<const Value*, at::Tensor*>& tensor_value_to_tensor);
|
| 98 |
+
|
| 99 |
+
// There are three types of ops in a processed graph in Static Runtime:
|
| 100 |
+
// 1. op with _out variant
|
| 101 |
+
// 2. view-producing op
|
| 102 |
+
// 3. tensor-producing op (could be replaced with type 1 by adding the _out
|
| 103 |
+
// variant to Static Runtime)
|
| 104 |
+
// In Static Runtime, type 2 ops are replaced with their corresponding copy
|
| 105 |
+
// versions when enable_out_variant is enabled and become type 1 ops.The memory
|
| 106 |
+
// planner only manages tensors that are outputs of type 1 ops. For type 3, the
|
| 107 |
+
// output tensors are allocated inside the operator and can't be directly
|
| 108 |
+
// managed by memory planner.
|
| 109 |
+
//
|
| 110 |
+
// Memory planner tries to minimize the number of memory allocations by
|
| 111 |
+
// tracking the output tensors of ops with _out variants with unique DataPtr
|
| 112 |
+
// (part of StorageImpl). It tries to do this in several steps:
|
| 113 |
+
// 1. record the max memory usage for each Tensor with unique DataPtr at the
|
| 114 |
+
// end of each iteration
|
| 115 |
+
// 2. in the next iteration, allocate the buffer for the max total usage and
|
| 116 |
+
// compute the offset of each allocation with regard to the single memory
|
| 117 |
+
// buffer, optionally reusing memory. In the first iteration, we rely on
|
| 118 |
+
// the default allocator for memory allocation.
|
| 119 |
+
// 3. free the buffer at the end of each iteration
|
| 120 |
+
// Steps 1 and 3 are handled by `deallocate()`, and step 2 by `allocate()`.
|
| 121 |
+
// Only models with simple output types are supported, i.e. None, Tensor or
|
| 122 |
+
// List/Tuple/Dict of Tensors. Complex output types such as List of Lists are
|
| 123 |
+
// not supported.
|
| 124 |
+
//
|
| 125 |
+
// Additional Optimizations:
|
| 126 |
+
//
|
| 127 |
+
// [Borrowed IValue Outputs]
|
| 128 |
+
// A few native ops (notably, `static_runtime::dict_unpack` and
|
| 129 |
+
// `static_runtime::VarTupleUnpack`) simply unpack IValues to a bunch of
|
| 130 |
+
// outputs without modification. For example, `dict_unpack` does the following:
|
| 131 |
+
// for each key in inputs:
|
| 132 |
+
// output[i] = dict_input[key]
|
| 133 |
+
// To avoid refcount bumps, the outputs of these ops are non-owning references.
|
| 134 |
+
// This requires special logic in the memory planner - when adding an op that
|
| 135 |
+
// borrows outputs, be sure that the memory planner is updated accordingly!
|
| 136 |
+
//
|
| 137 |
+
// [Managed Output Tensors]
|
| 138 |
+
// The memory planner is able to manage output tensors if the appropriate
|
| 139 |
+
// `StaticModuleOptions` are set. However, the memory planner handles output
|
| 140 |
+
// tensors separately from regular intermediate tensors:
|
| 141 |
+
// 1. They don't participate in memory reuse.
|
| 142 |
+
// 2. The memory planner cannot reclaim their backing storage until they have
|
| 143 |
+
// been explicitly freed by the client.
|
| 144 |
+
|
| 145 |
+
class MemoryPlanner {
|
| 146 |
+
public:
|
| 147 |
+
MemoryPlanner(
|
| 148 |
+
BlockRunner* block_runner,
|
| 149 |
+
const BlockInfo& block_info,
|
| 150 |
+
bool enable_out_variant,
|
| 151 |
+
bool manage_output_tensors);
|
| 152 |
+
|
| 153 |
+
// disable copying and moving
|
| 154 |
+
MemoryPlanner(const MemoryPlanner&) = delete;
|
| 155 |
+
MemoryPlanner& operator=(const MemoryPlanner&) = delete;
|
| 156 |
+
MemoryPlanner(MemoryPlanner&&) = delete;
|
| 157 |
+
MemoryPlanner& operator=(MemoryPlanner&&) = delete;
|
| 158 |
+
virtual ~MemoryPlanner() = default;
|
| 159 |
+
|
| 160 |
+
void allocate();
|
| 161 |
+
void deallocate();
|
| 162 |
+
void deallocateOutputTensors();
|
| 163 |
+
|
| 164 |
+
size_t total_num_managed_tensors() const {
|
| 165 |
+
return num_managed_tensors_;
|
| 166 |
+
}
|
| 167 |
+
|
| 168 |
+
size_t total_reused_tensors() const {
|
| 169 |
+
return reused_tensors_;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
size_t total_num_managed_output_tensors() const {
|
| 173 |
+
return managed_output_tensors_.size();
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
[[nodiscard]] size_t total_num_unmanaged() const {
|
| 177 |
+
return num_unmanaged_non_scalars() + num_unmanaged_scalars();
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
[[nodiscard]] size_t num_unmanaged_non_scalars() const {
|
| 181 |
+
return unmanaged_ivalues_.size() + unmanaged_borrowed_ivalues_.size();
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
[[nodiscard]] size_t num_unmanaged_scalars() const {
|
| 185 |
+
return num_unmanaged_scalar_ivalues_;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
size_t total_managed() const {
|
| 189 |
+
return managed_bytes_;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
size_t numOutputBufferBytes() const {
|
| 193 |
+
return output_buffer_bytes_;
|
| 194 |
+
}
|
| 195 |
+
|
| 196 |
+
// Check if `ivalue` is contained as a managed tensor. Only used in DCHECK().
|
| 197 |
+
bool isManagedOutputTensor(const IValue& ivalue) const {
|
| 198 |
+
if (!output_buffer_ || // output buffer got already deallocated.
|
| 199 |
+
output_buffer_bytes_ == 0 || // memory planning is not yet initialized.
|
| 200 |
+
!ivalue.isTensor() // a non-tensor is never managed
|
| 201 |
+
) {
|
| 202 |
+
return false;
|
| 203 |
+
}
|
| 204 |
+
const auto& tensor = ivalue.toTensor();
|
| 205 |
+
if (!tensor.has_storage() || !tensor.storage().data_ptr()) {
|
| 206 |
+
return false;
|
| 207 |
+
}
|
| 208 |
+
// TODO: Improve this once D31357486 is landed.
|
| 209 |
+
uint8_t* tensor_ptr =
|
| 210 |
+
static_cast<uint8_t*>(tensor.storage().data_ptr().get());
|
| 211 |
+
uint8_t* buffer_start = static_cast<uint8_t*>(output_buffer_.get());
|
| 212 |
+
uint8_t* buffer_end = buffer_start + output_buffer_bytes_;
|
| 213 |
+
return buffer_start <= tensor_ptr && tensor_ptr < buffer_end;
|
| 214 |
+
}
|
| 215 |
+
|
| 216 |
+
bool isManagedStorageImpl(const at::StorageImpl* impl) const {
|
| 217 |
+
if (storages_.empty()) {
|
| 218 |
+
return false;
|
| 219 |
+
}
|
| 220 |
+
// Comparing pointers that aren't within the same array is
|
| 221 |
+
// UB. We're doing fancy memory allocation stuff, so we cast to an
|
| 222 |
+
// integer type and carry on.
|
| 223 |
+
const auto impl_p = reinterpret_cast<uintptr_t>(impl);
|
| 224 |
+
const auto start = reinterpret_cast<uintptr_t>(&storages_[0]);
|
| 225 |
+
const auto end =
|
| 226 |
+
reinterpret_cast<uintptr_t>(&storages_[0] + storages_.size());
|
| 227 |
+
return impl_p >= start && impl_p < end;
|
| 228 |
+
}
|
| 229 |
+
|
| 230 |
+
bool overlapWithInternalBuffer(void* data_ptr) {
|
| 231 |
+
return buffer_start_ <= data_ptr && data_ptr < buffer_end_;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
protected:
|
| 235 |
+
uint8_t* allocateBuffer(size_t num_bytes);
|
| 236 |
+
|
| 237 |
+
size_t managed_bytes_{0};
|
| 238 |
+
size_t reused_tensors_{0};
|
| 239 |
+
|
| 240 |
+
// We allocate StorageImpls ourselves so that 1) we don't have to do
|
| 241 |
+
// an extra two loads per Tensor (which will likely miss in the CPU
|
| 242 |
+
// data cache) first reading the Storage (i.e., StorageImpl pointer)
|
| 243 |
+
// from the TensorImpl object and then second dereferencing it and
|
| 244 |
+
// 2) our memory access pattern during allocate() has high locality.
|
| 245 |
+
// We don't have any guarantee that the model doesn't change the
|
| 246 |
+
// Storage for managed tensors out from under us during execution,
|
| 247 |
+
// so we have to check the StorageImpls each time we deallocate.
|
| 248 |
+
ManagedStorages storages_;
|
| 249 |
+
|
| 250 |
+
// Contains the size (in bytes) of the data to be allocated for each storage
|
| 251 |
+
std::vector<size_t> storages_nbytes_;
|
| 252 |
+
|
| 253 |
+
private:
|
| 254 |
+
// ivalues created in one run but not managed by MemoryPlanner
|
| 255 |
+
std::vector<IValue*> unmanaged_ivalues_;
|
| 256 |
+
|
| 257 |
+
// Special class of unmanaged values: some native ops create IValues
|
| 258 |
+
// in a "borrowed" state that can and must be cleaned up without a
|
| 259 |
+
// reference count decrement.
|
| 260 |
+
std::vector<IValue*> unmanaged_borrowed_ivalues_;
|
| 261 |
+
|
| 262 |
+
// Even more special class of unmanaged values: if select_tensor
|
| 263 |
+
// outputs are outputs of the graph, then they need to be restored
|
| 264 |
+
// to an ordinary "strong reference" state.
|
| 265 |
+
std::vector<IValue*> borrowed_ivalues_needing_incref_;
|
| 266 |
+
|
| 267 |
+
std::vector<std::pair<size_t, at::Tensor*>> managed_output_tensors_;
|
| 268 |
+
at::DataPtr buffer_; // allocated each time we call Run()
|
| 269 |
+
uint8_t* buffer_start_{nullptr};
|
| 270 |
+
uint8_t* buffer_end_{nullptr};
|
| 271 |
+
size_t num_managed_tensors_{0};
|
| 272 |
+
size_t num_unmanaged_scalar_ivalues_{0};
|
| 273 |
+
|
| 274 |
+
at::DataPtr output_buffer_;
|
| 275 |
+
size_t output_buffer_bytes_{0};
|
| 276 |
+
|
| 277 |
+
virtual void allocateManagedTensors() = 0;
|
| 278 |
+
virtual void deallocateManagedTensors() = 0;
|
| 279 |
+
|
| 280 |
+
void allocateOutputTensors();
|
| 281 |
+
};
|
| 282 |
+
|
| 283 |
+
class StandardMemoryPlanner : public MemoryPlanner {
|
| 284 |
+
public:
|
| 285 |
+
StandardMemoryPlanner(
|
| 286 |
+
BlockRunner* block_runner,
|
| 287 |
+
const BlockInfo& block_info,
|
| 288 |
+
bool enable_out_variant,
|
| 289 |
+
bool manage_output_tensors,
|
| 290 |
+
bool optimize_memory);
|
| 291 |
+
|
| 292 |
+
protected:
|
| 293 |
+
void allocateManagedTensors() override;
|
| 294 |
+
void deallocateManagedTensors() override;
|
| 295 |
+
|
| 296 |
+
std::vector<StorageGroup> managed_tensors_;
|
| 297 |
+
};
|
| 298 |
+
|
| 299 |
+
} // namespace torch::jit
|
| 300 |
+
|
| 301 |
+
#else
|
| 302 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 303 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/ops.h
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <ATen/Utils.h>
|
| 5 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 6 |
+
#include <torch/csrc/jit/runtime/static/impl.h>
|
| 7 |
+
|
| 8 |
+
namespace at::native {
|
| 9 |
+
at::Tensor& reshape_copy_out(
|
| 10 |
+
at::Tensor& out,
|
| 11 |
+
const at::Tensor& self,
|
| 12 |
+
const at::DimVector& proposed_shape,
|
| 13 |
+
bool infer_size = true);
|
| 14 |
+
at::Tensor& to_copy_out(
|
| 15 |
+
Tensor& out,
|
| 16 |
+
const Tensor& self,
|
| 17 |
+
bool non_blocking,
|
| 18 |
+
bool copy_strides,
|
| 19 |
+
std::optional<MemoryFormat> memory_format);
|
| 20 |
+
} // namespace at::native
|
| 21 |
+
|
| 22 |
+
namespace torch::jit {
|
| 23 |
+
|
| 24 |
+
using SROpFunctor = SROperator (*)(Node* n);
|
| 25 |
+
struct SROperatorFunctor {
|
| 26 |
+
virtual SROperator Generate(Node* /*unused*/) {
|
| 27 |
+
SROperator out;
|
| 28 |
+
return out;
|
| 29 |
+
}
|
| 30 |
+
virtual ~SROperatorFunctor() = default;
|
| 31 |
+
};
|
| 32 |
+
|
| 33 |
+
TORCH_DECLARE_REGISTRY(SROperatorRegistry, SROperatorFunctor);
|
| 34 |
+
|
| 35 |
+
#define REGISTER_OPERATOR_FUNCTOR(name, id, ...) \
|
| 36 |
+
struct SROperatorFunctor_##id : public SROperatorFunctor { \
|
| 37 |
+
SROpFunctor fn = __VA_ARGS__; \
|
| 38 |
+
SROperator Generate(Node* n) override { \
|
| 39 |
+
return fn(n); \
|
| 40 |
+
} \
|
| 41 |
+
}; \
|
| 42 |
+
C10_REGISTER_CLASS(SROperatorRegistry, name, SROperatorFunctor_##id)
|
| 43 |
+
|
| 44 |
+
TORCH_DECLARE_REGISTRY(SRNativeOperatorRegistry, SROperatorFunctor);
|
| 45 |
+
#define REGISTER_NATIVE_OPERATOR_FUNCTOR(name, id, ...) \
|
| 46 |
+
struct SRNativeOperatorFunctor_##id : public SROperatorFunctor { \
|
| 47 |
+
SROpFunctor fn = __VA_ARGS__; \
|
| 48 |
+
SROperator Generate(Node* n) override { \
|
| 49 |
+
return fn(n); \
|
| 50 |
+
} \
|
| 51 |
+
}; \
|
| 52 |
+
C10_REGISTER_CLASS( \
|
| 53 |
+
SRNativeOperatorRegistry, name, SRNativeOperatorFunctor_##id)
|
| 54 |
+
|
| 55 |
+
inline at::Tensor create_empty_from(const at::Tensor& t) {
|
| 56 |
+
return at::detail::empty_cpu(
|
| 57 |
+
{0},
|
| 58 |
+
c10::typeMetaToScalarType(t.dtype()),
|
| 59 |
+
t.layout(),
|
| 60 |
+
t.device(),
|
| 61 |
+
std::nullopt,
|
| 62 |
+
std::nullopt);
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
inline at::Tensor create_empty_from(
|
| 66 |
+
at::IntArrayRef sizes,
|
| 67 |
+
const at::Tensor& t) {
|
| 68 |
+
return at::detail::empty_cpu(
|
| 69 |
+
sizes,
|
| 70 |
+
c10::typeMetaToScalarType(t.dtype()),
|
| 71 |
+
t.layout(),
|
| 72 |
+
t.device(),
|
| 73 |
+
std::nullopt,
|
| 74 |
+
std::nullopt);
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
inline at::Tensor create_empty(c10::ScalarType dtype) {
|
| 78 |
+
return at::detail::empty_cpu(
|
| 79 |
+
{0}, dtype, std::nullopt, std::nullopt, std::nullopt, std::nullopt);
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
inline at::Tensor create_empty_from(
|
| 83 |
+
const at::Tensor& t,
|
| 84 |
+
c10::ScalarType dtype) {
|
| 85 |
+
return at::detail::empty_cpu(
|
| 86 |
+
{0}, dtype, t.layout(), t.device(), std::nullopt, std::nullopt);
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
inline at::Tensor create_empty_from(const at::Tensor& t, c10::Layout layout) {
|
| 90 |
+
return at::detail::empty_cpu(
|
| 91 |
+
{0},
|
| 92 |
+
c10::typeMetaToScalarType(t.dtype()),
|
| 93 |
+
layout,
|
| 94 |
+
t.device(),
|
| 95 |
+
std::nullopt,
|
| 96 |
+
std::nullopt);
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
inline at::Tensor create_empty_from(const at::Tensor& t, c10::Device device) {
|
| 100 |
+
return at::detail::empty_cpu(
|
| 101 |
+
{0},
|
| 102 |
+
c10::typeMetaToScalarType(t.dtype()),
|
| 103 |
+
t.layout(),
|
| 104 |
+
device,
|
| 105 |
+
std::nullopt,
|
| 106 |
+
std::nullopt);
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
inline at::Tensor create_empty_from(
|
| 110 |
+
const at::Tensor& t,
|
| 111 |
+
c10::MemoryFormat memory_format) {
|
| 112 |
+
return at::detail::empty_cpu(
|
| 113 |
+
{0},
|
| 114 |
+
c10::typeMetaToScalarType(t.dtype()),
|
| 115 |
+
t.layout(),
|
| 116 |
+
t.device(),
|
| 117 |
+
std::nullopt,
|
| 118 |
+
memory_format);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
inline at::Tensor create_empty_from(
|
| 122 |
+
const at::Tensor& t,
|
| 123 |
+
c10::ScalarType dtype,
|
| 124 |
+
c10::MemoryFormat memory_format) {
|
| 125 |
+
return at::detail::empty_cpu(
|
| 126 |
+
{0}, dtype, t.layout(), t.device(), std::nullopt, memory_format);
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
inline bool checkResizedDataPtr(at::Tensor& t) {
|
| 130 |
+
auto const prev_data_ptr = t.data_ptr();
|
| 131 |
+
t.resize_({0});
|
| 132 |
+
return prev_data_ptr == t.data_ptr();
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
inline void fastResizeToZero(at::Tensor& t) {
|
| 136 |
+
t.unsafeGetTensorImpl()->set_sizes_contiguous({0});
|
| 137 |
+
TORCH_INTERNAL_ASSERT_DEBUG_ONLY(checkResizedDataPtr(t));
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
// check if an op has an out variant registered in Static Runtime
|
| 141 |
+
bool opIsRegistered(const c10::Symbol& op_name);
|
| 142 |
+
// check if Static Runtime can run an op natively.
|
| 143 |
+
// prim ops that are implemented directly in the jit interpreter are implemented
|
| 144 |
+
// as native ops in Static Runtime
|
| 145 |
+
bool nativeOpIsRegistered(const c10::Symbol& op_name);
|
| 146 |
+
|
| 147 |
+
bool canReuseInputsOutputs(
|
| 148 |
+
Node* n,
|
| 149 |
+
const c10::FastMap<Node*, bool>& node_has_out_variant);
|
| 150 |
+
bool isOptimizableContainerType(
|
| 151 |
+
Node* n,
|
| 152 |
+
const c10::FastMap<Node*, bool>& node_has_out_variant);
|
| 153 |
+
|
| 154 |
+
SROperator getOutOfPlaceOperation(Node* n);
|
| 155 |
+
SROperator getNativeOperation(Node* n);
|
| 156 |
+
|
| 157 |
+
bool hasVarArgs(Node* n);
|
| 158 |
+
|
| 159 |
+
inline std::string PrintNode(const Node* node) {
|
| 160 |
+
std::ostringstream ss;
|
| 161 |
+
node->print(ss, 0, nullptr, false);
|
| 162 |
+
return ss.str();
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
inline void LogAndDumpSchema(const Node* node) {
|
| 166 |
+
VLOG(1) << "Found schema mismatch for: " << node->schema();
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
inline bool sr_schema_check(torch::jit::Node* /*unused*/) {
|
| 170 |
+
return true;
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
template <typename Schema, typename... Schemas>
|
| 174 |
+
bool sr_schema_check(
|
| 175 |
+
torch::jit::Node* node,
|
| 176 |
+
Schema&& first,
|
| 177 |
+
Schemas&&... rest) {
|
| 178 |
+
auto is_match = node->matches(first) || sr_schema_check(node, rest...);
|
| 179 |
+
if (!is_match) {
|
| 180 |
+
torch::jit::LogAndDumpSchema(node);
|
| 181 |
+
}
|
| 182 |
+
return is_match;
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
bool sr_schema_check_kind(torch::jit::Node* node, c10::Symbol node_kind);
|
| 186 |
+
} // namespace torch::jit
|
| 187 |
+
|
| 188 |
+
C10_DECLARE_bool(static_runtime_enable_fast_math);
|
| 189 |
+
|
| 190 |
+
#else
|
| 191 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 192 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/passes.h
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 3 |
+
|
| 4 |
+
namespace torch::jit {
|
| 5 |
+
|
| 6 |
+
TORCH_API void FuseInferenceOpsForSparseNN(
|
| 7 |
+
std::shared_ptr<torch::jit::Graph>& graph);
|
| 8 |
+
|
| 9 |
+
TORCH_API void EliminateTrivialEquallySplit(
|
| 10 |
+
std::shared_ptr<torch::jit::Graph>& graph);
|
| 11 |
+
|
| 12 |
+
TORCH_API void FuseListUnpack(std::shared_ptr<torch::jit::Graph>& graph);
|
| 13 |
+
|
| 14 |
+
// If outputs_are_immutable is set to false, don't replace the view ops that
|
| 15 |
+
// produce aliases of graph outputs with the copy version.
|
| 16 |
+
TORCH_API void ReplaceWithCopy(
|
| 17 |
+
std::shared_ptr<torch::jit::Graph>& graph,
|
| 18 |
+
bool outputs_are_immutable = true);
|
| 19 |
+
|
| 20 |
+
TORCH_API void ReplacePermuteWithCopy(
|
| 21 |
+
std::shared_ptr<torch::jit::Graph>& graph,
|
| 22 |
+
bool outputs_are_immutable = true);
|
| 23 |
+
|
| 24 |
+
TORCH_API void ReplaceWithMaybeCopy(
|
| 25 |
+
std::shared_ptr<torch::jit::Graph>& graph,
|
| 26 |
+
bool outputs_are_immutable = true);
|
| 27 |
+
|
| 28 |
+
TORCH_API void RemoveImmutableInputDictLookups(
|
| 29 |
+
std::shared_ptr<torch::jit::Graph>& graph);
|
| 30 |
+
|
| 31 |
+
TORCH_API bool graphHasOp(std::shared_ptr<Graph>& graph, const char* op_name);
|
| 32 |
+
|
| 33 |
+
TORCH_API bool forwardHasOp(const Module& module, const char* op_name);
|
| 34 |
+
|
| 35 |
+
TORCH_API void FuseSignLog1P(std::shared_ptr<Graph>& graph);
|
| 36 |
+
|
| 37 |
+
TORCH_API void UseVariadicTupleUnpack(const std::shared_ptr<Graph>& graph);
|
| 38 |
+
|
| 39 |
+
// c10::Symbol::fromQualString is a bit long to type everywhere, and
|
| 40 |
+
// we can't use a `using` statement since it's a static class function.
|
| 41 |
+
inline c10::Symbol fromQualString(const std::string& qual_string) {
|
| 42 |
+
return c10::Symbol::fromQualString(qual_string);
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
// [Create owned refs for special values]
|
| 46 |
+
// StaticRuntimeBlockRunner moves its outputs to the return value at the end of
|
| 47 |
+
// run_impl. However, there's a corner case where this can cause problems. If
|
| 48 |
+
// we return a constant, then the only reference in the constants_ array can
|
| 49 |
+
// be destroyed by this move.
|
| 50 |
+
// We could add special logic to handle this in run_impl. But since this is a
|
| 51 |
+
// relatively rare corner case, it's simpler to just add an op that does nothing
|
| 52 |
+
// but create an owned reference to its input. This owned reference can be
|
| 53 |
+
// safely moved out of StaticRuntimeBlockRunner. Note that for scalars,
|
| 54 |
+
// this actually does a copy.
|
| 55 |
+
// Note that we have to do the same thing if we are returning a value from an
|
| 56 |
+
// outer scope in a sub-block.
|
| 57 |
+
TORCH_API void CreateOwnedRefsForSpecialValues(Graph& graph);
|
| 58 |
+
|
| 59 |
+
// [Force non-empty outputs]
|
| 60 |
+
// It is technically possible for sub-blocks to not return anything. This is
|
| 61 |
+
// problematic for StaticRuntimeBlockRunner because it assumes that at least one
|
| 62 |
+
// output is being returned. Rather than slowing down SR with special logic for
|
| 63 |
+
// this corner case, we simply force blocks that return nothing to return None.
|
| 64 |
+
TORCH_API void ForceNonEmptyOutputs(Graph& graph);
|
| 65 |
+
|
| 66 |
+
TORCH_API void UseVariadicGroupedAccessor(const std::shared_ptr<Graph>& graph);
|
| 67 |
+
|
| 68 |
+
TORCH_API void EliminateExtraPermuteOps(std::shared_ptr<Graph>& graph);
|
| 69 |
+
|
| 70 |
+
TORCH_API void EliminateNoOpSlice(std::shared_ptr<Graph>& graph);
|
| 71 |
+
|
| 72 |
+
TORCH_API void UseSplitAndSqueeze(std::shared_ptr<Graph>& graph);
|
| 73 |
+
|
| 74 |
+
// [Remove unnecessary outputs]]
|
| 75 |
+
// Removes outputs to reduce compute when it is not used later in the graph.
|
| 76 |
+
// Currently used to remove the max_indices output of embedding_bag, which
|
| 77 |
+
// isn't necessary to compute the main output.
|
| 78 |
+
TORCH_API void RemoveUnnecessaryOutputs(std::shared_ptr<Graph>& graph);
|
| 79 |
+
|
| 80 |
+
TORCH_API void RemoveUnnecessaryEmbeddingBagOutputs(
|
| 81 |
+
std::shared_ptr<Graph>& graph);
|
| 82 |
+
|
| 83 |
+
TORCH_API void FuseClampNaNToNum(std::shared_ptr<Graph>& graph);
|
| 84 |
+
|
| 85 |
+
TORCH_API void UseInPlaceGetRealInputsFromOptionalInputsV2(
|
| 86 |
+
std::shared_ptr<Graph>& graph);
|
| 87 |
+
|
| 88 |
+
TORCH_API void PrepackWeights(std::shared_ptr<Graph>& graph);
|
| 89 |
+
|
| 90 |
+
} // namespace torch::jit
|
| 91 |
+
|
| 92 |
+
C10_DECLARE_bool(enable_clip_ranges_gather_fusions);
|
| 93 |
+
|
| 94 |
+
#else
|
| 95 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 96 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/processed_node_wrapper.h
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <ATen/ATen.h>
|
| 5 |
+
#include <torch/csrc/jit/runtime/static/impl.h>
|
| 6 |
+
|
| 7 |
+
namespace torch::jit {
|
| 8 |
+
|
| 9 |
+
// The following class facilitates code reuse between ProcessedNodeInputWrapper
|
| 10 |
+
// and ProcessedNodeOutputWrapper via CRTP
|
| 11 |
+
template <typename DerivedWrapper>
|
| 12 |
+
class ProcessedNodeWrapperBase {
|
| 13 |
+
public:
|
| 14 |
+
class ProcessedNodeWrapperBaseIter {
|
| 15 |
+
public:
|
| 16 |
+
using iterator_category = std::forward_iterator_tag;
|
| 17 |
+
using value_type = at::Tensor;
|
| 18 |
+
using difference_type = size_t;
|
| 19 |
+
using pointer = const at::Tensor*;
|
| 20 |
+
using reference = const at::Tensor&;
|
| 21 |
+
|
| 22 |
+
ProcessedNodeWrapperBaseIter() = default;
|
| 23 |
+
|
| 24 |
+
ProcessedNodeWrapperBaseIter(
|
| 25 |
+
const DerivedWrapper* container,
|
| 26 |
+
size_t start_idx)
|
| 27 |
+
: container_(container), idx_(start_idx) {}
|
| 28 |
+
|
| 29 |
+
ProcessedNodeWrapperBaseIter& operator++() {
|
| 30 |
+
TORCH_DCHECK_NE(idx_, container_->size());
|
| 31 |
+
++idx_;
|
| 32 |
+
return *this;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
ProcessedNodeWrapperBaseIter operator++(int) {
|
| 36 |
+
ProcessedNodeWrapperBaseIter old = *this;
|
| 37 |
+
++(*this);
|
| 38 |
+
return old;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
reference operator*() const {
|
| 42 |
+
TORCH_CHECK(container_ != nullptr);
|
| 43 |
+
return (*container_)[idx_];
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
pointer operator->() const {
|
| 47 |
+
TORCH_CHECK(container_ != nullptr);
|
| 48 |
+
return &(*container_)[idx_];
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
friend bool operator==(
|
| 52 |
+
ProcessedNodeWrapperBaseIter lhs,
|
| 53 |
+
ProcessedNodeWrapperBaseIter rhs) {
|
| 54 |
+
TORCH_DCHECK_EQ(lhs.container_, rhs.container_);
|
| 55 |
+
return lhs.idx_ == rhs.idx_;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
friend bool operator!=(
|
| 59 |
+
ProcessedNodeWrapperBaseIter lhs,
|
| 60 |
+
ProcessedNodeWrapperBaseIter rhs) {
|
| 61 |
+
return !(lhs == rhs);
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
private:
|
| 65 |
+
const DerivedWrapper* container_ = nullptr;
|
| 66 |
+
size_t idx_ = 0;
|
| 67 |
+
};
|
| 68 |
+
|
| 69 |
+
// NB: to mimic the behavior of at::ArrayRef, both iterators are
|
| 70 |
+
// the const version.
|
| 71 |
+
using iterator = ProcessedNodeWrapperBaseIter;
|
| 72 |
+
using const_iterator = ProcessedNodeWrapperBaseIter;
|
| 73 |
+
using size_type = size_t;
|
| 74 |
+
using value_type = at::Tensor;
|
| 75 |
+
|
| 76 |
+
explicit ProcessedNodeWrapperBase(ProcessedNode& pnode) : pnode_(pnode) {}
|
| 77 |
+
|
| 78 |
+
iterator begin() {
|
| 79 |
+
return ProcessedNodeWrapperBaseIter(static_cast<DerivedWrapper*>(this), 0);
|
| 80 |
+
}
|
| 81 |
+
iterator end() {
|
| 82 |
+
return ProcessedNodeWrapperBaseIter(
|
| 83 |
+
static_cast<DerivedWrapper*>(this),
|
| 84 |
+
static_cast<DerivedWrapper*>(this)->size());
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
const_iterator begin() const {
|
| 88 |
+
return ProcessedNodeWrapperBaseIter(
|
| 89 |
+
static_cast<const DerivedWrapper*>(this), 0);
|
| 90 |
+
}
|
| 91 |
+
const_iterator end() const {
|
| 92 |
+
return ProcessedNodeWrapperBaseIter(
|
| 93 |
+
static_cast<const DerivedWrapper*>(this),
|
| 94 |
+
static_cast<const DerivedWrapper*>(this)->size());
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
const_iterator cbegin() const {
|
| 98 |
+
return ProcessedNodeWrapperBaseIter(
|
| 99 |
+
static_cast<const DerivedWrapper*>(this), 0);
|
| 100 |
+
}
|
| 101 |
+
const_iterator cend() const {
|
| 102 |
+
return ProcessedNodeWrapperBaseIter(
|
| 103 |
+
static_cast<const DerivedWrapper*>(this),
|
| 104 |
+
static_cast<const DerivedWrapper*>(this)->size());
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
bool empty() const {
|
| 108 |
+
return static_cast<const DerivedWrapper*>(this)->size() == 0;
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
protected:
|
| 112 |
+
ProcessedNode& pnode_;
|
| 113 |
+
};
|
| 114 |
+
|
| 115 |
+
// A ProcessedNodeWrapperBase lets us use ProcessedNode directly in a context
|
| 116 |
+
// where a container of IValues is expected. This trick is handy for avoiding
|
| 117 |
+
// refcount bumps in perf-sensitive native ops. For example, suppose we have an
|
| 118 |
+
// op that takes a list of tensors as an argument and we've turned the op into a
|
| 119 |
+
// variadic variant in static runtime. To use the PyTorch library implementation
|
| 120 |
+
// of the op, we would have to pack the variadic arguments into a list:
|
| 121 |
+
// std::vector<Tensor> tensor_list;
|
| 122 |
+
// tensor_list.reserve(pnode->num_outputs());
|
| 123 |
+
// for (const auto i : c10::irange(pnode->num_inputs())
|
| 124 |
+
// tensor_list.push_back(pnode->Input(i).toTensor());
|
| 125 |
+
// op_impl(tensor_list);
|
| 126 |
+
// Using ProcessedNodeWrapperBase, we can avoid this round of refcount bumps.
|
| 127 |
+
// All we need to do is turn `op_impl` into a template and pass it
|
| 128 |
+
// ProcessedNodeInputWrapper(*pnode)!
|
| 129 |
+
class ProcessedNodeInputWrapper
|
| 130 |
+
: public ProcessedNodeWrapperBase<ProcessedNodeInputWrapper> {
|
| 131 |
+
public:
|
| 132 |
+
// The last `back_elements_ignored` elements are not considered.
|
| 133 |
+
// Same for the first `front_elements_ignored` elements.
|
| 134 |
+
// This is useful for ops where
|
| 135 |
+
// only the first N elements are tensors (N < inputs.size()).
|
| 136 |
+
// For instance, the last argument to VarStack is an integer dimension.
|
| 137 |
+
explicit ProcessedNodeInputWrapper(
|
| 138 |
+
ProcessedNode& pnode,
|
| 139 |
+
size_t front_elements_ignored = 0,
|
| 140 |
+
size_t back_elements_ignored = 1)
|
| 141 |
+
: ProcessedNodeWrapperBase<ProcessedNodeInputWrapper>(pnode),
|
| 142 |
+
front_elements_ignored_(front_elements_ignored),
|
| 143 |
+
back_elements_ignored_(back_elements_ignored) {
|
| 144 |
+
TORCH_CHECK(front_elements_ignored_ <= pnode_.num_inputs());
|
| 145 |
+
TORCH_CHECK(
|
| 146 |
+
back_elements_ignored_ <=
|
| 147 |
+
pnode_.num_inputs() - front_elements_ignored_);
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
size_t size() const {
|
| 151 |
+
return pnode_.num_inputs() - back_elements_ignored_ -
|
| 152 |
+
front_elements_ignored_;
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
const at::Tensor& operator[](size_t idx) const {
|
| 156 |
+
TORCH_CHECK(idx < size());
|
| 157 |
+
return pnode_.Input(front_elements_ignored_ + idx).toTensor();
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
const at::Tensor& front() const {
|
| 161 |
+
TORCH_CHECK(
|
| 162 |
+
!empty(),
|
| 163 |
+
"Attempted to access front() of empty ProcessedNodeInputWrapper");
|
| 164 |
+
return pnode_.Input(front_elements_ignored_).toTensor();
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
const at::Tensor& back() const {
|
| 168 |
+
TORCH_CHECK(
|
| 169 |
+
!empty(),
|
| 170 |
+
"Attempted to access back() of empty ProcessedNodeInputWrapper");
|
| 171 |
+
return pnode_.Input(pnode_.num_inputs() - back_elements_ignored_ - 1)
|
| 172 |
+
.toTensor();
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
private:
|
| 176 |
+
size_t front_elements_ignored_;
|
| 177 |
+
size_t back_elements_ignored_;
|
| 178 |
+
};
|
| 179 |
+
|
| 180 |
+
// Similar to ProcessedNodeInputWrapper, but wraps outputs and allows for
|
| 181 |
+
// writing.
|
| 182 |
+
class ProcessedNodeOutputWrapper
|
| 183 |
+
: public ProcessedNodeWrapperBase<ProcessedNodeOutputWrapper> {
|
| 184 |
+
public:
|
| 185 |
+
using ProcessedNodeWrapperBase<
|
| 186 |
+
ProcessedNodeOutputWrapper>::ProcessedNodeWrapperBase;
|
| 187 |
+
|
| 188 |
+
size_t size() const {
|
| 189 |
+
return pnode_.num_outputs();
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
at::Tensor& operator[](size_t idx) const {
|
| 193 |
+
TORCH_CHECK(idx < size());
|
| 194 |
+
return pnode_.Output(idx).toTensor();
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
at::Tensor& front() const {
|
| 198 |
+
TORCH_CHECK(
|
| 199 |
+
!empty(),
|
| 200 |
+
"Attempted to access front() of empty ProcessedNodeOutputWrapper");
|
| 201 |
+
return pnode_.Output(0).toTensor();
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
at::Tensor& back() const {
|
| 205 |
+
TORCH_CHECK(
|
| 206 |
+
!empty(),
|
| 207 |
+
"Attempted to access back() of empty ProcessedNodeOutputWrapper");
|
| 208 |
+
return pnode_.Output(size() - 1).toTensor();
|
| 209 |
+
}
|
| 210 |
+
};
|
| 211 |
+
|
| 212 |
+
} // namespace torch::jit
|
| 213 |
+
|
| 214 |
+
#else
|
| 215 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 216 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/static_method.h
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/api/include/torch/imethod.h>
|
| 5 |
+
#include <torch/csrc/jit/runtime/static/impl.h>
|
| 6 |
+
|
| 7 |
+
namespace torch::jit {
|
| 8 |
+
|
| 9 |
+
class StaticMethod : public torch::IMethod {
|
| 10 |
+
public:
|
| 11 |
+
StaticMethod(
|
| 12 |
+
std::shared_ptr<StaticModule> static_module,
|
| 13 |
+
std::string method_name)
|
| 14 |
+
: static_module_(std::move(static_module)),
|
| 15 |
+
method_name_(std::move(method_name)) {
|
| 16 |
+
TORCH_CHECK(static_module_);
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
c10::IValue operator()(
|
| 20 |
+
std::vector<IValue> args,
|
| 21 |
+
const IValueMap& kwargs = IValueMap()) const override {
|
| 22 |
+
return (*static_module_)(std::move(args), kwargs);
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
const std::string& name() const override {
|
| 26 |
+
return method_name_;
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
protected:
|
| 30 |
+
void setArgumentNames(
|
| 31 |
+
std::vector<std::string>& argument_names_out) const override {
|
| 32 |
+
const auto& schema = static_module_->schema();
|
| 33 |
+
CAFFE_ENFORCE(schema.has_value());
|
| 34 |
+
const auto& arguments = schema->arguments();
|
| 35 |
+
argument_names_out.clear();
|
| 36 |
+
argument_names_out.reserve(arguments.size());
|
| 37 |
+
std::transform(
|
| 38 |
+
arguments.begin(),
|
| 39 |
+
arguments.end(),
|
| 40 |
+
std::back_inserter(argument_names_out),
|
| 41 |
+
[](const c10::Argument& arg) -> std::string { return arg.name(); });
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
private:
|
| 45 |
+
std::shared_ptr<StaticModule> static_module_;
|
| 46 |
+
std::string method_name_;
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
} // namespace torch::jit
|
| 50 |
+
|
| 51 |
+
#else
|
| 52 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 53 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/static/te_wrapper.h
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <torch/csrc/jit/tensorexpr/codegen.h>
|
| 5 |
+
#include <torch/csrc/jit/tensorexpr/ir.h>
|
| 6 |
+
#include <torch/csrc/jit/tensorexpr/ir_simplifier.h>
|
| 7 |
+
#include <torch/csrc/jit/tensorexpr/llvm_codegen.h>
|
| 8 |
+
#include <torch/csrc/jit/tensorexpr/loopnest.h>
|
| 9 |
+
|
| 10 |
+
namespace torch::jit {
|
| 11 |
+
|
| 12 |
+
class TEWrapper {
|
| 13 |
+
public:
|
| 14 |
+
TEWrapper() = default;
|
| 15 |
+
void call(const std::vector<void*>& args);
|
| 16 |
+
|
| 17 |
+
template <typename ExpectedType>
|
| 18 |
+
bool checkInput(const at::Tensor& t) {
|
| 19 |
+
#ifdef TORCH_ENABLE_LLVM
|
| 20 |
+
return t.is_contiguous() && t.dtype().Match<ExpectedType>();
|
| 21 |
+
#else
|
| 22 |
+
return false;
|
| 23 |
+
#endif
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
#ifdef TORCH_ENABLE_LLVM
|
| 27 |
+
void update(std::unique_ptr<tensorexpr::LLVMCodeGen>&& cg_);
|
| 28 |
+
#endif
|
| 29 |
+
|
| 30 |
+
private:
|
| 31 |
+
#ifdef TORCH_ENABLE_LLVM
|
| 32 |
+
std::unique_ptr<tensorexpr::LLVMCodeGen> cg;
|
| 33 |
+
#endif
|
| 34 |
+
};
|
| 35 |
+
|
| 36 |
+
std::shared_ptr<TEWrapper> createDiv();
|
| 37 |
+
std::shared_ptr<TEWrapper> createLogit();
|
| 38 |
+
std::shared_ptr<TEWrapper> createRelu();
|
| 39 |
+
std::shared_ptr<TEWrapper> createTanh();
|
| 40 |
+
std::shared_ptr<TEWrapper> createSigmoid();
|
| 41 |
+
std::shared_ptr<TEWrapper> createSignedLog1p();
|
| 42 |
+
std::shared_ptr<TEWrapper> createClamp();
|
| 43 |
+
std::shared_ptr<TEWrapper> createClampNanToNum();
|
| 44 |
+
|
| 45 |
+
} // namespace torch::jit
|
| 46 |
+
|
| 47 |
+
#else
|
| 48 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 49 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_script.h
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
// This file is temporary until native_functions.yaml and derivatives.yaml are
|
| 4 |
+
// merged. Ideally this should all go into native_functions.yaml
|
| 5 |
+
|
| 6 |
+
#include <c10/util/StringUtil.h>
|
| 7 |
+
#include <torch/csrc/jit/api/module.h>
|
| 8 |
+
#include <optional>
|
| 9 |
+
|
| 10 |
+
namespace torch::jit {
|
| 11 |
+
struct GradientPair {
|
| 12 |
+
std::shared_ptr<Graph> forward;
|
| 13 |
+
std::shared_ptr<Graph> backward;
|
| 14 |
+
};
|
| 15 |
+
|
| 16 |
+
TORCH_API std::optional<GradientPair> gradientInfoForSchema(
|
| 17 |
+
const FunctionSchema& schema);
|
| 18 |
+
TORCH_API bool hasGradientInfoForSchema(const FunctionSchema& schema);
|
| 19 |
+
} // namespace torch::jit
|
| 20 |
+
|
| 21 |
+
#else
|
| 22 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 23 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_shape_registry.h
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
// This file is temporary until native_functions.yaml and derivatives.yaml are
|
| 4 |
+
// merged. Ideally this should all go into native_functions.yaml
|
| 5 |
+
|
| 6 |
+
#include <torch/csrc/Export.h>
|
| 7 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 8 |
+
|
| 9 |
+
namespace torch::jit {
|
| 10 |
+
|
| 11 |
+
/*
|
| 12 |
+
ADDING A NEW SHAPE GRAPH:
|
| 13 |
+
- For one node schema, there is one corresponding registered shape compute
|
| 14 |
+
graph. The schema of the graph should be the same except for Tensor arguments.
|
| 15 |
+
For every Tensor input in operator schema, there should be a List[int]
|
| 16 |
+
corresponding to that Tensor's shape. For example: "aten::linear(Tensor input,
|
| 17 |
+
Tensor weight, Tensor? bias=None) -> Tensor" ==> def linear(input: List[int],
|
| 18 |
+
weight: List[int], bias: Optional[List[int]])
|
| 19 |
+
|
| 20 |
+
Additionally, arguments which are unused at the end of the schema may be left
|
| 21 |
+
off. This allows sharing a single graph for multiple function schemas, such as
|
| 22 |
+
unary operators with different trailing arguments that do not affect the output
|
| 23 |
+
shape.
|
| 24 |
+
|
| 25 |
+
The shape graph should return a new, unaliased List[int] (or tuple of lists for
|
| 26 |
+
multiple returns) and should not modify any input lists. This allows the shape
|
| 27 |
+
graphs to be composed and executed.
|
| 28 |
+
|
| 29 |
+
The shape analysis (particularly for non-complete, or symbolic shapes) works by
|
| 30 |
+
partially evaluating the JIT IR. It may be possible for a Graph to be registered
|
| 31 |
+
that we cannot currently partially evaluate. If this happens, please file an
|
| 32 |
+
issue. There are lints registered to avoid particular known patterns (continue
|
| 33 |
+
or break or early return in a loop). Those may be improved in the future, please
|
| 34 |
+
file an issue if necessary.
|
| 35 |
+
|
| 36 |
+
To debug (and write initially) the recommended flow is to define these functions
|
| 37 |
+
in python and iterate there. Functions should be added to
|
| 38 |
+
torch/jit/_shape_functions.
|
| 39 |
+
|
| 40 |
+
To test operators, the preferred flow is through OpInfos, with
|
| 41 |
+
`assert_jit_shape_analysis=True`. If this is not feasible, you can look at tests
|
| 42 |
+
in `test_symbolic_shape_analysis.py` such as `test_adaptive_avg_pool2d`.
|
| 43 |
+
|
| 44 |
+
Operators which take in a list of tensors, such as concat, are not yet
|
| 45 |
+
supported. Concat has been special cased and could be generalized as needed.
|
| 46 |
+
Please file an issue.
|
| 47 |
+
*/
|
| 48 |
+
|
| 49 |
+
struct BoundedShapeGraphs {
|
| 50 |
+
std::shared_ptr<Graph> lower_bound;
|
| 51 |
+
std::shared_ptr<Graph> upper_bound;
|
| 52 |
+
};
|
| 53 |
+
|
| 54 |
+
TORCH_API void RegisterShapeComputeGraphForSchema(
|
| 55 |
+
const FunctionSchema& schema,
|
| 56 |
+
const std::shared_ptr<Graph>& g);
|
| 57 |
+
|
| 58 |
+
TORCH_API std::optional<std::shared_ptr<Graph>> shapeComputeGraphForSchema(
|
| 59 |
+
const FunctionSchema& schema);
|
| 60 |
+
|
| 61 |
+
TORCH_API std::optional<BoundedShapeGraphs> boundedGraphsForSchema(
|
| 62 |
+
const FunctionSchema& schema);
|
| 63 |
+
|
| 64 |
+
TORCH_API std::vector<const FunctionSchema*> RegisteredShapeComputeSchemas();
|
| 65 |
+
|
| 66 |
+
TORCH_API void LintShapeComputeGraph(
|
| 67 |
+
const FunctionSchema* schema,
|
| 68 |
+
const std::shared_ptr<Graph>& graph);
|
| 69 |
+
|
| 70 |
+
} // namespace torch::jit
|
| 71 |
+
|
| 72 |
+
#else
|
| 73 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 74 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/symbolic_shape_registry_util.h
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
// This file is temporary until native_functions.yaml and derivatives.yaml are
|
| 4 |
+
// merged. Ideally this should all go into native_functions.yaml
|
| 5 |
+
|
| 6 |
+
#include <torch/csrc/Export.h>
|
| 7 |
+
#include <torch/csrc/jit/ir/ir.h>
|
| 8 |
+
|
| 9 |
+
namespace torch::jit {
|
| 10 |
+
|
| 11 |
+
TORCH_API const OperatorMap<std::string>& get_tensorexpr_elementwise_set();
|
| 12 |
+
|
| 13 |
+
} // namespace torch::jit
|
| 14 |
+
|
| 15 |
+
#else
|
| 16 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 17 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/vararg_functions.h
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <ATen/core/List.h>
|
| 4 |
+
#include <ATen/core/functional.h>
|
| 5 |
+
#include <ATen/core/ivalue.h>
|
| 6 |
+
#include <ATen/core/jit_type.h>
|
| 7 |
+
#include <ATen/core/stack.h>
|
| 8 |
+
|
| 9 |
+
namespace torch::jit {
|
| 10 |
+
|
| 11 |
+
void tupleUnpack(Stack& stack);
|
| 12 |
+
|
| 13 |
+
void format(Stack& stack, size_t num_inputs);
|
| 14 |
+
|
| 15 |
+
void einsum(Stack& stack, size_t num_inputs);
|
| 16 |
+
|
| 17 |
+
void percentFormat(Stack& stack, size_t num_inputs);
|
| 18 |
+
|
| 19 |
+
void listUnpack(Stack& stack, size_t num_outputs);
|
| 20 |
+
|
| 21 |
+
void tupleConstruct(Stack& stack, size_t num_inputs);
|
| 22 |
+
|
| 23 |
+
void namedTupleConstruct(Stack& stack, c10::TypePtr type, size_t num_inputs);
|
| 24 |
+
|
| 25 |
+
void listConstruct(Stack& stack, const c10::Type& list_type, size_t num_inputs);
|
| 26 |
+
|
| 27 |
+
void dictConstruct(Stack& stack, const c10::Type& type, size_t num_inputs);
|
| 28 |
+
|
| 29 |
+
// as weak_ref will create a Object with a non-owning CompilationUnit reference,
|
| 30 |
+
// for use as a constant in the Graph to avoid a reference cycle
|
| 31 |
+
void createObject(
|
| 32 |
+
Stack& stack,
|
| 33 |
+
const at::ClassTypePtr& type,
|
| 34 |
+
bool as_weak_ref = false);
|
| 35 |
+
|
| 36 |
+
void isinstance(Stack& stack, at::ArrayRef<at::TypePtr> types);
|
| 37 |
+
|
| 38 |
+
void tupleSlice(Stack& stack, size_t begin, size_t end);
|
| 39 |
+
|
| 40 |
+
void dequantize(Stack& stack);
|
| 41 |
+
|
| 42 |
+
} // namespace torch::jit
|
| 43 |
+
|
| 44 |
+
#else
|
| 45 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 46 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/runtime/variable_tensor_list.h
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
#include <ATen/core/Tensor.h>
|
| 4 |
+
|
| 5 |
+
namespace torch::jit {
|
| 6 |
+
|
| 7 |
+
// a wrapper to mark places where we expect all the at::Tensors to be
|
| 8 |
+
// variables
|
| 9 |
+
struct variable_tensor_list : public std::vector<at::Tensor> {
|
| 10 |
+
variable_tensor_list() = default;
|
| 11 |
+
template <class InputIt>
|
| 12 |
+
variable_tensor_list(InputIt first, InputIt last)
|
| 13 |
+
: std::vector<at::Tensor>(first, last) {}
|
| 14 |
+
explicit variable_tensor_list(std::vector<at::Tensor>&& tensor)
|
| 15 |
+
: std::vector<at::Tensor>(std::move(tensor)) {}
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
} // namespace torch::jit
|
| 19 |
+
|
| 20 |
+
#else
|
| 21 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 22 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
outputs/audit_venv/lib/python3.11/site-packages/torch/include/torch/csrc/jit/serialization/callstack_debug_info_serialization.h
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|
| 2 |
+
#pragma once
|
| 3 |
+
|
| 4 |
+
#include <c10/core/Allocator.h>
|
| 5 |
+
#include <torch/csrc/jit/frontend/source_range.h>
|
| 6 |
+
#include <torch/csrc/jit/ir/scope.h>
|
| 7 |
+
|
| 8 |
+
#include <ATen/core/ivalue.h>
|
| 9 |
+
|
| 10 |
+
#include <vector>
|
| 11 |
+
|
| 12 |
+
#include <c10/util/flat_hash_map.h>
|
| 13 |
+
|
| 14 |
+
namespace c10 {
|
| 15 |
+
struct IValue;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
namespace torch::jit {
|
| 19 |
+
|
| 20 |
+
class Pickler;
|
| 21 |
+
class InlinedCallStackSerializer {
|
| 22 |
+
public:
|
| 23 |
+
// Serialize InlinedCallStack as
|
| 24 |
+
// SerializedInlinedCallStack =
|
| 25 |
+
// [module_info, source range tag, SerializedInlinedCallStack]
|
| 26 |
+
// module_info = [ClassType.qualifiedName, instance_name]
|
| 27 |
+
// source_range_tag = unique source range id
|
| 28 |
+
c10::IValue serialize(
|
| 29 |
+
const InlinedCallStackPtr& cs_ptr,
|
| 30 |
+
const SourceRangeTagMap& source_range_tags);
|
| 31 |
+
|
| 32 |
+
private:
|
| 33 |
+
// module_info = [ClassType.qualifiedName, instance_name]
|
| 34 |
+
c10::IValue serialize_module_instance_info(
|
| 35 |
+
const std::optional<ModuleInstanceInfo>& m);
|
| 36 |
+
|
| 37 |
+
// This caches serialized inlined callstack ptr, since many
|
| 38 |
+
// InlinedCallStackPtr can refer to the same one.
|
| 39 |
+
ska::flat_hash_map<InlinedCallStackPtr, c10::IValue>
|
| 40 |
+
serialized_inlined_callstack_;
|
| 41 |
+
// This caches serialized module instance info.
|
| 42 |
+
// There might be many nodes that are part of the same
|
| 43 |
+
// parent, grandparent etc. module.
|
| 44 |
+
ska::flat_hash_map<std::string, c10::IValue> serialized_module_instance_info_;
|
| 45 |
+
};
|
| 46 |
+
|
| 47 |
+
class TORCH_API CallStackDebugInfoPickler {
|
| 48 |
+
public:
|
| 49 |
+
CallStackDebugInfoPickler() = default;
|
| 50 |
+
|
| 51 |
+
std::vector<char> pickle(
|
| 52 |
+
const std::unordered_map<int64_t, DebugInfoTuple>& callstack_ptrs,
|
| 53 |
+
const SourceRangeTagMap& source_range_tags);
|
| 54 |
+
|
| 55 |
+
private:
|
| 56 |
+
InlinedCallStackSerializer css_;
|
| 57 |
+
};
|
| 58 |
+
|
| 59 |
+
class InlinedCallStackDeserializer {
|
| 60 |
+
public:
|
| 61 |
+
InlinedCallStackPtr deserialize(
|
| 62 |
+
const c10::IValue& iv,
|
| 63 |
+
const ska::flat_hash_map<int64_t, SourceRange>& source_range_map,
|
| 64 |
+
const std::shared_ptr<CompilationUnit>& cu);
|
| 65 |
+
|
| 66 |
+
private:
|
| 67 |
+
std::optional<ModuleInstanceInfo> deserialize_module_instance_info(
|
| 68 |
+
const c10::IValue& iv,
|
| 69 |
+
const std::shared_ptr<CompilationUnit>& cu);
|
| 70 |
+
|
| 71 |
+
ska::
|
| 72 |
+
flat_hash_map<c10::intrusive_ptr<c10::ivalue::Tuple>, InlinedCallStackPtr>
|
| 73 |
+
cached_inlined_callstacks_;
|
| 74 |
+
ska::flat_hash_map<c10::intrusive_ptr<c10::ivalue::Tuple>, ModuleInstanceInfo>
|
| 75 |
+
cached_module_instance_info_;
|
| 76 |
+
};
|
| 77 |
+
|
| 78 |
+
class TORCH_API CallStackDebugInfoUnpickler {
|
| 79 |
+
public:
|
| 80 |
+
ska::flat_hash_map<int64_t, DebugInfoTuple> unpickle(
|
| 81 |
+
const at::DataPtr& data,
|
| 82 |
+
size_t size,
|
| 83 |
+
const ska::flat_hash_map<int64_t, SourceRange>& source_range_map,
|
| 84 |
+
const std::shared_ptr<CompilationUnit>& cu);
|
| 85 |
+
|
| 86 |
+
private:
|
| 87 |
+
InlinedCallStackDeserializer csds_;
|
| 88 |
+
};
|
| 89 |
+
|
| 90 |
+
} // namespace torch::jit
|
| 91 |
+
|
| 92 |
+
#else
|
| 93 |
+
#error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
|
| 94 |
+
#endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|