文章图片
作者|王益、严浩 翻译|程浩源、董文文
1
GDB Python3 PyTorch官方发布了如何使用GDB对Python触发的C++代码进行调试的指南,详情参考:
https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md#gdb-integration
其核心思路是运行gdb python3。在GDB会话中,可以为给定的C++函数名设置断点,如at::Tensor::neg。GDB当前无法找到这个函数,prompt中会提示是否在共享库加载时将断点挂起,回答yes。然后输入run,GDB会启动Python解释器。Python解释器会提示输入Python源码。输入import torch,然后回车。
当Python解释器执行import语句时,会加载相关的共享库。GDB会监视加载并设置断点。执行Python源码,触发断点,然后打开GDB prompt进行C++调试,例如使用 bt 检查回溯,使用 l 显示Python调用的C++代码。
2
在调试模式下编译OneFlow
Linux系统
OneFlow 支持 Linux,暂不支持macOS和Windows。本文主要介绍在AWS GPU主机上运行Amazon Linux 2(类似于CentOS)。
(base) [wkyi ~]$ cat /etc/os-release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;
33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
Conda或Docker环境
OneFlow官方文档建议使用Conda或Docker镜像:
https://github.com/Oneflow-Inc/oneflow#option-1-build-with-conda-recommended。本次运行使用Anaconda。使用Conda或Docker是为了修复C++编译器和其他构建工具链的版本。使用新版本的g++需要对源代码进行更新,如 https://github.com/Oneflow-Inc/oneflow/issues/8397。
编译调试版本
这里要注意,必须先编译OneFlow的调试版本,因为GDB需要调试符号才能使 bt 和 l 的输出有意义。
cd ~/w/oneflow/build
CMAKE_BUILD_TYPE=Debug cmake .. -C ../cmake/caches/international/cpu.cmake
我安装的是CPU版本的OneFlow,创建了cpu.cmake文件。因为我的 AWS 主机不在中国,所以是在international目录下创建文件。
报错
在安装报错时,我在GitHub上提交了相关issue
(https://github.com/Oneflow-Inc/oneflow/issues?q=is%3Aissue+author%3Awangkuiyi),OneFlow的研发人员快速给出了回应,向他们致敬!
编译步骤
本小节将展示编译OneFlow的具体步骤:
1. 下载安装Anaconda。默认安装路径是 ~/anaconda3。安装时将环境变量添加到~/.bashrc。然后,获取环境变量或重新连接主机使更改生效。
【前沿技术|OneFlow源码一览(GDB编译调试)】2. 创建并激活Conda环境,具体步骤参考: https://github.com/Oneflow-Inc/conda-env
3. Git clone源码
mkdir ~/wcd ~/wgit clone https://github.com/Oneflow-Inc/oneflow
4. 编译OneFlow
cd oneflow mkdir build cd build CMAKE_BUILD_TYPE=Debug cmake .. -C ../cmake/caches/international/cpu.cmake make -k -j $(nproc)
运行和调试
安装好后,在~/w/oneflow/build 目录中会出现 source.sh文件,这个文件设置了PYTHONPATH 环境。运行下列命令使设置生效。
source source.sh
然后,用GDB运行Python编辑器。
gdb python3
在GDB prompt中,我在oneflow::one::Tensor::is_eager设置了一个断点,在共享库加载时会将断点挂起。
(gdb) b oneflow::one::Tensor::is_eager
Function "oneflow::one::Tensor::is_eager" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (oneflow::one::Tensor::is_eager) pending.
再然后,输入run运行Python编辑器。在Python prompt中,输入oneflow。
(gdb) run
Starting program: /home/wkyi/anaconda3/envs/oneflow-dev-gcc7-v2/bin/python3
Missing separate debuginfos, use: debuginfo-install glibc-2.26-58.amzn2.x86_64
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Python 3.7.10 (default, Feb 26 2021, 18:47:35)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import oneflow
导入的时间会比平时更长。如果显示ImportError,要检查是否运行了source source.sh。
接下来就可以来创建tensor了。
>>> a = oneflow.tensor(1)Thread 1 "python3" hit Breakpoint 1, oneflow::one::CopyBetweenMirroredTensorAndNumpy (t=..., array=array@entry=0x7fffe5905150, Copy=,
Copy@entry=0x7fffefc977e0 ::From(unsigned long, oneflow::NumPyArrayPtr const&)>, modifier=...,
block_host_until_done=block_host_until_done@entry=false) at /home/wkyi/w/oneflow/oneflow/api/python/utils/tensor_utils.h:98
98CHECK_OR_RETURN(tensor->is_eager()) << "eager tensors supported only.";
输入回车,此行代码执行会触发断点。
上述信息表明在源文件的第 98 行有一个名为tensor->is_eager()的函数 oneflow::one::CopyBetweenMirroredTensorAndNumpy。
要显示更多内容,可以输入l。在第 98 行,调用了tensor->is_eager()。
(gdb) l
93inline Maybe CopyBetweenMirroredTensorAndNumpy(
94const std::shared_ptr& t, PyObject* array,
95Maybe (*Copy)(uint64_t, const NumPyArrayPtr&), const std::string& modifier,
96bool block_host_until_done) {
97auto tensor = JUST(t->AsMirroredTensor());
98CHECK_OR_RETURN(tensor->is_eager()) << "eager tensors supported only.";
99
100if (block_host_until_done) {
101NumPyArrayPtr array_ptr(array);
102const auto& Callback = [array_ptr, Copy](uint64_t ofblob_ptr) {
你可能会好奇,为什么在Python中创建tensor会触发对Tensor::is_eager的调用?可以输入bt来显示更多信息。
(gdb) bt
#0oneflow::one::CopyBetweenMirroredTensorAndNumpy (t=..., array=array@entry=0x7fffe5905150, Copy=,
Copy@entry=0x7fffefc977e0 ::From(unsigned long, oneflow::NumPyArrayPtr const&)>, modifier=...,
block_host_until_done=block_host_until_done@entry=false) at /home/wkyi/w/oneflow/oneflow/api/python/utils/tensor_utils.h:98
#10x00007fffefd5aa5c in oneflow::one::CopyMirroredTensorFromUntypedArray (array=0x7fffe5905150, tensor=...)
at /home/wkyi/w/oneflow/oneflow/api/python/utils/tensor_utils.cpp:61#13 0x00007fffefbe433f in oneflow::one::functional::tensor (self=, args=, kwargs=)
at /home/wkyi/w/oneflow/build/oneflow/api/python/functional/tensor_api.yaml.pybind.cpp:96
#14 0x00005555556b98b4 in _PyMethodDef_RawFastCallKeywords () at /tmp/build/80754af9/python_1614362349910/work/Objects/call.c:693
#15 0x00005555556b99d1 in _PyCFunction_FastCallKeywords (func=0x7ffdc75675a0, args=, nargs=, kwnames=)
at /tmp/build/80754af9/python_1614362349910/work/Objects/call.c:732#29 0x000055555578c22c in _Py_UnixMain () at /tmp/build/80754af9/python_1614362349910/work/Modules/main.c:3495
#30 0x00007ffff783113a in __libc_start_main () from /lib64/libc.so.6
#31 0x0000555555730e90 in _start () at ../sysdeps/x86_64/elf/start.S:103
调用堆栈的底部是_stack,它是Python编辑器的入口点。从上面的代码中可以看到Python和OneFlow共享库之间的调用边界——Python中的_PyMethodDef_RawFastCallKeywords函数调用了OneFlow的C++函数oneflow::one::functional::tensor,进而触发了对oneflow::one::Tensor::is_eager的调用
上述内容展示了如何使用GDB对C++编写的Python库进行调试。以下将更进一步,展示如何在VSCode中调用GDB,以便更轻松地定位代码。
要想在Python C++库中使用GDB,需要进行如下操作:
1. 构建C++库的调试版本
2. 用GDB启动Python解释器
3. 在C++函数中设置断点,例如b oneflow::one::functional::tensor
4. 在Python REPL中运行代码,触发断点,然后GDB会在断点处暂停
按照以下方法改进VSCode用户界面
1. 安装Microsoft的“C/C++”扩展,该扩展支持GDB调试器
2. 添加新的调试启动配置
文章图片
3. 添加下列配置
{
"version": "0.2.0",
"configurations": [
{
"type": "cppdbg",
"request": "launch",
"name": "GDB",
"program": "/home/charlieyan/anaconda3/envs/oneflow-dev-gcc7-v2/bin/python
"cwd": ".",
"environment": [
{
"name": "PYTHONPATH",
"value": "/home/charlieyan/proj/oneflow/python"
}
]
}
]
}
4. 然后就可以启动调试器“GDB”并设置断点。当调试器在断点处暂停时,VSCode也会跳转到源代码行,侧边栏中的变量会与调用栈一起显示。要想更好地理解代码,也可以单步执行各个函数。
文章图片
参考来源:
1.https://code.visualstudio.com/docs/cpp/launch-json-reference
2.https://of-worldwide.quip.com/JuQ0AuodVJn4/Use-GDB-to-Walkthrough-OneFlow-Source-Code
(本文经授权后编译发布)
其他人都在看
- OneFlow v0.7.0发布
- 图解OneFlow的学习率调整策略
- 解读Pathways:向前一步是OneFlow
- OneFlow源码解析:算子签名的自动推断
- Hinton:我的五十年深度学习生涯与研究心法
- LLVM之父:为什么我们要重建AI基础设施软件
- 并行计算的量化模型及其在深度学习引擎的应用
https://github.com/Oneflow-Inc/oneflow/
文章图片
https://github.com/Oneflow-Inc/oneflow/
推荐阅读
- 业界观点|LLVM之父Chris Lattner(为什么我们要重建AI基础设施软件)
- 网络|我,AI博士生,在线众筹研究主题
- Python每日一练|Python每日一练(牛客新题库)——第15天(综合练习)
- 图神经网络|图神经网络的基本知识
- 信息安全|网络安全自学篇
- LSTM神经网络算法
- 人工智能论文总结|一种基于超像素和生成对抗网络的视网膜血管分割方法
- 机器学习|基于双任务一致性的半监督医学图像分割
- 深度学习|基础GAN实例(pytorch代码实现)