Add helpful pretty pretting summaries to torch for lldb debugging (#97101)

# Summary
Add support for pretty printing of tensors when using lldb similiar to what is currently available for gdb

<img width="772" alt="Screenshot 2023-03-18 at 6 20 34 PM" src="https://user-images.githubusercontent.com/32754868/226148687-b4e6cfe1-8be1-4657-9ebc-d134f697dd37.png">

<img width="254" alt="Screenshot 2023-03-18 at 6 20 43 PM" src="https://user-images.githubusercontent.com/32754868/226148690-caca6f76-d873-419e-b5e4-6bb403b3d179.png">

I changed it so to override the variable formatting instead of having to call a seperate command you can just do `print <tensor>`

I also add one for sizes
<img width="309" alt="Screenshot 2023-03-19 at 1 05 49 PM" src="https://user-images.githubusercontent.com/32754868/226206458-e3f0111b-6a97-4d75-8125-48455aa2cf43.png">

Last one:
<img width="815" alt="Screenshot 2023-03-19 at 1 39 23 PM" src="https://user-images.githubusercontent.com/32754868/226207687-20bd014f-9e0e-4c01-b2c8-190b7365aa70.png">

If you use the codelldb extension be sure to add:
    `"lldb.launch.initCommands": ["command source ${env:HOME}/.lldbinit"]`
    To your setttings .json

Pull Request resolved: https://github.com/pytorch/pytorch/pull/97101
Approved by: https://github.com/ngimel
This commit is contained in:
drisspg
2023-03-20 01:27:44 +00:00
committed by PyTorch MergeBot
parent 5471621497
commit dba9487324
3 changed files with 126 additions and 0 deletions

17
.lldbinit Normal file
View File

@ -0,0 +1,17 @@
# automatically load the pytorch_lldb extension.
#
# lldb automatically tries to load this file whenever it is executed from the
# root of the pytorch repo, but by default it is not allowed to do so due to
# security reasons. If you want to use pytorch_lldb, please add the following
# line to your ~/.lldbinit (i.e., the .lldbinit file which is in your home
# directory, NOT this file):
# settings set target.load-cwd-lldbinit true
# setting set escape-non-printables false
#
# Alternatively, you can manually load the pytorch_lldb commands into your
# existing lldb session by doing the following:
# (lldb) command script import tools/lldb/pytorch_lldb.py
command script import tools/lldb/pytorch_lldb.py
setting set escape-non-printables false
type category enable torch

View File

@ -0,0 +1,97 @@
from typing import Any
import lldb # type: ignore[import]
def get_target() -> Any:
target = lldb.debugger.GetSelectedTarget()
if not target:
print("[-] error: no target available. please add a target to lldb.")
return None
return target
class DisableBreakpoints:
"""
Context-manager to temporarily disable all lldb breakpoints, useful if
there is a risk to hit one during the evaluation of one of our custom
commands
"""
def __enter__(self) -> None:
target = get_target()
if target.DisableAllBreakpoints() is False:
print("[-] error: failed to disable all breakpoints.")
def __exit__(self, etype: Any, evalue: Any, tb: Any) -> None:
target = get_target()
if target.EnableAllBreakpoints() is False:
print("[-] error: failed to enable all breakpoints.")
def IntArrayRef_summary(valobj: Any, internal_dict: Any, options: Any) -> str:
"""Print human readable representation of c10::IntArrayRef"""
with DisableBreakpoints():
target = get_target()
tensor = valobj.GetName()
result = target.EvaluateExpression(
f"torch::gdb::int_array_ref_string({tensor})"
)
str_result = str(result)
str_result = str_result[str_result.find('"') + 1 : -1]
return str_result
def DispatchKeyset_summary(valobj: Any, internal_dict: Any, options: Any) -> str:
"""Print human readable representation of c10::DispatchKeyset"""
with DisableBreakpoints():
target = get_target()
keyset = valobj.GetName()
result = target.EvaluateExpression(
f"torch::gdb::dispatch_keyset_string({keyset})"
)
str_result = str(result)
str_result = str_result[str_result.find('"') + 1 : -1]
return str_result
def Tensor_summary(valobj: Any, internal_dict: Any, options: Any) -> str:
"""Print a human readable representation of the given at::Tensor.
at::Tensor instances do not have a C++ implementation of a repr method: in
pytorch, this is done by pure-Python code. As such, print <tensor>
internally creates a Python wrapper for the given tensor and call repr()
on it.
Usage:
print self
"""
with DisableBreakpoints():
target = get_target()
tensor = valobj.GetName()
result = target.EvaluateExpression(f"torch::gdb::tensor_repr({tensor})")
str_result = str(result)
target.EvaluateExpression(f"(void)free({result.GetValue()})")
str_result = "\n" + str_result[str_result.find("tensor") : -1]
return str_result
# And the initialization code to add your commands
def __lldb_init_module(debugger: Any, internal_dict: Any) -> Any:
debugger.HandleCommand(
"type summary add c10::IntArrayRef -F pytorch_lldb.IntArrayRef_summary -w torch"
)
debugger.HandleCommand(
"type summary add c10::DispatchKeySet -F pytorch_lldb.DispatchKeyset_summary -w torch"
)
debugger.HandleCommand(
"type summary add at::Tensor -F pytorch_lldb.Tensor_summary -w torch"
)
print(
"Pretty Printing lldb summary for PyTorch AT types has been installed and is ready for use. "
"This category is enabled by default. To disable run: `type category disable torch`"
)
print(
"Usage:\n\tprint <at::tensor>\n\tprint <c10::IntArrayRef>\n\tprint <c10::DispatchKeySet>"
)

View File

@ -305,6 +305,18 @@ error:
return nullptr; return nullptr;
} }
std::string int_array_ref_string(at::IntArrayRef sizes) {
std::stringstream ss;
ss << sizes;
return ss.str();
}
std::string dispatch_keyset_string(c10::DispatchKeySet keyset) {
std::stringstream ss;
ss << keyset;
return ss.str();
}
} // namespace gdb } // namespace gdb
} // namespace torch } // namespace torch