1. 程式人生 > >opencv 平行計算函式 parallel_for_的使用

opencv 平行計算函式 parallel_for_的使用

opencv 平行計算函式 parallel_for_
前面的話
在使用opencv的過程中,對圖片的處理計算量還是很大的,所以在實施執行的程式中如何高效的計算會節省很多時間。現有的方法有很多,如OpenMp,TBB,OpenCL,當然還有Nvidia的CUDA。 
但是OpenMP在windows的VS上支援的很好,設定簡單,效果也還不錯,但是在Linux雖然也支援, 
但是我用Cmake時,感覺效果並不明顯。TBB和OpenCL沒有直接用過。CUDA是個好東西,但是並 
不太適合毫秒級別的程式執行,單一張圖片在cpu和gpu之間的傳輸時間就已經達到300ms(我用 
的是opencv的cuda庫函式);在TX2上直接對cuda進行程式設計,資料的傳輸也是在50ms(不包含初始化)以上,根本不能拿來做實時的運算。所以如何在cpu上更加高效的計算變得尤為重要。偶然間發現了opencv的平行計算函式parallel_for_,它整合了上述的多個元件

在OpenCV 3.2中,以下並行框架按照以下順序提供: 
1. 英特爾執行緒構建塊(第三方庫,應顯式啟用),如TBB 
2. C =並行C / C ++程式語言擴充套件(第三方庫,應明確啟用) 
3. OpenMP(整合到編譯器,應該被顯式啟用) 
4. APPLE GCD(系統範圍廣,自動使用(僅限APPLE)) 
5. Windows RT併發(系統範圍,自動使用(僅Windows RT)) 
6. Windows併發(執行時的一部分,自動使用(僅限Windows) - MSVC ++> = 10)) 
7. Pthreads(如果有的話) 
您可以看到,OpenCV庫中可以使用多個並行框架。一些並行庫是第三方庫,必須在CMake(例如TBB,C =)中進行顯式構建和啟用,其他可以自動與平臺(例如APPLE GCD)一起使用,但是您應該可以使用這些庫來訪問並行框架直接或通過啟用CMake中的選項並重建庫。第二個(弱)前提條件與要實現的任務更相關,因為並不是所有的計算都是合適的/可以被平行地執行。為了保持簡單,可以分解成多個基本操作而沒有記憶體依賴性(無可能的競爭條件)的任務很容易並行化。計算機視覺處理通常易於並行化,因為大多數時間一個畫素的處理不依賴於其他畫素的狀態。

OpenCV在編譯時需要使能OpenMV,TBB等

程式碼簡單的貼出來,這裡記錄一下:在c++11中,可以不必定一個類去繼承平行計算迴圈體類(ParallelLoopBody),可以直接使用,如main中所示在c++11之下的就需要繼承一下該平行計算迴圈體了,繼承的原因個人認為是通過複寫虛擬函式,實現平行計算


#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>

using namespace std;
using namespace cv;

class Parallel_My : public ParallelLoopBody
{
public:
    Parallel_My (Mat &img, const float x1, const float y1, const float scaleX, const float scaleY)
        : m_img(img), m_x1(x1), m_y1(y1), m_scaleX(scaleX), m_scaleY(scaleY)
    {
    }

    virtual void operator ()(const Range& range) const
    {
        for (int r = range.start; r < range.end; r++) //process of for loop
        {
          /***

          ***/
        }
    }

    Parallel_My& operator=(const Parallel_My &) {
        return *this;
    };

private:
    Mat &m_img;
    float m_x1;
    float m_y1;
    float m_scaleX;
    float m_scaleY;
};

int main()
{
    //! [mandelbrot-transformation]
    Mat Img(4800, 5400, CV_8U);
    float x1 = -2.1f, x2 = 0.6f;
    float y1 = -1.2f, y2 = 1.2f;
    float scaleX = mandelbrotImg.cols / (x2 - x1);
    float scaleY = mandelbrotImg.rows / (y2 - y1);

    #ifdef CV_CXX11 //method one
    parallel_for_(Range(0, Img.rows*tImg.cols), [&](const Range& range)
    {
        for (int r = range.start; r < range.end; r++) //這是需要平行計算的for迴圈
        {

        }
    });

    #else   //method two
    Parallel_My parallel_my0(Img, x1, y1, scaleX, scaleY);
    parallel_for_(Range(0, Img.rows*Img.cols), parallel_my0);
    #endif
}

可以參考這裡: 
1.使用parallel_for_優化程式碼 
2. 官網document
轉:https://blog.csdn.net/qq_31806429/article/details/79242399