Skip to content

Commit dba9487

Browse files
drisspgpytorchmergebot
authored andcommitted
Add helpful pretty pretting summaries to torch for lldb debugging (pytorch#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: pytorch#97101 Approved by: https://github.com/ngimel
1 parent 5471621 commit dba9487

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

.lldbinit

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

tools/lldb/pytorch_lldb.py

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
from typing import Any
2+
3+
import lldb # type: ignore[import]
4+
5+
6+
def get_target() -> Any:
7+
target = lldb.debugger.GetSelectedTarget()
8+
if not target:
9+
print("[-] error: no target available. please add a target to lldb.")
10+
return None
11+
return target
12+
13+
14+
class DisableBreakpoints:
15+
"""
16+
Context-manager to temporarily disable all lldb breakpoints, useful if
17+
there is a risk to hit one during the evaluation of one of our custom
18+
commands
19+
"""
20+
21+
def __enter__(self) -> None:
22+
target = get_target()
23+
24+
if target.DisableAllBreakpoints() is False:
25+
print("[-] error: failed to disable all breakpoints.")
26+
27+
def __exit__(self, etype: Any, evalue: Any, tb: Any) -> None:
28+
target = get_target()
29+
30+
if target.EnableAllBreakpoints() is False:
31+
print("[-] error: failed to enable all breakpoints.")
32+
33+
34+
def IntArrayRef_summary(valobj: Any, internal_dict: Any, options: Any) -> str:
35+
"""Print human readable representation of c10::IntArrayRef"""
36+
with DisableBreakpoints():
37+
target = get_target()
38+
tensor = valobj.GetName()
39+
result = target.EvaluateExpression(
40+
f"torch::gdb::int_array_ref_string({tensor})"
41+
)
42+
str_result = str(result)
43+
str_result = str_result[str_result.find('"') + 1 : -1]
44+
return str_result
45+
46+
47+
def DispatchKeyset_summary(valobj: Any, internal_dict: Any, options: Any) -> str:
48+
"""Print human readable representation of c10::DispatchKeyset"""
49+
with DisableBreakpoints():
50+
target = get_target()
51+
keyset = valobj.GetName()
52+
result = target.EvaluateExpression(
53+
f"torch::gdb::dispatch_keyset_string({keyset})"
54+
)
55+
str_result = str(result)
56+
str_result = str_result[str_result.find('"') + 1 : -1]
57+
return str_result
58+
59+
60+
def Tensor_summary(valobj: Any, internal_dict: Any, options: Any) -> str:
61+
"""Print a human readable representation of the given at::Tensor.
62+
63+
at::Tensor instances do not have a C++ implementation of a repr method: in
64+
pytorch, this is done by pure-Python code. As such, print <tensor>
65+
internally creates a Python wrapper for the given tensor and call repr()
66+
on it.
67+
Usage:
68+
print self
69+
"""
70+
with DisableBreakpoints():
71+
target = get_target()
72+
tensor = valobj.GetName()
73+
result = target.EvaluateExpression(f"torch::gdb::tensor_repr({tensor})")
74+
str_result = str(result)
75+
target.EvaluateExpression(f"(void)free({result.GetValue()})")
76+
str_result = "\n" + str_result[str_result.find("tensor") : -1]
77+
return str_result
78+
79+
80+
# And the initialization code to add your commands
81+
def __lldb_init_module(debugger: Any, internal_dict: Any) -> Any:
82+
debugger.HandleCommand(
83+
"type summary add c10::IntArrayRef -F pytorch_lldb.IntArrayRef_summary -w torch"
84+
)
85+
debugger.HandleCommand(
86+
"type summary add c10::DispatchKeySet -F pytorch_lldb.DispatchKeyset_summary -w torch"
87+
)
88+
debugger.HandleCommand(
89+
"type summary add at::Tensor -F pytorch_lldb.Tensor_summary -w torch"
90+
)
91+
print(
92+
"Pretty Printing lldb summary for PyTorch AT types has been installed and is ready for use. "
93+
"This category is enabled by default. To disable run: `type category disable torch`"
94+
)
95+
print(
96+
"Usage:\n\tprint <at::tensor>\n\tprint <c10::IntArrayRef>\n\tprint <c10::DispatchKeySet>"
97+
)

torch/csrc/utils.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,18 @@ char* tensor_repr(at::Tensor tensor) {
305305
return nullptr;
306306
}
307307

308+
std::string int_array_ref_string(at::IntArrayRef sizes) {
309+
std::stringstream ss;
310+
ss << sizes;
311+
return ss.str();
312+
}
313+
314+
std::string dispatch_keyset_string(c10::DispatchKeySet keyset) {
315+
std::stringstream ss;
316+
ss << keyset;
317+
return ss.str();
318+
}
319+
308320
} // namespace gdb
309321
} // namespace torch
310322

0 commit comments

Comments
 (0)