1

私はこれを行うための最良の方法を見つけようとしていますが、私がやろうとしていることを正確に理解するのに少し行き詰まっているので、それが何であるか、私が何であるかを説明しますやりたいと思っているのですが、行き詰まっています。

私は単一の配列(実際には画像)を持つプログラムに取り組んでいます。このプログラムでは、フレームごとに多数のオブジェクトを画像配列に配置できます。各オブジェクトは、他のすべてのオブジェクトから完全に独立しています。唯一の依存関係は出力であり、理論的には、これらのオブジェクトのうち2つを配列の同じ場所に配置することが可能です。より多くのオブジェクトを配置できるように、画像上にオブジェクトを配置する効率を高めようとしています。それをするために、私は問題をスレッド化したいと思っています。

スレッド化に向けて私が取った最初のステップは、単にアレイをミューテックスで保護することです。配列にオブジェクトを配置するすべての操作は同じ関数を呼び出すので、ミューテックスロックを1か所に配置するだけで済みます。これまでのところ、機能していますが、私が期待するような改善は見られません。これは、ほとんどの場合、制限要因がイメージ書き込みステートメントであるためであると私は仮定しています。

次に行う必要があると考えているのは、書き込み先の複数のイメージバッファーを用意し、すべての操作が完了したらそれらを結合することです。あいまいさは問題ではありません。必要なのは、ピクセル数を単純に足し合わせることだけです。しかし、これを行うためにどのメカニズムを使用する必要があるかを理解するのに苦労しています。セマフォを見てきましたが、バッファの数が制限されることはわかりますが、2つ以上のプログラムが同時に同じバッファに書き込もうとして、不正確になる可能性がある状況を想像できます。

新しい非標準ライブラリを含まないソリューションが必要です。私は解決策を構築することをいとわないが、私は現在暗闇の中でたださまよっているので、正しい方向へのいくつかの指針を非常に高く評価するだろう...

これを視覚化するために、たとえば、画像配列のさまざまな場所にボールを配置するように指示されたと想像してください。与えられた明るさ、場所、サイズで、フレームごとにボールを配置するように言われています。ボールの正確な位置は、前のフレームの物理特性によって異なります。すべてのボールは、可能な限り迅速に最終的な画像配列に配置する必要があります。この例では、2つのボールが重なり合っている場合、明るさを単純に足し合わせることができるため、一方が他方をブロックしているかどうかを判断する必要はありません。また、GPUカードを使用しないでください;-)

疑似コードは次のようになります:(場所、明るさ、サイズに論理オブジェクトが指定されていると仮定します)。また、isValidPointは、円の位置と半径を指定して、点が円上にあるかどうかを単純に検出するとします。

global output_array[x_arrLimit*y_arrLimit)
void update_ball(int ball_num)
{
  calc_ball_location(ball_num, *location, *brightness, *size); // location, brightness, size all set inside function
  place_ball(location,brightness,size)
}

void place_ball(location,brighness,size)
{
  get_bounds(location,size,*xlims,*ylims)
  for (int x=xlims.min;x<xlims.max;y++)
  {
    for (int y=ylims.min;y<ylims.max;y++)
    {
      if (isValidPoint(location,size,x,y))
      {
        output_array(x,y)+=brightness;
      }
    }
  }
}
4

2 に答える 2

4

現在の設計でスピードアップが見られない理由は、バッファ全体に単一のミューテックスを使用すると、すべてのオブジェクトをとにかく連続して追加する必要があるため、スレッド化に煩わされない可能性があるためです(重要な処理がない限り)何を追加するかを決定するために行われていますが、そうではないようです)。「オブジェクトをバッファに追加する」ために必要なものに応じて(スキャンラインアルゴリズム、フラッドフィルなどを使用しますか)、行または行の範囲ごとに1つのミューテックスを使用するか、画像を次のように分割することを検討してください。リージョンごとに1つのミューテックスを持つ長方形のタイルなど。これにより、同じ領域を更新しようとしない限り、複数のスレッドを同時にイメージに追加できます。

于 2012-07-05T15:45:19.150 に答える
0

OK、あるオブジェクトに画像メンバーがあります。間違いなく複雑なコードを追加して、他の画像/オブジェクトを追加します。何でもそれを操作します。関与する可能性のある他のすべてのオブジェクトに集約し、実行する操作をスレッドに指示するコマンドenunと、完了時に呼び出す「OnCompletion」イベントを追加します。

生産者/消費者キューの最後にぶら下がっているスレッドのプールにキューに入れます。一部のスレッドは*objectを取得し、画像/セットに対して操作を実行してから、イベントを呼び出します(完成した* objectをパラメーターとして渡します)。イベントでは、アプリのニーズに応じて、好きなことを行うことができます。たぶん、処理された画像を(スレッドセーフ!!)、ベクター、または他のコンテナーに追加するか、他のスレッドにキューに入れるでしょう-何でも。

画像の処理順序を維持する必要がある場合(ビデオストリームなど)、プールに送信される各オブジェクトに増分シーケンス番号を追加して、「OnComplete」ハンドラーが「後の」画像をキューに入れることができるようにすることができます。以前のものがすべて入ってくるまで。

2つのスレッドが同じ画像で機能することはないため、処理中にロックする必要はありません。必要な(場合によっては)唯一のロックはキュー内のロックであり、オブジェクトポインタをキューにプッシュ/キューからポップするのにかかる時間だけロックします-競合は非常にまれです。

于 2012-07-05T15:46:41.647 に答える