2019年5月17日 星期五

如何讓Nvidia Jetson Nano能順利執行OpenCV4.1.0中CUDA相關函式

2015年在好友Edwin Huang贊助下拿到Nvidia最早的嵌入式開發板Jetson TK1,第一次感受到算力如此強大、價格如此實惠的平台,於是藉著這塊開發板開始了我的深度學習(雙關語)之旅。在當時Cuda, Cudnn, OpenCV整合的並不好,官方提供的套件也問題多多,加上為了讓深度學習框架Caffe能順利執行,光安裝環境竟花了快一個月才解決,坑多到有如月球表面,深怕一出狀況就要重新來過,為此還寫了足足八張A4紙的安裝說明文件。

Fig.1 Nvidia Jetson Nano (點擊圖片放大)


今(2019)年在好友James Wu贊助下,直接從美國帶回最新的Jetson Nano(以下簡稱Nano),一拿到手就迫不急待的開箱測試,沒想到從官網下載映像檔(image)[1]並燒進SD卡插入後開機就可使用,內建Ubuntu 18.04LTS並自帶CUDA10.0, OpenCV 3.3, TensorRT及多個加速計算庫等基本常用工具包,實在非常方便,不可同日而語。雖然官方說16GB的SD卡就夠用,但裝完後大概所剩無幾,於是我改用32GB SD卡,方便後面安裝OpenCV,QT及其它相關套件。而電源部份因為暫時沒有要大量執行,所以暫時使用5V/2A的變壓器供電,不會有當機或開不起來問題。

當大家都想著如何用Nano來玩深度學習,但我卻想著OpenCV中的那些GPU(CUDA)加速函式,因為有太多計算量大的視覺問題(如立體匹配等)只要靠那些GPU(CUDA)加速函式就足夠應付一秒二十到三十張的計算,解決ARM CPU計算速度不夠快及不易撰寫多執行緒的問題。

Fig. 2 OpenCV 4.1.0 CUDA加速函式庫 (點擊圖片放大)

雖然OpenCV3.3版後就已加入DNN模組,讓原本習慣寫C++的人能輕易整合原先函式,但其支援性直到最新的4.1版本才有明顯改善。不過可惜的是目前OpenCV中CUDA加速模組並不支援DNN模組,感覺上NVIDIA還是傾向直接使用一般框架(TensorFlow, TensorRT...)會更直接些。除此之外新版更對OpenVINO的支援性大幅提升,因此立馬決定要直接把OpenCV 4.1.0及QT5重新安裝到Nano,怎知惡夢再次降臨。

本來以為上次在樹莓派(3B+)上已經有裝OpenCV 4.0 + QT 5的經驗及步驟[2],但照著作一遍卻卡在CMAKE段,無法成功,上網查了好久,連最知名的PyImageSearch[3]都還故作神祕說再等等,最後皇天不負苦心人,讓我找到一些參考資料解決了這個大麻煩。接下來就帶著大家一步一步完成。

一、修正共享桌面錯誤


為了方便遠端操作Nano,不接螢幕、鍵盤、滑鼠,第一個想到就是安裝TeamViewer,不過卻無法順利執行,就先略過。後來發現Nano有提供「共享桌面」功能,沒想到一執行就發出錯誤訊息,上網查了一下才發現是官方版映像檔與舊的Gnome桌面不相容,要另外修正後才能使用。首先用文字編輯器(vi, nano, gedit...)開啟org.gnome.Vino.gschema.xml。

sudo nano /usr/share/glib-2.0/schemas/org.gnome.Vino.gschema.xml

然後把下列內容加入xml檔中,並存檔離開。

<key name='enabled' type='b'>
   <summary>Enable remote access to the desktop</summary>
   <description>
   If true, allows remote access to the desktop via the RFB
   protocol. Users on remote machines may then connect to the
   desktop using a VNC viewer.
   </description>
   <default>false</default>
</key>

再來編譯 Gnome schemas,執行下列指令。

sudo glib-compile-schemas /usr/share/glib-2.0/schemas

