|
| 1 | +# C++ Debugging |
| 2 | + |
| 3 | +PyTorch has good support for C++ debugging. This guide shows you how build with |
| 4 | +debugging symbols, and how to debug PyTorch using GDB or LLDB with VSCode. |
| 5 | + |
| 6 | +## Why would you need this? |
| 7 | + |
| 8 | +This guide is for contributors to PyTorch or PyTorch/XLA who use C++ to build features like [custom C++ operations](https://pytorch.org/tutorials/advanced/cpp_custom_ops.html). |
| 9 | + |
| 10 | +## Install GDB: The GNU Project Debugger |
| 11 | + |
| 12 | +The official instructions are [here](https://www.sourceware.org/gdb/) but if you are in a conda environment, you can |
| 13 | +install it with the following command: |
| 14 | + |
| 15 | +``` sh |
| 16 | +conda install -c conda-forge gdb |
| 17 | +``` |
| 18 | + |
| 19 | +## Building PyTorch with Debugging Symbols |
| 20 | + |
| 21 | +Looking into [`setup.py`]((https://github.com/pytorch/pytorch/blob/300e0ee13c08ef77e88f32204a2e0925c17ce216/setup.py#L2C1-L11C53)), we see |
| 22 | + |
| 23 | +``` python |
| 24 | +# Environment variables you are probably interested in: |
| 25 | +# |
| 26 | +# DEBUG |
| 27 | +# build with -O0 and -g (debug symbols) |
| 28 | +# |
| 29 | +# REL_WITH_DEB_INFO |
| 30 | +# build with optimizations and -g (debug symbols) |
| 31 | +# |
| 32 | +# USE_CUSTOM_DEBINFO="path/to/file1.cpp;path/to/file2.cpp" |
| 33 | +# build with debug info only for specified files |
| 34 | +``` |
| 35 | + |
| 36 | +Setting `DEBUG` will result in a slow binary, since every single file will |
| 37 | +be unoptimized (`-O0`) and built with debugging symbols. |
| 38 | + |
| 39 | +In practice, you'll want to set the `USE_CUSTOM_DEBINFO` instead. |
| 40 | + |
| 41 | +The challenge becomes knowing which files to build with debugging symbols. A common issue will be debugging a file, then realizing you want to look at data structures or another |
| 42 | +function call in a file that's not built with debugging symbols. |
| 43 | + |
| 44 | +Your basic flow as you get started is: |
| 45 | + |
| 46 | +1. Identify the source file you want to debug. |
| 47 | +2. Build that file with debugger symbols using a command similar to `USE_CUSTOM_DEBINFO="aten/src/ATen/native/Linear.cpp" python setup.py develop`. |
| 48 | +3. Start a debugger session with a breakpoint. You'll discover additional files you want to debug. |
| 49 | +4. Add those files to the `USE_CUSTOM_DEBINFO`. |
| 50 | +5. Rebuild those files. |
| 51 | +6. Rebuild with a command similar to `USE_CUSTOM_DEBINFO="aten/src/ATen/native/Linear.cpp;newfile.cpp" python setup.py develop`. |
| 52 | +7. Start your debugger session again. |
| 53 | + |
| 54 | +Again, the key line environment variable to set is `USE_CUSTOM_DEBINFO`. At this point, your PyTorch |
| 55 | +is built with debugging symbols and ready for GDB command line to debug! However, we recommend |
| 56 | +debugging with VSCode, and we will review the instructions to integrate with VSCode shortly. |
| 57 | + |
| 58 | +### Ensuring your file is built |
| 59 | + |
| 60 | +For PyTorch, in our experience, you'll need to do a full clean and rebuild each time. Unfortunately, touching a file to update its timestamp does not seem to reliably rebuild that file. |
| 61 | + |
| 62 | +In the output of the `python setup.py develop` command, look for a line that starts with `Source files with custom debug infos` |
| 63 | +to make sure your file is correctly being built with debugger symbols. For example: |
| 64 | + |
| 65 | +``` sh |
| 66 | +-- USE_ROCM_KERNEL_ASSERT : OFF |
| 67 | +-- Performing Test HAS_WMISSING_PROTOTYPES |
| 68 | +-- Performing Test HAS_WMISSING_PROTOTYPES - Failed |
| 69 | +-- Performing Test HAS_WERROR_MISSING_PROTOTYPES |
| 70 | +-- Performing Test HAS_WERROR_MISSING_PROTOTYPES - Failed |
| 71 | +-- Source files with custom debug infos: aten/src/ATen/Utils.cpp aten/src/ATen/ScalarOps.cpp aten/src/ATen/EmptyTensor.cpp aten/src/ATen/core/Tensor.cpp aten/src/ATen/native/Linear.cpp |
| 72 | +``` |
| 73 | + |
| 74 | +It may also be helpful to ensure that your previous debugger session is shut down. |
| 75 | + |
| 76 | +## VSCode Configuration |
| 77 | + |
| 78 | +Integrating with VSCode will require installing the C/C++ Extension Pack, published by Microsoft. Search in the Extensions tab of VSCode with the identifier `ms-vscode.cpptools-extension-pack`. |
| 79 | + |
| 80 | + |
| 81 | + |
| 82 | +Next, you'll need to create a `launch.json` in the `pytorch/.vscode` folder. Here is |
| 83 | +a sample file to start from. You'll need to adjust the file paths to match your specific installation. |
| 84 | + |
| 85 | +``` json |
| 86 | +{ |
| 87 | + "version": "0.2.0", |
| 88 | + "configurations": [ |
| 89 | + { |
| 90 | + "name": "GDB a python interpreter", |
| 91 | + "type": "cppdbg", |
| 92 | + "request": "launch", |
| 93 | + "program": "/home/USERNAME/miniconda3/envs/torch310/bin/python", // Replace with your executable's path |
| 94 | + "args": [], |
| 95 | + "cwd": "${workspaceFolder}", |
| 96 | + "environment": [], |
| 97 | + "externalConsole": false, |
| 98 | + "MIMode": "gdb", |
| 99 | + "setupCommands": [ |
| 100 | + { |
| 101 | + "description": "Enable pretty-printing for gdb", |
| 102 | + "text": "-enable-pretty-printing", |
| 103 | + "ignoreFailures": true |
| 104 | + }, |
| 105 | + { |
| 106 | + "description": "Set Disassembly flavor to Intel", |
| 107 | + "text": "-gdb-set disassembly-flavor intel", |
| 108 | + "ignoreFailures": true |
| 109 | + } |
| 110 | + ], |
| 111 | + // "preLaunchTask": "C/C++: g++ build active file", |
| 112 | + "miDebuggerPath": "/home/USERNAME/miniconda3/envs/torch310/bin/gdb" // Replace with your gdb location |
| 113 | + } |
| 114 | + ] |
| 115 | + } |
| 116 | + ``` |
| 117 | + |
| 118 | +## LLDB |
| 119 | + |
| 120 | +You can also debug with LLDB instead of GDB. In our experience, LLDB is faster. But both have their quirks, and you may benefit from switching between the two. |
| 121 | + |
| 122 | +Install LLDB for VSCode by searching in the Extensions tab of VSCode with the identifier `vadimcn.vscode-lldb`. |
| 123 | + |
| 124 | +Then add this to your launch.json file: |
| 125 | + |
| 126 | +``` json |
| 127 | + { |
| 128 | + "name": "LLDB Python", |
| 129 | + "type": "lldb", |
| 130 | + "request": "launch", |
| 131 | + "program": "/home/yho_google_com/miniconda3/envs/torch310/bin/python", |
| 132 | + |
| 133 | + } |
| 134 | +``` |
| 135 | + |
| 136 | + |
| 137 | +## Using VSCode's Visual Debugger |
| 138 | + |
| 139 | +First, open the file you want to debug. |
| 140 | + |
| 141 | + |
| 142 | + |
| 143 | +Second, click to the left of the line number you want to set a breakpoint. You'll see a red dot there, and, in the lower left of the debugger tab. |
| 144 | + |
| 145 | + |
| 146 | + |
| 147 | +Third, you will start the debugger session. Select the GDB or LLDB configuration using the dropdown to the right of the green play button. Now press the green play button. This triggers the rules we |
| 148 | +set in the launch.json file. |
| 149 | + |
| 150 | +Notice that the red button now fades to an empty white circle. That's because you have an active session, but you have not imported torch yet, so the torch library you built with debugger symbols is not yet loaded. |
| 151 | + |
| 152 | + |
| 153 | + |
| 154 | +In the python interpretor, `import torch`. This loads the torch library you built. Now, the breakpoints become bright red again to indicate that they are active. |
| 155 | + |
| 156 | + |
| 157 | + |
| 158 | +Run a command that will trigger the breakpoint, namely, `torch.einsum()`. Notice the yellow arrow indicating the current file location, and the variables and call stack information on the left. You are debugging! |
| 159 | + |
| 160 | + |
| 161 | + |
| 162 | +## A realistic build command |
| 163 | + |
| 164 | +Over time, you'll collect additional flags to your build command, such as not building certain libraries to speed up builds, or adding diagnostics. Here is one example that turns off building CUDA and turns on handling an environment variable to print dispatcher traces. |
| 165 | + |
| 166 | +``` sh |
| 167 | +USE_CUSTOM_DEBINFO="aten/src/ATen/native/Linear.cpp" USE_CUDA=0 LD_LIBRARY_PATH=/home/USERNAME/miniconda3/envs/torch310/lib CFLAGS="-DHAS_TORCH_SHOW_DISPATCH_TRACE" python setup.py develop |
| 168 | +``` |
| 169 | + |
| 170 | +## Future Work |
| 171 | + |
| 172 | +This guide has demonstrated how to build debugging symbols for PyTorch C++ files. Future work will demonstrate adding debugging symbols to PyTorch/XLA C++ files. |
0 commit comments