Weitere ähnliche Inhalte
Ähnlich wie 【関東GPGPU勉強会#4】GTX 1080でComputer Visionアルゴリズムを色々動かしてみる (20)
Kürzlich hochgeladen (12)
【関東GPGPU勉強会#4】GTX 1080でComputer Visionアルゴリズムを色々動かしてみる
- 8. サンプルコード(PtrStepSz)
// PtrStepSz型の変数を生成
cv::cudev::PtrStepSz<uchar> pSrc =
cv::cudev::PtrStepSz<uchar>(src.rows, src.cols * src.channels(), src.ptr<uchar>(), src.step);
const dim3 block(64, 2);
const dim3 grid(cv::cudev::divUp(dst.cols, block.x), cv::cudev::divUp(dst.rows, block.y));
// CUDAカーネルを呼び出す
kernel<<<grid, block>>>(pSrc); // カーネル引数としてPtrStepSz型の変数を渡す
CV_CUDEV_SAFE_CALL(cudaGetLastError());
CV_CUDEV_SAFE_CALL(cudaDeviceSynchronize());
カーネル呼び出し部
- 11. 【追記】サンプルコード(GpuMat)
cv::Mat src = cv::imread("lena.jpg", cv::IMREAD_GRAYSCALE);
cv::cuda::GpuMat d_src(src);
const dim3 block(64, 2);
const dim3 grid(cv::cudev::divUp(dst.cols, block.x), cv::cudev::divUp(dst.rows, block.y));
// CUDAカーネルを呼び出す
kernel<<<grid, block>>>(d_src); // カーネル引数としてGpuMatクラスのインスタンスを渡す
CV_CUDEV_SAFE_CALL(cudaGetLastError());
CV_CUDEV_SAFE_CALL(cudaDeviceSynchronize());
カーネル呼び出し部
- 16. CUDAカーネル実装
• 計測環境
– OS:Ubuntu 16.04 LTS(64bit)
– CUDA:CUDA Toolkit v8.0
– GCC:5.4.0
– CPU:Intel Xeon CPU E5-2623 v3 @ 3.00GHz
– メモリ:128GB
– GPU:GeForce GTX 1080
• Pascalアーキテクチャ
- 17. CUDAカーネル実装
• 計測環境(比較用)
– OS:Ubuntu 16.04 LTS(64bit)
– CUDA:CUDA Toolkit v8.0
– GCC:5.4.0
– CPU:Intel Xeon CPU E5-2623 v3 @ 3.00GHz
– メモリ:128GB
– GPU:GeForce GTX TITAN X
• Maxwellアーキテクチャ
- 18. CUDAカーネル実装
• 計測環境(比較用)
– OS:Windows 10 Pro(64bit)
– CUDA:CUDA Toolkit v7.5
– Visual Studio:Visual Studio 2013 Update5
– CPU:Intel Core i7-3930K @ 3.20GHz
– メモリ:32GB
– GPU:GeForce GTX 680
• Keplerアーキテクチャ
- 19. CUDAカーネル実装
GeForce
GTX 1080
GeForce
GTX Titan X
GeForce
GTX 680
アーキテクチャ Pascal Maxwell Kepler
CUDAコア数 2560基 3072基 1536基
定格クロック 1607MHz 1000MHz 1006MHz
ブーストクロック 1733MHz 1075MHz 1058MHz
メモリバス帯域幅 320GB/s 336.5GB/s 192.2GB/s
メモリ容量 8GB 12GB 2GB
動作クロックが大きく向上
メモリバス帯域幅はGeForce
Titan Xとほぼ同等
CUDAコア、メモリ容量がGTX 1080より多い
- 21. フィルタ処理(CPU実装)
ソースコード:https://github.com/atinfinity/imageFilteringGpu
for(int y = border_size; y < (dst.rows - border_size); y++){
uchar* pdst = dst.ptr<uchar>(y);
for(int x = border_size; x < (dst.cols - border_size); x++){
double sum = 0.0;
for(int yy = 0; yy < kernel.rows; yy++){
for(int xx = 0; xx < kernel.cols; xx++){
sum +=
(kernel.ptr<float>(yy)[xx] * src.ptr<uchar>(y+yy-border_size)[x+xx-border_size]);
}
}
pdst[x] = sum;
}
}
計算結果をストア
カーネル係数で重み付けして加算
- 24. フィルタ処理(__ldg関数利用)
ソースコード:https://github.com/atinfinity/imageFilteringGpu
if((y >= border_size) && y < (dst.rows-border_size)){
if((x >= border_size) && (x < (dst.cols-border_size))){
double sum = 0.0;
for(int yy = 0; yy < kernel.rows; yy++){
const uchar* psrc = src.ptr(y+yy-border_size) + (x-border_size);
const float* pkernel = kernel.ptr(yy);
for(int xx = 0; xx < kernel.cols; xx++){
sum += (__ldg(&pkernel[xx]) * __ldg(&psrc[xx]));
}
}
dst.ptr(y)[x] = sum;
}
}
__ldg関数を利用してRead-Onlyキャッシュ経由で読み込み
- 27. フィルタ処理
入力画像はw=800、h=640のグレースケール画像
単位はms
5回計測して平均をとる
GTX 1080
(Pascal)
GTX TITAN X
(Maxwell)
GTX680
(Kepler)
CPU実装(Naive) 57.521 44.158 39.255
OpenCV(Mat) 4.956 4.980 5.212
CUDA実装(Naive) 0.426 0.606 1.138
CUDA実装
(__ldg関数使用)
0.417 0.560 -
CUDA実装
(テクスチャメモリ使用)
0.531 0.618 1.168
CC3.0では__ldgが使えない・・・
- 29. テンプレートマッチング(CPU実装)
ソースコード:https://github.com/atinfinity/matchTemplateGpu
for(int y = 0; y < result.rows; y++){
float* presult = result.ptr<float>(y);
for(int x = 0; x < result.cols; x++){
long sum = 0;
for(int yy = 0; yy < templ.rows; yy++){
const uchar* pimg = img.ptr<uchar>(y + yy);
const uchar* ptempl = templ.ptr<uchar>(yy);
for(int xx = 0; xx < templ.cols; xx++){
int diff = pimg[x + xx] - ptempl[xx];
sum += (diff*diff);
}
}
presult[x] = sum;
}
}
画素値の差を計算
差の二乗和を加算
- 32. テンプレートマッチング(32x32)
入力画像はw=1920、h=1080のグレースケール画像
単位はms
5回計測して平均をとる
GTX 1080
(Pascal)
GTX TITAN X
(Maxwell)
GTX680
(Kepler)
CPU実装(Naive) 1696.070 1728.700 1107.840
OpenCV(Mat) 36.876 36.782 38.723
CUDA実装(Naive) 13.845 19.483 46.181
CUDA実装
(shared memory)
7.851 11.834 49.417
CUDA実装
(shared memory + __ldg)
6.931 9.641 -
CC3.0では__ldgが
使えない・・・
- 36. やり残したこと
• テンプレートマッチング(CUDA版)のチューニング
– 演算部分の最適化
– 【追記】long型を使用している箇所を見直す
– アルゴリズムそのものの見直し
• CUDA8から追加された機能を試す
– cudaMemPrefetchAsyncなるAPIが増えているのに気付いたけど使い方
がよくわからず・・・
• 【追記】Unified Memoryのprefetchに関するAPIのようです。
• OpenCVベンチマーク
– 詳細なプロファイリングおよび分析
• NPPベンチマーク
– CUDA8のNPPはPascal世代にも最適化されている?