完成後,再次進入【設定】啟動【共享桌面】就可順利看到如下圖(Fig.3)所示畫面。勾選「允許其它使用者觀看及控制你的桌面」,再點選桌面左上角【搜尋應用程式】,輸入[Startup]搜尋啟動設定程式,進入設定畫面按「新增」,隨便輸入一個名字「Vino」及註解「VNC Server」,最重要的是在命令欄位中輸入「/usr/lib/vino/vino-server」最後按下存檔完成設定。

Fig. 3 共享桌面設定流程圖 (點擊圖片放大)

不過此時VNC還是無法連線,因為須禁用加密功能,打開「終端機」執行下面命令後,重啟Nano,並登入,即可在別台電腦使用VNC Viewer(不限那一種)來和Nano連線了。這裡有個地方要注意,Nano若沒有使用者登入是無法連線的,所以建議把使用者設定成自動登入,VNC才不會連不進。

gsettings set org.gnome.Vino require-encryption false
gsettings set org.gnome.Vino prompt-enabled false
sudo reboot

另外若想確認系統是否已有正確啟動VNC Server,可先安裝nmap,再用這個工具來檢查。

sudo apg-get install nmap
nmap 主機名稱或編址(IP)

若正常的話,應會看到下面資訊。

5900/tcp open  vnc

二、變更遠端連線桌面解析度


在沒有設定好第一項時只能乖乖在有HDMI螢幕及有鍵盤、滑鼠情狀況下操作,由於沒有裝USB WiFi上網,只好暫時用有線網路測試,當設定好後,而確認VNC有啟動,但從另一台筆電始終連不上,一開始以為是防火牆擋住了,試了好多種方案都不行,最後一檢查閘道(Gateway) IP才發現是自己搞了一個大烏龍,Nano和筆電分別在兩個閘道下難怪連不到,最後把Nano搬到同一個HUB後就解決VNC連不上的問題。

好不容易可以用VNC Viewer(RealVNC)連上線,此時發現因為沒插實體HDMI螢幕,所以解析度被降至很低,根本無法操作,因為很多內容都超出可見範圍。經過一番努力終於找到如何修正。只要打開終端機輸入下面指令即可調整成自己想要的解析度。至於更多xrandr用法請自行上網了解這裡不多做說明。

sudo xrandr --fb 1280x960

三、增加交換磁區大小


雖然Nano有4GB的DDR4,但為了後續編譯OpenCV及執行大型深度學習網路能正常運作,在這裡強烈建議再多開一些交換磁區(Swap File),至於要多少一般網友建議至少2~4GB,以下就以4GB舉例。這裡和樹莓派做法不一樣較為複雜些,首先建立一個專屬路徑(不能用sudo權限),進入後再以fallocate配置,再以chmod變更交換磁區的操作權限為600,最後再以mkswap, swapon將指定路徑變為交換磁區。

mkdir ~/swap/
cd ~/swap/
fallocate -l 4G swapfile
ls -lh swapfile
sudo chmod 600 swapfile
ls -lh swapfile
sudo mkswap swapfile
sudo swapon swapfile
swapon -s

最後為了使每次開機都能自動配置,所以要編輯/etc/fstab

sudo nano /etc/fstab

加入下列路徑,存檔後離開。

/home/ubuntu/swap/swapfile none swap sw 0 0


四、安裝必要套件

這個部份和之前發表過的文章「樹莓派(Pi 3+)安裝OpenCV 4 / QT5填坑心得」一樣,這裡就不多做說明。不過不一樣的是CMAKE部份要修正如下第五項說明。

五、調整CMAKE參數進行編譯


此次為了讓OpenCV能順利使用GPU(CUDA),所以編譯時要加入CUDA相關設定,包括WITH_CUDA, CUDA_FAST_MATH, CUDA_ARCH_BIN, CUDA_ARCH_PTX等等,而之前ENABLE_VFP3一定要刪掉,不能CMAKE會失敗,猜想應該是NVIDIA的ARM CPU和標準的有些不同吧??完整CMAKE指令如下。

sudo cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
-D ENABLE_NEON=ON \
-D WITH_CUDA=ON \
-D CUDA_FAST_MATH=1 \
-D CUDA_ARCH_BIN="5.3" \
-D CUDA_ARCH_PTX="" \
-D WITH_GSTREAMER=ON \
-D WITH_LIBV4L=ON \
-D BUILD_opencv_python2=ON \
-D BUILD_opencv_python3=ON \
-D WITH_FFMPEG=ON \
-D BUILD_TESTS=OFF \
-D WITH_QT=ON \
-D OPENCV_ENABLE_NONFREE=ON \
-D BUILD_PERF_TESTS=OFF \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D INSTALL_C_EXAMPLES=OFF \
-D BUILD_EXAMPLES=OFF ..

