這里提到的CenterNet指的是Keypoint Triplets for Object Detection,因為最近看了很多關於anchor-free的論文,其中也有很多如CornerNet、ExtremeNet、CenterNet使用的方法相似,而且網絡的backbone使用的也相同,所以想要直接通過對CenterNet的理解來理解相關論文的實驗流程。
Code Github:https://github.com/xingyizhou/CenterNet
&基本配置
配置流程在對應的github中都有介紹,在此也簡單介紹一下:
1、搭建conda的虛擬環境
conda create --name CenterNet --file conda_packagelist.txt source activate CenterNet
2、編譯代碼
cd <dir>/models/py_utils/_cpools python setup.py install --user # 其中--user是為了python能夠創建文件而不需要權限 cd <dir>/external make # 在進行下一步之前,需要建立在coco文件夾下建立對應的需要使用到的數據及信息 # 名稱需要依照使用的模型文件中的定義,或者將配置文件中的定義改成自定義的名稱 cd <dir>/data/coco/PythonAPI dake
& 問題及解決方案
首先,我使用的是4卡的服務器,但是成功運行時使用的是2個gpu,下面將我在配置此代碼過程中遇到的主要問題進行介紹。而且在網上搜索相應內容的時候,網上的解決方案對我並不適用。
1、RuntimeError: CUDA error: out of memory
這個問題我遇到兩種,第一種是在修改了文件中的一些配置,如相關的數據庫的路徑,以及threads的數量,然后直接運行代碼就出現了下面的錯誤。
在遇到這個問題時,我以為是一般的0卡的內存不夠用,然后在train.py中聲明了CUDA_VISIBLE_DeVICES環境變量,只將當前占用較少的GPU顯示表示,然后設置Threads為1。
這個方法在只有out of memory,或者是后面說明了當前使用的GPU還差多少內存的時候,才能使用,此時表明當前使用的GPU的大小或者數量不支持運算。
2、Runtime Error: CUDA error: invalid device ordinal
首先說明一點,使用的環境不一樣,每個人的問題解決方案可能也是不同的,要仔細看問題報錯的原因,以及看代碼,比如在遇到這個問題的時候,我搜索了一下,基本上都是關於使用的device的問題,系統讀取時是通過device(“cuda:1”)進行讀取的,我將torch._C._scatter()的結果打印出來,確實在每一行的最后都跟隨着一個device=1的標記。但是在整個項目中並沒有出現device(“cuda:1”)的問題,因此按照網上給出的解決方法了調節一些參數,如將cudnn.enabled設置為False等等都是沒用的。
而我這個問題是需要分析一下代碼,錯誤信息在這里的作用也並不明顯。需要注意我先前提到過的threads的數量與chunk的匹配關系,根據整體運行錯誤的分析,當前代碼使用的多線程模式應當是靜態分配,也就是一個chunk對應一個線程,而且在配置文件中所有的chunk的和,需要與batch_size的大小相匹配,如最終使用2個treads,那么此時就只能設置兩個chunk,也就是配置文件中國的“chunk_size=[6, 6]”,對應的“batch_size”設置為12。當然在batch_size與chunk的和不匹配的時候,也會出現sum(chunk)=**, but ** expected的報錯問題。
3、AttributeError: ‘NoneType’ object has no ‘cudaEventCreateWithFlags’
這個問題是出現在所有的問題基本上都調節好了之后運行代碼時產生的,在網上也沒有這個內容的詳細解決方案,只能一步步看源碼,一步步輸出打印,跟着代碼走的時候確實發現了一些不同之處,在運行的所有文件中也確實沒有對於cudaEventCreateWithFlags的定義。
由於之前我也跑過mmdetection的代碼,使用的也是多GPU模式,就參照了其使用DataParalell的代碼,也的確在其中發現了一些不同尋常的地方:mmdetection中使用多GPU的代碼,其中定義device_ids以及output_device的方法不一樣,mmdetection中多出了_get_device_index函數,我就嘗試着將代碼進行了修改,在dataparalell.py中,具體如下:
同時在這個代碼的最后還要將mmdetection中utils的_get_device_index函數copy進來,以正常使用。
總結一下,最終修改的部分是在
- dataparalell.py的device_ids以及output_device;
- 項目默認使用的chunk_size是8組,如果使用的threads的數量不是8的話,可能需要進行修改,包括threads的數量、chunk_size以及batch_size;
- 如果再次運行出現out of memory,可以嘗試修改CUDA_VISIBLE_DEVICES變量。