0

申し訳ありませんが、IntelのTBBを入手できていないようですが、サポートされているようですが、タスクの観点から並列処理を考えることに慣れていないので、使い方に頭を悩ませることはできません。スレッドとして。

私の現在のワークロードには、処理を継続するために作業をキューに送信するジョブがあります(再帰を考えてみてください。ただし、それ自体を呼び出す代わりに、作業をキューに送信します)。これをJavaで機能させる方法は、並行キュー(非ブロッキングキュー)と、キューを機能させたスレッドプールエグゼキューターを作成し、それに作業を送り返すことでした。しかし今、私はc ++で同様のことをしようとしていますが、TBBはプールを作成できることがわかりましたが、そのアプローチは大きく異なります(Javaスレッドはキューで動作している限り動作し続けるようですが、TBBはタスクを中断しているようです最初に)。

これが私が行うことの簡単なJavaの例です(この前に、必要なスレッド数などを設定しました):

static class DoWork implements Callable<Void> {
    // queue with contexts to process
    private Queue<int> contexts;

    DoWork(Context request) {
        contexts = new ArrayDeque<int>();
        contexts.add(request);
    }

    public Void call() {
        while(!contexts.isEmpty()) {
            //do work 
            contexts.add(new int(data)); //if needs to be send back to the queue to do more work
        }
    }
}

TBBでこれを行うことは確かに可能ですが、送信した時点で作業が中断されているように見えるため、どうすればよいかわかりません。したがって、キューに2つのアイテムがある場合、2つのスレッドしか起動しない可能性がありますが、作業が増えるにつれて成長しません(8つのコアがある場合でも)。

誰かが私のタスクを達成する方法を理解するのを手伝ってくれますか?また、Javaのスレッド環境を使用することから来るTBBについて考えるより良い方法を提案できますか(また、私はTBBに忠誠を誓っていないので、もっと簡単/より良いものがあれば、私は喜んで学びますそれ。積極的に開発されていないように見えるので、私はc ++スレッドプールが好きではありません)?

4

2 に答える 2

1

並列処理用のアイテムのキューを持つことに基づくアプローチでは、各スレッドがキューから1つのアイテムをポップして続行します(そして、ある時点でキューの最後に新しいアイテムを追加する可能性があります)。アプリケーション。キューは単一の同期ポイントになり、スレッドは処理する次のアイテムにアクセスするために待機する必要があります。実際には、このアプローチは、タスク(各アイテムの処理ジョブ)が非常に大きく、完了するまでに時間がかかる場合に機能します。これにより、(ほとんどの)スレッドが同時に終了してキューに到達する場合とは対照的に、キューの競合が少なくなります。次に処理するアイテムのために。

ある程度再利用可能なコードを記述している場合、タスクが十分に大きいか、サイズ(実行時間)が異なることを保証することはできません。

アプリケーションがスケーリングすると仮定します。つまり、キュー内のかなりの数のアイテム(スレッドの数よりはるかに多い)から開始し、スレッドが処理を実行している間、最後に十分なタスクを追加するため、アプリケーションが終了するまで全員。

その場合は、互換性を保つために、アイテムの2つのスレッドセーフなベクトル(たとえば、TBBのconcurrent_vectors)を保持することをお勧めします。1つのベクトル(アイテムの初期セット)から始めて、アイテムの初期ベクトルに対してparallel_forを実行するタスク(TBBリファレンスマニュアルの第12章のどこかに説明されていると思います)をenque()します。最初のバッチが処理されている間、新しいアイテムを2番目のconcurrent_vectorにプッシュバックし、最初のバッチが完了したら、2番目のベクトルに対してparallel_forを使用してタスクをenque()し、新しいアイテムを最初のベクトルにプッシュし始めます。 。すべてのスレッドをビジー状態に保つのに十分な作業が残っている間に、2つではなく3つのベクトルを使用し、それらの間を徐々に移動することで、アイテムの並列処理をより適切にオーバーラップさせることができます。

于 2012-05-15T21:00:06.167 に答える
1

あなたがやろうとしているのは、まさにTBBparallel_doが設計されているようなものです。によって呼び出された「body」にparallel_doは「feeder」引数が渡されます。この引数はfeeder.add(...some new task...)、タスクの処理中に実行して、現在のタスクが完了する前に実行する新しいタスクを作成できますparallel_do

于 2012-05-15T23:02:47.360 に答える