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