我使用簡單的 CPU 函式、CUDA 和 openCV(在 CPU 上)通過連續增加元素數量并測量運行時間來比較矩陣加法的性能。我已經繪制了下面的資料。請注意,它是每個資料型別的一個圖,其中 CUCV_8U 是 unsigned char 的宏,CUCV_16U=unsigned short,CUCV32F=float 和 CUCV64F=double。
我注意到,直到矩陣大約有 2^12 個元素,openCV 和 CUDA 的運行時間才會增加。在它們超過那個“限制”之后,運行時開始發散(注意對數縮放)。現在,我想解釋一下這個“限制”。
如果只是針對CUDA,我建議是由于可用的CUDA內核數,我的GTX 960是1024。當矩陣中的總元素數超過內核數時,執行緒無法執行不再并行,但同時執行。
但是,openCV 似乎遵循相同的趨勢(持續運行直到大約 2^12 個元素),所以我想知道這可能是什么原因。有人有想法嗎?
謝謝!
如果您需要有關我使用的代碼的資訊,請查看我的專案存盤庫
// CUDA Kernel
template <typename T>
__global__ void cuCV::kernel::add(DeviceCuMat<T> OUT, const DeviceCuMat<T> A, const DeviceCuMat<T> B) {
int col = blockIdx.x * blockDim.x threadIdx.x;
int row = blockIdx.y * blockDim.y threadIdx.y;
int ch = blockIdx.z * blockDim.z threadIdx.z;
int index = row * A.getWidth() col (A.getWidth()*A.getHeight()) * ch; // linearisation of index
if (col < A.getWidth() && row < A.getHeight() && ch < A.getNChannels())
OUT.getDataPtr()[index] = A.getDataPtr()[index] B.getDataPtr()[index];
}
uj5u.com熱心網友回復:
我注意到,直到矩陣大約有 2^12 個元素,openCV 和 CUDA 的運行時間才會增加。
啟動內核需要一些時間,因為它需要與作業系統(更具體地說是圖形驅動程式)互動,并且目標設備通常是PCI 設備(需要 PCI 通信)。I/O 操作通常很慢,而且通常有很大的延遲(對于 HPC 應用程式)。還有許多其他開銷需要考慮,包括在設備上分配資料、管理虛擬記憶體頁面等的時間。由于系統呼叫在大多數主流系統上往往需要至少 1 我們,而對于涉及離散 GPU 的系統則大約需要幾十我們,預計報告的時間。開始資料傳輸的時間一個基于 PCI 的 GPU 通常大約有數百個我們(在幾乎所有平臺上至少有 10 個我們)。
請注意,GPU 旨在執行大規模并行計算代碼,而不是低延遲代碼。擁有更多核心不會使小型計算更快,但可以更快地計算更多操作。這是阿姆達爾定律和古斯塔夫森定律的原理。
如果要計算小型矩陣,則不應使用離散 GPU。如果你有很多,那么你可以在 GPU 上有效地做到這一點,但使用一個大內核(不是每個矩陣 1 個內核)。
如果僅用于 CUDA,我建議這是由于可用 CUDA 內核的數量,我的 GTX 960 為 1024
這樣的計算不應受計算限制,而是受記憶體限制(否則,您應該清楚地優化內核,因為任何 GPU 都應該使記憶體飽和以進行此類基本操作)。因此,重要的是目標 GPU 的記憶體帶寬,而不是 CUDA 內核的數量。另請注意,GPU 的記憶體往往比一個 CPU 可以使用的速度更快,但延遲明顯更大。
另請注意,GTX 960 并非旨在高效計算雙精度計算。事實上,一個好的主流 CPU 在這樣的計算上應該明顯優于它。該 GPU 旨在加速簡單精度計算(通常用于游戲等 3D 應用程式)。如果你想加速雙精度計算,那么你需要一個(更昂貴的)基于服務器的 GPU。幸運的是,這對于記憶體系結代碼來說應該不是什么大問題。
OpenCV 似乎遵循相同的趨勢(持續運行直到大約 2^12 個元素)
OpenCV 實作仍然存在開銷。例如,創建執行緒需要一些時間,也需要分配資料(盡管它應該比 GPU 快得多),更不用說快取肯定是冷的(因此可能會受到快取未命中的限制)。在主流 Linux PC 上創建幾個執行緒的時間大約是幾我們到幾十我們(由于更多的內核和更復雜的架構,通常在服務器上更多)。
總體而言,CPU 實作似乎受記憶體限制,因為計算速度取決于專案大小(乍一看是成比例的)。話雖如此,如果假設結果是針對 1 個內核執行的代碼,吞吐量似乎很慢(我得到了 2.5 GiB/s,這對于最近的主流 PC 來說非常糟糕)。GPU 計算的效率也令人懷疑,因為時間與專案大小無關。這意味著計算當然不受記憶體限制,并且內核可能會被優化(檢查影像的布局,GPU首先進行連續訪問,然后應用一些展開以減少每個執行緒的內核開銷)。
我強烈建議您同時分析CPU 和 GPU 實作。對于 CPU 實作(對于大型矩陣),首先要做的是檢查是否使用了多個內核以及是否執行了 SIMD 指令。對于 CPU 和 GPU 實作,您應該檢查記憶體吞吐量。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/519708.html
標籤:C 表现opencv库达
上一篇:(-215:斷言失敗)總計>=0&&(深度==CV_32F||深度==CV_32S)在函式'cv::convexHull'中
