电竞比分网-中国电竞赛事及体育赛事平台

分享

OneFlow源碼一覽:GDB編譯調(diào)試

 520jefferson 2022-07-14 發(fā)布于北京
圖片


作者|王益、嚴浩

翻譯|程浩源、董文文

1

GDB Python3

PyTorch官方發(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)試模式下編譯OneFlow

Linux系統(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)試符號才能使 btl 的輸出有意義。

cd ~/w/oneflow/buildCMAKE_BUILD_TYPE=Debug cmake .. -C ../cmake/caches/international/cpu.cmake

我安裝的是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 python3

在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。

(gdb) runStarting program: /home/wkyi/anaconda3/envs/oneflow-dev-gcc7-v2/bin/python3Missing 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 linuxType 'help', 'copyright', 'credits' or 'license' for more information.>>> import 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()。

(gdb) l93    inline Maybe<void> CopyBetweenMirroredTensorAndNumpy(94        const std::shared_ptr<Tensor>& t, PyObject* array,95        Maybe<void> (*Copy)(uint64_t, const NumPyArrayPtr&), const std::string& modifier,96        bool block_host_until_done) {97      auto tensor = JUST(t->AsMirroredTensor());98      CHECK_OR_RETURN(tensor->is_eager()) << 'eager tensors supported only.';99100      if (block_host_until_done) {101        NumPyArrayPtr array_ptr(array);102        const auto& Callback = [array_ptr, Copy](uint64_t ofblob_ptr) {

你可能會好奇,為什么在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)用

上述內(nèi)容展示了如何使用GDB對C++編寫的Python庫進行調(diào)試。以下將更進一步,展示如何在VSCode中調(diào)用GDB,以便更輕松地定位代碼。

要想在Python C++庫中使用GDB,需要進行如下操作:

1. 構(gòu)建C++庫的調(diào)試版本
2. 用GDB啟動Python解釋器
3. 在C++函數(shù)中設置斷點,例如b oneflow::one::functional::tensor
4. 在Python REPL中運行代碼,觸發(fā)斷點,然后GDB會在斷點處暫停

按照以下方法改進VSCode用戶界面

1. 安裝Microsoft的“C/C++”擴展,該擴展支持GDB調(diào)試器
2. 添加新的調(diào)試啟動配置

圖片

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. 然后就可以啟動調(diào)試器“GDB”并設置斷點。當調(diào)試器在斷點處暫停時,VSCode也會跳轉(zhuǎn)到源代碼行,側(cè)邊欄中的變量會與調(diào)用棧一起顯示。要想更好地理解代碼,也可以單步執(zhí)行各個函數(shù)。

圖片

參考來源:
1.https://code./docs/cpp/launch-json-reference

2.https://of-worldwide./JuQ0AuodVJn4/Use-GDB-to-Walkthrough-OneFlow-Source-Code

(本文經(jīng)授權(quán)后編譯發(fā)布)

其他人都在看

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多