現在 OpenCV 的 GPU 介面可以說非常可用了,但是這個內存和顯存來回拷貝的問題,一直讓我無從下手。比如寫了一些識別的演算法,想在 GPU 上跑,每次從攝像頭讀回來的圖像都要從內存拷貝到顯存,結果就是負加速。

但是,我覺得可能是我打開的方式不太對。因為 OpenCV 對 GPU 的介面開發的這麼積極,nVidia 在 GPU 加速領域大展身手,肯定不是沒有道理的。

所以,我特別想知道,那些用 GPU 加速視覺處理的(比如雙目),是怎麼解決的這個問題的?

我大致了解下,CSI 介面的攝像頭的圖像數據是可以直接進顯存的?


TX1的話好像是CPU/GPU共享內存?有個zero copy,可以試試,省去拷貝的時間。

通常來說這類問題都是靠流水線化操作,提高吞吐量來掩蓋延遲的。傳輸數據的時候乾等著的話,效率低是必然的。


內存拷貝和kernel執行可以並行。

也可以在CPU做一些編碼壓縮,如H264。然後只拷貝編碼的數據包到GPU,用NVDEC解碼,減少要拷貝的數據量。


當然你得用cuda stream 把攝像頭每一幀「流」起來,這樣就掩蓋了copy的延遲,而不同的stream又可以並行,throughput肯定不是問題


誠如前面朋友所言,zero copy技術可以解決題主的問題:

https://ohmwardbond.blogspot.jp/2017/03/zero-copy-cuda-opencv-and-nvidia-jetson.html?

ohmwardbond.blogspot.jp

http://ohmwardbond.blogspot.com/2017/03/zero-copy-cuda-opencv-and-nvidia-jetson_15.html?

ohmwardbond.blogspot.com

兩篇博客,已經把zero copy在題主所用的場景(opencv, tk1)下的使用講的很好了,可以參考一下。

如果題主訪問不了,可以直接搜索Zero-Copy: CUDA, OpenCV and NVidia Jetson TK1,國內有搬運。


數據傳輸的效率確實很重要,包括內存與顯存、GPU上的數據讀寫等,最開始寫CUDA的時候也遇到了CUDA寫的程序跑的比OpenCV還慢。

針對第一個問題,內存與顯存之間的數據傳輸效率問題,&這本書裡面有專門的一節講優化的,總的來說,主要包括以下幾種方法:

  1. 使用鎖頁內存,這樣CPU與GPU之間的數據傳輸是就可以是非同步的,也就可以與Kernel並行執行;但使用的時候,必須得預先完成內存空間的分配,不然很耗時!
  2. 使用Zero Copy,此時GPU可以直接讀取CPU內存上的數據,也支持數據傳輸與計算之間的Overlap。但要避免CPU與GPU之間的多次傳輸。TX1上內存和顯存確實是同一個存儲,可以考慮。
  3. 使用Unified Virtual Addressing ,此時CPU與所有的GPU之間共享一個虛擬的定址空間。

當程序僅需到ms級或以下的時候,給我的感覺是優化就得非常非常小心了。。。

針對第二個問題,外設的數據是可以直接進入GPU現存的,Nvidia有一個GPUDirect RDMA,可以讓GPU通過PCIe直接讀取第三方硬體的數據。官方有文檔介紹


要做加速這件事,首先需要分析出耗時的瓶頸在哪裡。

如果處理過程是計算密集的(例如存在大量卷積等操作),耗時瓶頸在計算上,那麼使用gpu做並行計算加速可以起到顯著效果,因為這種情況下數據從cpu傳輸到gpu的開銷佔比非常小。

而如果處理過程不是計算密集型的,瓶頸並不在計算上,那麼這時使用gpu加速的效果就很一般了,甚至有可能起到反效果,原因正如題主所說,此時數據拷貝的開銷反而佔據更大的比重。

目前視覺領域使用gpu進行加速的場景都是計算密集的(例如deep learning的訓練和預測),如果題主所處理的問題不符合上述第一種特點,恐怕需要考慮其他加速方法。


從攝像頭直接到顯存跨過內存,有點類似協處理器(不使用cpu直接dma操作)。我也有這個疑問,但目前我們實際項目還是得拷貝。


推薦閱讀:
相关文章