如須包含第四項內容的完整安裝程序,可至GITHUB下載JetsonNano_OpenCV410_QT5_CUDA_Install.sh,直接執行即可一次搞定。此次編譯(Make)時比上次樹莓派好多了,不用到一整天,大約只需二小時(含第四項再加一至二個小時,視網路速度而定)就可完成。另外發現一個小狀況,雖Ubuntu已有設定不進入睡眠,鎖定後也不用密碼,但遇到某些項目執行太久時還是會要sudo的密碼,請大家安裝時還是要偶而關心一下進度。

Nano預設是使用OpenCV 3.3, Python (2.7),而Python3要另行設定。而執行完上述所有程序後應該會把Python及Python3的環境都重設好,所以若使用Python的朋友可以測試一下用Python和Python3進入後執行下列指令確認OpenCV版本。

import cv2
cv2.__version__

六、設定QT工作環境


接下來就可以啟動QT Creator了,啟動後從主選單進入【工具】─【選項】─【建置並執行】發現【Comilers】和【Kits】的桌面環境都已設定好,直接就就可使用。

Fig.4 QT Creator工作環境設定 (點擊圖片放大)

七、撰寫及測試GPU加速函式


接下來就用QT來實現一個完整的測試例子,這裡主要是利用雙向濾波(Bilateral Filter)這項功能來測試CPU版和GPU(CUDA)版計算速度的差異。主程式主要配置一個可用於顯示cv::Mat格式的QLabel,另外搭配幾個簡單按鍵,用於載入圖像及計算雙向濾波。

Fig. 5 範例程式主畫面 (點擊圖片放大)

在OpenCV中,不是用GPU(CUDA)計算就一定會比CPU快,主要問題在於計算內容平行展開的程度(如矩陣計算),再來是影像是否一定停在GPU記憶體中計算,若不是則GPU常會表現得很差。在這個測試例中為了讓較清楚看出GPU性能表現,故意將雙向濾波的參數值加大。經測試後得到CPU執行時間約675ms(視作業系統忙碌狀況)變化不大。而GPU計算第一次會耗費較多的時間(391ms)而第二次執行少了約30%的時間(259ms),之後再執行則在200~300ms之間,因此得知GPU可能在第一次要配置相關記憶體及參數所以要花費較多時間。

Fig.6 CPU執行雙向濾波結果 (點擊圖片放大)
Fig. 7 GPU(CUDA)執行雙向濾波結果 (點擊圖片放大)

完整安裝腳本、範例程式及程式說明請至GITHUB OmniXRI/Jetson_Nano_OpenCV410_QT5下載。

結論:

經過這次的實測後確認OpenCV上CUDA的相關函式的確可以正常運行在Jetson Nano上,且明顯提升了不少計算效率,未來若再加上深度學習(DNN)模組,相信可玩出更多實用的案例,讓電腦視覺應用能更加便宜。

參考資料:

[1] NVIDIA Jetson Nano官網  https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit

[2] 樹莓派(Pi 3+)安裝OpenCV 4 / QT5填坑心得  https://omnixri.blogspot.com/2019/03/pi-3opencv-4-qt5.html

[3] PyImageSearch https://www.pyimagesearch.com/2019/05/06/getting-started-with-the-nvidia-jetson-nano/


本文歡迎轉發(貼)及非商業用途使用,若有引用部份文章或圖片時煩請註明出處、作者:「歐尼克斯實境互動工作室 作者:Jack Hsu」及本文網址,謝謝!
 

2 則留言:

【頂置】簡報、源碼、系列文快速連結區

常有人反應用手機瀏覽本部落格時常要捲很多頁才能找到系列發文、開源專案、課程及活動簡報,為了方便大家快速查詢,特整理連結如下,敬請參考! Edge AI Taiwan 邊緣智能交流區 全像顯示與互動交流區 台科大(NTUST) 人工智慧與邊緣運算實務 開南大學...