背景
- 使用Anaconda配置源碼環境
- 源碼需要使用
python setup.py
來編譯依賴cuda的torch拓展模塊,如 nms,ROIPool,ROIAlign等等 - 系統的CUDA和Conda裝的
cudatoolkit
版本不同
問題
符合上述背景條件或者類似條件,會導致一些奇怪的錯誤,例如:
ImportError: ***/ATSS/atss_core/_C.cpython-36m-x86_64-linux-gnu.so: undefined symbol: __cudaRegisterFatBinaryEnd
原因分析
按照源碼安裝教程,conda安裝pytorch時cudatoolkit
版本爲9.0
,而編譯源碼時,有一個依賴CUDA的拓展模塊atss_core._C
,查看編譯過程信息發現,使用的是系統默認CUDA,而非想象中的cudatoolkit
包,這就導致拓展模塊依賴的CUDA版本和Pytorch依賴的cuda版本不一,進而引發一些奇怪錯誤。
總結
在conda的虛擬環境中,編譯依賴cuda的torch拓展模塊時,並未優先使用cudatoolkit
包,轉而使用了系統CUDA包,如果兩個CUDA包版本不一,可能會引發一些意想不到的問題。
推薦解決方案
一般出現這種問題時,源碼作者可能指定了cudatoolkit
,則不好去改動其版本。
推薦在系統上再安裝一個對應CUDA版本,且不覆蓋原有(系統默認)版本,然後使用CUDA_HOME
環境變量來指出對應CUDA版本的安裝目錄,如 export CUDA_HOME=/usr/local/cuda-9.0
,這樣可以避免更改系統或用戶文件。
通過這種方式,只要安裝時不覆蓋系統默認版本,不會影響其它用戶。如果你僅在terminal中臨時export,還能避免對其他依賴cuda程序的影響,很方便。
深入分析
按理說既然是在同一個虛擬環境下,編譯涉及CUDA的拓展模塊,應該優先搜索該虛擬環境下conda安裝的cudatoolkit
包,就能避免該問題。
進一步分析源碼發現,cuda根目錄由torch.utils.cpp_extension
給出,而torch.utils.cpp_extension
中的_find_cuda_home
函數,只要沒有設置CUDA_HOME
或CUDA_PATH
環境變量,就會返回默認系統路徑/usr/local/cuda
。