![]() 作者|王益、嚴浩翻譯|程浩源、董文文 1GDB Python3PyTorch官方發(fā)布了如何使用GDB對Python觸發(fā)的C++代碼進行調(diào)試的指南,詳情參考: https://github.com/pytorch/pytorch/blob/master/CONTRIBUTING.md#gdb-integration 其核心思路是運行gdb python3。在GDB會話中,可以為給定的C++函數(shù)名設置斷點,如at::Tensor::neg。GDB當前無法找到這個函數(shù),prompt中會提示是否在共享庫加載時將斷點掛起,回答yes。然后輸入run,GDB會啟動Python解釋器。Python解釋器會提示輸入Python源碼。輸入import torch,然后回車。 當Python解釋器執(zhí)行import語句時,會加載相關(guān)的共享庫。GDB會監(jiān)視加載并設置斷點。執(zhí)行Python源碼,觸發(fā)斷點,然后打開GDB prompt進行C++調(diào)試,例如使用 bt 檢查回溯,使用 l 顯示Python調(diào)用的C++代碼。 2在調(diào)試模式下編譯OneFlowLinux系統(tǒng)OneFlow 支持 Linux,暫不支持macOS和Windows。本文主要介紹在AWS GPU主機上運行Amazon Linux 2(類似于CentOS)。 (base) [wkyi ~]$ cat /etc/os-releaseNAME='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:///'Conda或Docker環(huán)境OneFlow官方文檔建議使用Conda或Docker鏡像: https://github.com/Oneflow-Inc/oneflow#option-1-build-with-conda-recommended。本次運行使用Anaconda。使用Conda或Docker是為了修復C++編譯器和其他構(gòu)建工具鏈的版本。使用新版本的g++需要對源代碼進行更新,如 https://github.com/Oneflow-Inc/oneflow/issues/8397。 編譯調(diào)試版本這里要注意,必須先編譯OneFlow的調(diào)試版本,因為GDB需要調(diào)試符號才能使 bt 和 l 的輸出有意義。
我安裝的是CPU版本的OneFlow,創(chuàng)建了cpu.cmake文件。因為我的 AWS 主機不在中國,所以是在international目錄下創(chuàng)建文件。 報錯在安裝報錯時,我在GitHub上提交了相關(guān)issue (https://github.com/Oneflow-Inc/oneflow/issues?q=is%3Aissue+author%3Awangkuiyi),OneFlow的研發(fā)人員快速給出了回應,向他們致敬! 編譯步驟本小節(jié)將展示編譯OneFlow的具體步驟: 1. 下載安裝Anaconda。默認安裝路徑是 ~/anaconda3。安裝時將環(huán)境變量添加到~/.bashrc。然后,獲取環(huán)境變量或重新連接主機使更改生效。 2. 創(chuàng)建并激活Conda環(huán)境,具體步驟參考: https://github.com/Oneflow-Inc/conda-env 3. Git clone源碼 mkdir ~/w cd ~/w git 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) 運行和調(diào)試 安裝好后,在~/w/oneflow/build 目錄中會出現(xiàn) source.sh文件,這個文件設置了PYTHONPATH 環(huán)境。運行下列命令使設置生效。 source source.sh然后,用GDB運行Python編輯器。 在GDB prompt中,我在oneflow::one::Tensor::is_eager設置了一個斷點,在共享庫加載時會將斷點掛起。 (gdb) b oneflow::one::Tensor::is_eagerFunction 'oneflow::one::Tensor::is_eager' not defined.Make breakpoint pending on future shared library load? (y or [n]) yBreakpoint 1 (oneflow::one::Tensor::is_eager) pending.再然后,輸入run運行Python編輯器。在Python prompt中,輸入oneflow。
導入的時間會比平時更長。如果顯示ImportError,要檢查是否運行了source source.sh。 接下來就可以來創(chuàng)建tensor了。 >>> a = oneflow.tensor(1)Thread 1 'python3' hit Breakpoint 1, oneflow::one::CopyBetweenMirroredTensorAndNumpy<long> (t=..., array=array@entry=0x7fffe5905150, Copy=<optimized out>, Copy@entry=0x7fffefc977e0 <oneflow::BlobNumpyCopyUtil<long>::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:9898 CHECK_OR_RETURN(tensor->is_eager()) << 'eager tensors supported only.';輸入回車,此行代碼執(zhí)行會觸發(fā)斷點。 上述信息表明在源文件的第 98 行有一個名為tensor->is_eager()的函數(shù) oneflow::one::CopyBetweenMirroredTensorAndNumpy。 要顯示更多內(nèi)容,可以輸入l。在第 98 行,調(diào)用了tensor->is_eager()。
你可能會好奇,為什么在Python中創(chuàng)建tensor會觸發(fā)對Tensor::is_eager的調(diào)用?可以輸入bt來顯示更多信息。 (gdb) bt#0 oneflow::one::CopyBetweenMirroredTensorAndNumpy<long> (t=..., array=array@entry=0x7fffe5905150, Copy=<optimized out>, Copy@entry=0x7fffefc977e0 <oneflow::BlobNumpyCopyUtil<long>::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#1 0x00007fffefd5aa5c in oneflow::one::CopyMirroredTensorFromUntypedArray<long> (array=0x7fffe5905150, tensor=...) at /home/wkyi/w/oneflow/oneflow/api/python/utils/tensor_utils.cpp:61#13 0x00007fffefbe433f in oneflow::one::functional::tensor (self=<optimized out>, args=<optimized out>, kwargs=<optimized out>) 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=<optimized out>, nargs=<optimized out>, kwnames=<optimized out>) 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調(diào)用堆棧的底部是_stack,它是Python編輯器的入口點。從上面的代碼中可以看到Python和OneFlow共享庫之間的調(diào)用邊界——Python中的_PyMethodDef_RawFastCallKeywords函數(shù)調(diào)用了OneFlow的C++函數(shù)oneflow::one::functional::tensor,進而觸發(fā)了對oneflow::one::Tensor::is_eager的調(diào)用 ![]()
![]() 2.https://of-worldwide./JuQ0AuodVJn4/Use-GDB-to-Walkthrough-OneFlow-Source-Code (本文經(jīng)授權(quán)后編譯發(fā)布) |
|
|