2015-12-08 11 views
5

私はアプリケーションを開発していますが、主な目的はフレームグラバーから画像を取得し、処理してGUI上に画像を表示することです。 フレームグラバーはPCIeに接続されています。私はフレームグラバーSDKを使用しています。 イメージストリームは10〜100画像/秒でかなり遅いです 私のコードについてのアドバイスとそれを最適化する方法はこちらです。 まず、Qthreadから継承したクラスのrun()関数があります。 イメージを取得し、バッファqueuecv :: Mat>に配置します。 - 1は、ブロッキング機能へのイメージのおかげを取得したスレッド :...マルチスレッドのアドバイス

void ImageProcessing::run(){ 
while(_runningThread){ 
if (_ctrl->getMutexIn()->tryLock()){ 
    while(!_ctrl->getBufferIn()->empty()){ 
     _ctrl->getBufferIn()->front().convertTo(tempConvert, CV_32F); 
     _bufferLocalIn.push(tempConvert); 
     _ctrl->getBufferIn()->pop(); 
    } 
    _ctrl->getMutexIn()->unlock(); 
} 

// Do some processing and put image and a buffer for GUI 
} 
} 

そうに

void ImageIn::run(){ 
     _cam->allocMemory(); 
     _cam->startAquisition(); 
     _runningThread = true; 

     while(_runningThread) 
     { 
      Mat image(_cam.getSizeX(), _cam.getSizeY(), CV_16U, _cam->getImageDMA0()); 

      _ctrl->getMutexIn()->lock(); // Lock BufferIn 
      _ctrl->getBufferIn()->push(image); // store Image in BufferIn 
      _ctrl->getMutexIn()->unlock(); // Unlock bufferIn 
     } 

} 

画像はバッファに格納され、その後、処理スレッドがいくつかの作業を行う、私はいくつかの質問を持っていますCPU消費量は少なくなりますが、スレッド2は継続的に実行され、多くのCPUを消費します。これを修正するために何ができるのでしょうか? - それをコーディングするのは正しい方法ですか?


だから私はそれを試してみました:

QThread* thread = new QThread; 
ImageWriter* worker = new ImageWriter(); 
worker->moveToThread(thread); 

QTimer* timer = new QTimer(); 
int msec = 100; 
timer->setInterval(msec); 

QObject::connect(thread, SIGNAL(started()), worker, SLOT(process())); 
QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit())); 
QObject::connect(timer, SIGNAL(timeout()), thread, SLOT(start())); 
timer->start(); 

が、それは大丈夫ですか?

+1

条件待ちについて読んでください。最初のスレッドが処理する新しいイメージを取得するまで、2番目のスレッドを待機させることができます。その後、入力イメージのリストが空になり、条件付き待機に戻るまで処理を続けます。私は1つの質問を持っている:ブロック機能は、あなたのフレームグラバーSDKから取得する前に新しい画像が利用可能になるまで待つ? – Micka

+0

ありがとう、私は条件付き待ちについて読んで、それを試みます。 はい、_cam-> getImageDMA0()関数はフレームグラバーSDKからブロック機能を呼び出します。このブロッキング関数は新しいイメージを待ちます。 –

答えて

2

Qtはイベント駆動型フレームワークであるため、各スレッドにはイベントを受け取り、それらを受け取るためにさまざまなオブジェクトに送信するイベントキューがあります。

スレッド内のコードのいずれかのセクションでは、基本的にしばらく(1)ループを持っている場合は、イベントの伝播が発生することができない、これはあなたが

でイベント処理を飢え
while(_runningThread) 

で両方のスレッドでやっていることです無限ループは過剰なCPU消費の原因です。

Qtに無限ループ内でQApplication::processEventsを呼び出してイベントを処理させることは可能ですが、これは理想的ではありません。

より良い方法は、処理をタイムスライスしてQTimerとし、イベントの伝播を自然に起こさせることです。これは、処理状態を保存してからイベントループに戻る前に、処理がどれほど長くなるかを決定する必要があります。タイマーのティックはあなたの処理機能を呼び出し、状態を復元してレジュームすることができます。

このメソッドは、QThread自体から直接継承するのではなく、QThreadに移動するQObjectから派生した処理クラスを作成する方が簡単です。 How to Really Truly Use QThreadに関する素晴らしい記事があり、これを行う方法のテンプレートとして使用できます。

最後に、QThreadに複数のQObjectが実行されていることを考慮してください。一般的なルールとして、スレッド数が使用可能なプロセッサコアの数を超えた場合は、メリットはありません。

ターゲットマシンがクアッドコアであることが分かっている場合、3つの余分なQThread(メインを含む合計4つ)を作成し、複数の処理オブジェクトを作成し、それらを異なるスレッドに移動して最適な処理を提供できます。

+0

この解決策も試してみます。 QwaitConditionはmoveToThreadを使用するよりも優れていますか? –

+1

これは2つの全く異なるものを比較しています。ドキュメントが[QWaitCondition](http://doc.qt.io/qt-5/qwaitcondition.html#details)の状態である* QWaitConditionクラスはスレッド*を同期させるための条件変数を提供しますが、moveToThreadはオブジェクトをそのスレッド上でその処理が行われるようにします。 – TheDarkKnight

+0

私は見ています。 イメージレートが処理には速すぎる場合は、(スレッドに移動した)あまりにも多くの処理関数を呼び出すと、これは危険ですか? –