mirror of
https://github.com/zebrajr/pytorch.git
synced 2025-12-07 12:21:27 +01:00
Summary: Adding back D46578700 / PR https://github.com/pytorch/pytorch/pull/108426 Note: The changes were originally reverted due to memory regression, these changes are putting the code behind a gflag so it is only used by binaries that require expanded stack for BPF Profiling. Original Diff comment: To get a Node's call stack we currently loop on the InlinedCallStack graph and follow the "callee" chain. Since the node's inlined stack does not change we can optimize this but expanding the node's inlined stack once and reusing it. This is particularly useful when reading the node's stack from another process (e.g. BPF) as it simplified the memory traversal process. The new data structure (NodeSourceInfo) only holds pointers to the function name and file name variables, and assumes these objects will be alive throughout the lifetime of the process. Each Node has an extended attribute that has an index to a vector of stack frames expanded_node_stacks_ node_stack_attr_symbol_ is only needed to make accessing the stack vector index attribute easier from BPF. Test Plan: - Verified using BPF Program in subsequent diffs - Perf testing for loading large model: P822455246 Differential Revision: D49565461 Pull Request resolved: https://github.com/pytorch/pytorch/pull/110229 Approved by: https://github.com/zdevito
207 lines
5.9 KiB
C++
207 lines
5.9 KiB
C++
#include <torch/csrc/jit/ir/scope.h>
|
|
|
|
#include <ATen/core/class_type.h>
|
|
#include <ATen/core/function.h>
|
|
|
|
namespace torch::jit {
|
|
// util functions
|
|
namespace utils {
|
|
|
|
std::string get_module_info(const ModuleInstanceInfo& module_instance_info) {
|
|
std::string module_info;
|
|
const auto& class_type = module_instance_info.class_type();
|
|
std::string instance_name = module_instance_info.instance_name();
|
|
std::string type_name;
|
|
if (class_type) {
|
|
type_name += class_type->name()->qualifiedName();
|
|
type_name = type_name.substr(type_name.find_last_of('.') + 1);
|
|
}
|
|
if (type_name.empty()) {
|
|
type_name = "UNKNOWN_TYPE";
|
|
}
|
|
if (instance_name.empty()) {
|
|
instance_name = "UNKNOWN_INSTANCE";
|
|
}
|
|
module_info.append(instance_name).append("(").append(type_name).append(")");
|
|
return module_info;
|
|
}
|
|
|
|
} // namespace utils
|
|
ScopePtr Scope::intrusive_from_this() {
|
|
c10::raw::intrusive_ptr::incref(this); // we are creating a new pointer
|
|
// from a raw `this` pointer
|
|
// so we need to bump the refcount
|
|
// to account for this ownership
|
|
return c10::intrusive_ptr<Scope>::reclaim(this);
|
|
}
|
|
|
|
Scope::Scope() : name_(Symbol::scope("")) {}
|
|
|
|
Scope::Scope(ScopePtr parent, Symbol name)
|
|
: parent_(std::move(parent)), name_(name) {}
|
|
|
|
ScopePtr Scope::push(Symbol name) {
|
|
return c10::make_intrusive<Scope>(intrusive_from_this(), name);
|
|
}
|
|
|
|
ScopePtr Scope::parent() {
|
|
if (!parent_) {
|
|
throw std::runtime_error("Cannot get parent from Scope with no parent");
|
|
}
|
|
return parent_;
|
|
}
|
|
|
|
bool Scope::isRoot() const {
|
|
return !parent_;
|
|
}
|
|
|
|
bool Scope::isBlank() const {
|
|
static const Symbol blank = Symbol::scope("");
|
|
return isRoot() && name() == blank;
|
|
}
|
|
|
|
ScopePtr Scope::getRoot() {
|
|
ScopePtr current = intrusive_from_this();
|
|
while (current->parent_) {
|
|
current = current->parent_;
|
|
}
|
|
return current;
|
|
}
|
|
|
|
size_t Scope::getDepth() {
|
|
size_t d = 1;
|
|
ScopePtr current = intrusive_from_this();
|
|
while (current->parent_) {
|
|
current = current->parent_;
|
|
d += 1;
|
|
}
|
|
return d;
|
|
}
|
|
|
|
Symbol Scope::name() const {
|
|
return name_;
|
|
}
|
|
|
|
std::string Scope::namesFromRoot(const std::string& separator) const {
|
|
// TODO: I think the answer is we shouldn't have used Symbol here
|
|
std::string out = this->name_.toUnqualString();
|
|
if (this->isRoot()) {
|
|
return out;
|
|
}
|
|
ScopePtr parent = this->parent_;
|
|
while (!parent->isRoot()) {
|
|
// NOLINTNEXTLINE(performance-inefficient-string-concatenation)
|
|
out = std::string(parent->name_.toUnqualString()) + separator + out;
|
|
parent = parent->parent_;
|
|
}
|
|
return out;
|
|
}
|
|
|
|
InlinedCallStackPtr InlinedCallStack::intrusive_from_this() {
|
|
c10::raw::intrusive_ptr::incref(this); // we are creating a new pointer
|
|
// from a raw `this` pointer
|
|
// so we need to bump the refcount
|
|
// to account for this ownership
|
|
return c10::intrusive_ptr<InlinedCallStack>::reclaim(this);
|
|
}
|
|
|
|
InlinedCallStack::InlinedCallStack(Function* fn, SourceRange source_range)
|
|
: fn_(fn),
|
|
fn_name_(fn_ ? fn_->name() : ""),
|
|
source_range_(std::move(source_range)) {}
|
|
|
|
InlinedCallStack::InlinedCallStack(
|
|
Function* fn,
|
|
SourceRange source_range,
|
|
c10::optional<ModuleInstanceInfo> module_instance_info)
|
|
: fn_(fn),
|
|
fn_name_(fn_ ? fn_->name() : ""),
|
|
source_range_(std::move(source_range)),
|
|
module_instance_info_(std::move(module_instance_info)) {}
|
|
|
|
InlinedCallStack::InlinedCallStack(
|
|
Function* fn,
|
|
SourceRange source_range,
|
|
c10::optional<ModuleInstanceInfo> module_instance_info,
|
|
std::string& function_name)
|
|
: fn_(fn),
|
|
fn_name_(std::move(function_name)),
|
|
source_range_(std::move(source_range)),
|
|
module_instance_info_(std::move(module_instance_info)) {}
|
|
|
|
InlinedCallStack::InlinedCallStack(
|
|
InlinedCallStackPtr callee,
|
|
Function* fn,
|
|
SourceRange source_range)
|
|
: callee_(std::move(callee)),
|
|
fn_(fn),
|
|
fn_name_(fn_ ? fn_->name() : ""),
|
|
source_range_(std::move(source_range)) {}
|
|
|
|
InlinedCallStack::InlinedCallStack(
|
|
InlinedCallStackPtr callee,
|
|
Function* fn,
|
|
SourceRange source_range,
|
|
c10::optional<ModuleInstanceInfo> module_instance_info,
|
|
std::string& function_name)
|
|
: callee_(std::move(callee)),
|
|
fn_(fn),
|
|
fn_name_(std::move(function_name)),
|
|
source_range_(std::move(source_range)),
|
|
module_instance_info_(std::move(module_instance_info)) {}
|
|
|
|
InlinedCallStack::InlinedCallStack(
|
|
InlinedCallStackPtr callee,
|
|
Function* fn,
|
|
SourceRange source_range,
|
|
c10::optional<ModuleInstanceInfo> module_instance_info)
|
|
: callee_(std::move(callee)),
|
|
fn_(fn),
|
|
fn_name_(fn_ ? fn_->name() : ""),
|
|
source_range_(std::move(source_range)),
|
|
module_instance_info_(std::move(module_instance_info)) {}
|
|
|
|
c10::optional<InlinedCallStackPtr> InlinedCallStack::callee() const {
|
|
return callee_;
|
|
}
|
|
|
|
void InlinedCallStack::setCallee(c10::optional<InlinedCallStackPtr> callee) {
|
|
callee_ = std::move(callee);
|
|
}
|
|
|
|
c10::optional<ModuleInstanceInfo> InlinedCallStack::module_instance() const {
|
|
return module_instance_info_;
|
|
}
|
|
|
|
SourceRange InlinedCallStack::source_range() const {
|
|
return source_range_;
|
|
}
|
|
|
|
Function* InlinedCallStack::function() const {
|
|
return fn_;
|
|
}
|
|
|
|
const std::string& InlinedCallStack::function_name() const {
|
|
return fn_name_;
|
|
}
|
|
|
|
std::vector<InlinedCallStackEntry> InlinedCallStack::vec() {
|
|
std::vector<InlinedCallStackEntry> r;
|
|
c10::optional<InlinedCallStackPtr> current = intrusive_from_this();
|
|
while (current) {
|
|
r.emplace_back(
|
|
(*current)->fn_,
|
|
(*current)->source_range_,
|
|
(*current)->module_instance_info_);
|
|
current = (*current)->callee_;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
ModuleInstanceInfo::ModuleInstanceInfo(
|
|
c10::ClassTypePtr module_type,
|
|
std::string instance_name)
|
|
: module_type_(std::move(module_type)),
|
|
instance_name_(std::move(instance_name)) {}
|
|
} // namespace torch::jit
|