同上一篇,但是把所有 search range 平行化到每個 work-item,結論是沒有比較快…
Stereo Matching using OpenCL
繼上一篇的OpenCL版本,速度快了不少,但是顯卡會 freeze ….修改 TDR Level 讓 driver可以跑久一點
KeyPath : HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GraphicsDrivers KeyValue : TdrLevel ValueType : REG_DWORD ValueData : TdrLevelOff (0) - Detection disabled TdrLevelBugcheck (1) - Bug check on detected timeout, for example, no recovery. TdrLevelRecoverVGA (2) - Recover to VGA (not implemented). TdrLevelRecover (3) - Recover on timeout. This is the default value.
OpenCL Box Filtering
一個很 tricky 的點跟 CPU 計算不一樣,這邊如果把 main.cpp 呼叫 kernel 的 devBy 全部換成 devBx,在 thread 數不超過顯卡 core 負荷時(也就是一個 round 可以跑完 kernel ),結果是不會變的。可以嘗試在大圖需要多個 round 才能跑完 kernel 時就會出錯。
其實因為所有 thread 同步 inplace filtering 寫入關係,當寫入任一點時其他點的 source 已經不會需要再用到,所以不會有 propagate 的問題
讀寫檔案使用 OpenCV,減少 memory access 次數所以 x 和 y 方向 filtering 分開
OpenCL baby step using mingw
Headers & Document
Library
Nvidia
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\Win32\OpenCL.lib
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\x64\OpenCL.lib
Compile yourself
Binary
Included in AMD or Nvidia Driver
Note
- Nvidia only support OpenCL 1.2, AMD OpenCL 2.x
- No useful debugger like Nvidia Nsight. Use printf.
- Cross paltform intermediate language SPIR.
Example
OpenCV OpenCL example using UMat
重點在於 shader code 必須是固定的,如果 filter kernel 一直改變,估計在 runtime 重新 compile shader 的時間會成為瓶頸。
#include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/core/ocl.hpp> #include <time.h> using namespace cv; using namespace cv::ocl; int main(int argc, char** argv) { setUseOpenCL(1); printf("useCL %s\n", useOpenCL()?"true":"false"); Mat img = imread(argv[1]); UMat mImgSource, mImgSource2, mImgResult, mImgResult2, mImgResult3; img.copyTo(mImgSource); int ksize = 200; RNG rng; while (true) { clock_t t1 = clock(); add(mImgSource, UMat(mImgSource.size(), mImgSource.type(), Scalar( rng.uniform(0,50), rng.uniform(0,50), rng.uniform(0,50), rng.uniform(0,50) )), mImgSource2); boxFilter(mImgSource2, mImgResult, -1, Size(ksize, ksize)); boxFilter(mImgResult, mImgResult2, -1, Size(ksize, ksize)); resize(mImgResult2, mImgResult3, Size(), 0.5, 0.5); clock_t t2 = clock(); printf("%d %d\n", ksize, (int)(t2-t1)); imshow("img", mImgResult3); int key = waitKey(1); if (key > 0) break; } }