2015-07-20 81 views
2

GPU:GeForce GTX 750OpenCV的GPU模糊緩慢

CPU:Intel i5-4440 3.10 GHz

下面是一個簡單的C++代碼,我跑。

#include <iostream> 
    #include "opencv2/highgui/highgui.hpp" 
    #include "opencv2\gpu\gpu.hpp" 

    int main(int argc, char** argv) { 
     cv::Mat img0 = cv::imread("IMG_0984.jpg", CV_LOAD_IMAGE_GRAYSCALE); // Size 3264 x 2448 
     cv::Mat img0Blurred; 

     cv::gpu::GpuMat gpuImg0(img0); 
     cv::gpu::GpuMat gpuImage0Blurred; 

     int64 tickCount; 

     for (int i = 0; i < 5; i++) 
     { 
      tickCount = cv::getTickCount(); 
      cv::blur(img0, img0Blurred, cv::Size(7, 7)); 
      std::cout << "CPU Blur " << (cv::getTickCount() - tickCount)/cv::getTickFrequency() << std::endl; 

      tickCount = cv::getTickCount(); 
      cv::gpu::blur(gpuImg0, gpuImage0Blurred, cv::Size(7, 7)); 
      std::cout << "GPU Blur " << (cv::getTickCount() - tickCount)/cv::getTickFrequency() << std::endl; 

     } 

     cv::gpu::DeviceInfo deviceInfo; 
     std::cout << "Device Info: "<< deviceInfo.name() << std::endl; 

     std::cin.get(); 

     return 0; 
    } 

而作爲一個結果,我通常得到的東西是這樣的:

CPU Blur: 0.01 
GPU Blur: 1.7 
CPU Blur: 0.009 
GPU Blur: 0.012 
CPU Blur: 0.009 
GPU Blur: 0.013 
CPU Blur: 0.01 
GPU Blur: 0.012 
CPU Blur: 0.009 
GPU Blur: 0.013 

Device Info: GeForce GTX 750 

所以在GPU第一操作需要一定的時間。

但是,GPU的其他部分怎麼樣呢?

爲什麼GPU不提供任何加速度。畢竟這是一個很大的圖像(3264 x 2448)。並行任務很好,不是嗎?

我的CPU很好,還是我的GPU不好? 或者這是組件之間的某種通信問題?

+0

[相關](http://stackoverflow.com/questions/15035907/why-cvgpugaussianblur-is-slower-than-cvgaussianblur) –

+0

你使用opencv與IPP? – Micka

+0

不,我沒有..... – ancajic

回答

6

你的第一個gpu測量結果與其他測量結果很不相同,我也經歷過同樣的事情。第一次調用opencv內核(erode/dilate/etc ...)比其他的更長。 在一個應用程序中,當我們初始化GPU內存時,我們首先調用了cv :: gpu :: XX以避免產生這種噪聲。

我也看到cv :: gpu在沒有cv :: gpu :: Stream參數的每次調用之後使用cudaDeviceSynchronize。這可能會很長,並導致您噪音的測量。 然後opencv可能會爲臨時緩衝區分配內存以存儲用於模糊圖像的內核。

我沒有在你的例子中看到gpuImage0Blurred的分配,你能確定你的目標圖像在循環外正確分配,否則你也會測量這個矩陣的分配時間。

使用nvvp可以爲您提供關於應用程序運行時發生的事情的線索,以刪除不必要的操作。

編輯:

#include <iostream> 
#include "opencv2/highgui/highgui.hpp" 
#include "opencv2\gpu\gpu.hpp" 


int main(int argc, char** argv) { 
    cv::Mat img0 = cv::imread("IMG_0984.jpg", CV_LOAD_IMAGE_GRAYSCALE); // Size 3264 x 2448 
    cv::Mat img0Blurred; 


    cv::gpu::GpuMat gpuImg0; 
    cv::gpu::Stream stream; 
    stream.enqueueUpload(img0, gpuImg0); 
    stream.waitForCompletion(); 

    // allocates the matrix outside the loop 
    cv::gpu::GpuMat gpuImage0Blurred(gpuImg0.size(), gpuImg0.type()); 

    int64 tickCount; 

    for (int i = 0; i < 5; i++) 
    { 
     tickCount = cv::getTickCount(); 
     cv::blur(img0, img0Blurred, cv::Size(7, 7)); 
     std::cout << "CPU Blur " << (cv::getTickCount() - tickCount)/cv::getTickFrequency() << std::endl; 

     tickCount = cv::getTickCount(); 
     cv::gpu::blur(gpuImg0, gpuImage0Blurred, cv::Size(7, 7), cv::Point(-1, -1), stream); 
     // ensure operations are finished before measuring time spent doing operations 
     stream.WaitCompletion(); 
     std::cout << "GPU Blur " << (cv::getTickCount() - tickCount)/cv::getTickFrequency() << std::endl; 

    } 

    std::cin.get(); 

    return 0; 
} 

是的,事實證明waitForCompletion使所有的差異。 我收到相同的值就像開頭:

CPU Blur: 0.01 
GPU Blur: 1.7 
CPU Blur: 0.009 
GPU Blur: 0.012 
CPU Blur: 0.009 
GPU Blur: 0.013 
CPU Blur: 0.01 
GPU Blur: 0.012 
CPU Blur: 0.009 
GPU Blur: 0.013 
+0

這很酷,但現在我面臨着一個不同的問題。我只是將模糊作爲一個簡單的基準。我其實想要並行化特徵檢測。所以,這是在我的下一個問題:http://stackoverflow.com/questions/31536735/fast-gpu-feature-detection-slow – ancajic

+0

你仍然沒有分配你的輸出矩陣的循環之外,只是聲明變量, CV :: gpu :: GpuMat gpuImage0Blurred(gpuImg0.size(),gpuImg0。type()); 將在設備上進行分配,否則您的第一個模糊調用將分配此緩衝器 – X3liF

+1

我已更新編輯,在測量時間之前在流上添加同步,因爲您只會測量添加訂單所花費的時間流,而不是花費的計算時間。 – X3liF