私はOpenCVとTBBで作業することを学んでいます。私はマルチコアCPUを持っているので、私のプログラムのmuticpuサポートを作成したいので、イメージのマルチプロセッシングを使う方法を学ぶ必要があります。OpenCVマルチコア画像処理用TBBタスクスケジューラの作成方法は? C++
私は彼らがfabonacci番号を使用して記事Intel®Technologyジャーナル紙の「インテル®スレッディング・ビルディング・ブロックでスケーラブルなマルチコアソフトウェアの基礎」(あなたがここhttp://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.71.8289&rep=rep1&type=pdf PDFでそれを見つけることができます)
を読んだことがありますマルチプロセッシングの例としての計算。 TBBパッケージのTBBの例にも同様のfabonacci番号の例があります(ParallelTaskFibを参照)。唯一の問題は計算が簡単でCPUがそれほど負担がかからないことです。少数でマルチタスキングを実行する場合、CutOffを低くするとオーバーヘッドが大きくなり効率的ではありません。ですから、TBBで作業することを学ぶためには、画像処理のより実用的な例が必要です。私の考えでは、TBBタスクスケジューラを使いたいと思っています。私はクラスFibTaskで始まり、名前を変更したParallelFib関数を使用して、引数ベクトルを画像ベクトルで動作するように変更しました。それがどのように設計されたかの基本原則はそのまま残すべきです。ファボナッチの例には、aとbという2つの子だけが含まれています。今問題は、私が1つの関数matTask(元々 '実行'と呼ばれていた)で2人以上の子供を使用できるかどうかわかりません。だから私は、より多くのポインタとより多くのポインタを追加しようとspawn_and_wait_for_all()を待って...この段階では、私はこのデザインが正しいか、パフォーマンスの問題がないかどうかを尋ねたいので、画像処理関数を作成しませんでした。それは終了していません。あなたの提案が私のコンセプトの間違いを修正するのを待つつもりです。
私の基本的な考えは、lena.jpgにガウスぼかしのようなフィルタ機能を使用することです。まず、いくつかのスレッドを渡します。私は8コアしかないので最大8スレッドしか渡すことができません。私はlenaイメージを同じサイズの8つのストリップに分割し、ピクセルをベクトル(8つの基本ベクトル)にコピーすることを計画しています。次に、それらをbluredする必要があります。次に、8つのセクションのマージンに重なる次の7-8イメージを作成する必要があるということです。私はbluringアクションだけを繰り返したい。最後に、画像の残りの部分(source_image.rows()/ 8から残っている部分)にもう1つのパスが必要です。
私が解決する必要がある主な事柄(私はやり方がわからない)は、無限ループを止めることです。 1)コーピングと2)ブラーリング3)クロッピング4)貼り付けのために、異なるクラスと異なるメソッドを作成する必要がありますか?または、1回の呼び出しですべてを渡すことができますか?これは、コードが同じことをしたので、fabonnaciの数字の例との違いですが、私はより多くのことをする必要があります...それでは、ロジック、関数の名前付け方法、
簡単な解決策は、同じサイズの8つのストリップを使用することです。次に7-8のオーバーレイ領域を使用します。
コードではエラーは表示されませんが、時間的な概念なので正しい結果を返すとは限りません。
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include "tbb/task.h"
#include "tbb/task_scheduler_init.h"
#define CutOff 12
using namespace cv;
void SerialAction(int n){};
/**
**/
class matTask: public tbb::task {
public:
int n;
const int offset;
std::vector<cv::Mat> main_layers;
std::vector<cv::Mat> overlay_layers;
matTask(std::vector<cv::Mat>main_layers_, std::vector<cv::Mat> overlay_layers_, int n_, const int offset_) :
main_layers(main_layers_),
overlay_layers(overlay_layers_),
n(n_), offset(offset_)
{}
task* execute() {
if(n<CutOff) {
SerialAction(n);
}
else {
// Main layers - copy regions
matTask& a = *new(allocate_child())
matTask(main_layers,overlay_layers,n,0);
matTask& b = *new(allocate_child())
matTask(main_layers,overlay_layers,n-1,0);
matTask& c = *new(allocate_child())
matTask(main_layers,overlay_layers,n-2,0);
matTask& d = *new(allocate_child())
matTask(main_layers,overlay_layers,n-3,0);
matTask& e = *new(allocate_child())
matTask(main_layers,overlay_layers,n-4,0);
matTask& f = *new(allocate_child())
matTask(main_layers,overlay_layers,n-5,0);
matTask& g = *new(allocate_child())
matTask(main_layers,overlay_layers,n-6,0);
matTask& h = *new(allocate_child())
matTask(main_layers,overlay_layers,n-7,0);
spawn_and_wait_for_all(a);
spawn_and_wait_for_all(b);
spawn_and_wait_for_all(c);
spawn_and_wait_for_all(d);
spawn_and_wait_for_all(e);
spawn_and_wait_for_all(f);
spawn_and_wait_for_all(g);
spawn_and_wait_for_all(h);
// In the case of effect:
// Overlay layers
matTask& ab = *new(allocate_child())
matTask(main_layers,overlay_layers,n,offset);
matTask& bc = *new(allocate_child())
matTask(main_layers,overlay_layers,n-1,offset);
matTask& cd = *new(allocate_child())
matTask(main_layers,overlay_layers,n-2,offset);
matTask& de = *new(allocate_child())
matTask(main_layers,overlay_layers,n-2,offset);
matTask& ef = *new(allocate_child())
matTask(main_layers,overlay_layers,n-2,offset);
matTask& gh = *new(allocate_child())
matTask(main_layers,overlay_layers,n-2,offset);
// ... + crop .. depends on size of kernel
set_ref_count(8);
spawn(b);
spawn_and_wait_for_all(a);
}
return NULL;
}
};
void ParallelAction(std::vector<cv::Mat> main, std::vector<cv::Mat> overlays, int n, const int offset) {
matTask& a = *new(tbb::task::allocate_root())
matTask(main, overlays, n,offset);
tbb::task::spawn_root_and_wait(a);
}
int main(int argc, char** argv)
{
int threads = 8;
std::vector<cv::Mat> main_layers;
std::vector<cv::Mat> overlays;
cv:: Mat sourceImg;
sourceImg = imread("../../data/lena.jpg");
if (sourceImg.empty())
return -1;
const int offset = (int) sourceImg.rows/threads;
cv::setNumThreads(0);
ParallelAction(main_layers, overlays, threads, offset);
// GaussianBlur(src, dst, Size(3,3), 0, 0, BORDER_DEFAULT);
return 0;
}
編集:アントンの答えに 反応。 operator()オーバーロードを使用する場合、operator()が正確に適用されるのはいつですか?また、ApplyFooにいくつかのメソッドを追加することは可能ですか? WWは()がオーバーロードされていると、1つの方法しかないようです。
void Foo(float a){};
class ApplyFoo {
float *const my_a;
public:
void operator()(const tbb::blocked_range<size_t>& r) const {
float *a = my_a;
for(size_t i=r.begin(); i!=r.end(); ++i)
Foo(a[i]);
}
ApplyFoo(float a[]) :
my_a(a) // initiate my_a
{}
};
OpenCVの 'ParallelLoopBody'をサブクラス化し、利用可能な場合はtbbを使用する' cv:parallel_for_'を使用することができます。グレースケール変換の例はこちら[http://stackoverflow.com/a/34315148/5008845]で見ることができます。おそらくあなたのニーズに適応することができます – Miki
ありがとう、私は変更を試してみます。今私はTBBでそれをやろうとしています。 –