セクションをパラレルで実行した後、メインスレッドにマージしてから、セクションをパラレルに戻したいとします。子供時代のゲームの赤い光の緑色のライトに似ています。C++フォーク結合並列処理ブロッキング
私は何をしようとしているのかの例を挙げました。条件変数を使ってスレッドをブロックしますが、それらをすべて並列に開始したいが、最後にブロックするそれらは連続してプリントアウトすることができます。 * =操作は、数秒に及ぶはるかに大きな操作になる可能性があります。スレッドを再利用することも重要です。タスクキューを使用するのは重すぎるかもしれません。
私は多忙なループでこの問題を解決する方法を知っているので、単純なビジーループではない何らかのブロッキング構造を使用する必要があります。英語で
:
- スレッド1は、
- スレッド(お互いをブロックせずに)すべてのスレッドを起動する1信号
- スレッド2-11工程その専用記憶
- をブロックされている10個のスレッドを作成しますスレッド1は2-11が完了するまで待っています(ここでカウントするにはアトミックを使用できます)
- スレッド2-11が完了し、必要に応じて状態を確認するためにそれぞれ1に通知することができます の
- スレッド1つのチェックの条件と2
例コード(ナイーブがcplusplus.com上の例から採用)から連続配列
// condition_variable example
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <atomic>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
std::atomic<int> count(0);
bool end = false;
int a[10];
void doublea (int id) {
while(!end) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck);
a[id] *= 2;
count.fetch_add(1);
}
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();
ready = false; // Naive
while (count.load() < 10) sleep(1);
for(int i = 0; i < 10; i++) {
std::cout << a[i] << std::endl;
}
ready = true;
cv.notify_all();
ready = false;
while (count.load() < 10) sleep(1);
for(int i = 0; i < 10; i++) {
std::cout << a[i] << std::endl;
}
end = true;
cv.notify_all();
}
int main() {
std::thread threads[10];
// spawn 10 threads:
for (int i=0; i<10; ++i) {
a[i] = 0;
threads[i] = std::thread(doublea,i);
}
std::cout << "10 threads ready to race...\n";
go(); // go!
return 0;
}
を
なぜ「カウント」アトミックですか?なぜ一方の側で条件変数を使用し、別の側でビジーなスリープを使用するのですか? – UmNyobe
@UmNyobe私は明らかにビジーな睡眠を使いたくありません。スレッドは通知を待つ間にスリープ状態になるはずです。 あなたの疑問にお答えしますと、カウントは、一度に複数のスレッドで増加する可能性があるため、アトミックです。増分は2段階のプロセスです。 –