異なるパラメータで同じ関数を何度も呼び出すスレッドのベクトルを再利用したいと思います。 (原子パラメータを除いて)記述がないので、ミューテックスの必要はありません。このアイデアを表現するために、ベクトルの最大値を見つける並列化されたコードの基本的な例を作成しました。明らかにベクトルの最大値を見つけるより良い方法がありますが、説明のために、私が書いている実際のコードの詳細を知ることを避けるために、私はこのばかげた例を考えています。C++同じ関数を呼び出すスレッドのベクトルを再利用する
コードベクトルは番号Kを(K上限で初期化されている)を含むかどうかをチェックする機能pFindを呼び出すことにより、ベクトルの最大数を見出します。実行されている場合は実行が停止し、そうでない場合はkが1つ減らされ、プロセスが繰り返されます。
コードでは、ベクトル内にkの検索を並列化するスレッドのベクトルを生成します。問題は、すべての値がkの場合、スレッドのベクトルが再生成され、新しいスレッドが結合されるたびに発生するということです。 スレッドのベクトルを生成し、それらを結合するたびに、避けたいオーバーヘッドが発生します。
スレッドのベクトル(プール)を1回生成して新しい実行に再利用する方法があるのだろうかと思います。他のどのスピードアップのヒントも高く評価されます。
void pFind(
vector<int>& a,
int n,
std::atomic<bool>& flag,
int k,
int numTh,
int val
) {
int i = k;
while (i < n) {
if (a[i] == val) {
flag = true;
break;
} else
i += numTh;
}
}
int main() {
std::atomic<bool> flag;
flag = false;
int numTh = 8;
int val = 1000;
int pos = 0;
while (!flag) {
vector<thread>threads;
for (int i = 0; i < numTh; i++){
thread th(&pFind, std::ref(a), size, std::ref(flag), i, numTh, val);
threads.push_back(std::move(th));
}
for (thread& th : threads)
th.join();
if (flag)
break;
val--;
}
cout << val << "\n";
return 0;
}
の残りの部分で説明;メインスレッドは引数の共有キューを作成し、そこから作業者は必要に応じて新しい作業を取ります。キューにアクセスするにはmutexが必要ですが、作業項目を挿入して抽出するのが安い限り( '.front()'の 'std :: move'を使用してコピー構築を避け、' .pop() 'mutexの制御の外側にある他のすべての作業でアイテムを削除するか、' std :: move'が依然として高価である、 'unique_ptr'などを格納して取り出す)場合、ロックの競合は最小限に抑える必要があります。 – ShadowRanger
基本的には、スレッドを「再利用」しないでください。スレッドは、終了する代わりに作業を続ける方法を知っておいてください。 – ShadowRanger
簡単な例を提供することができますか(または私に1つを指摘してください)。事前に感謝します – totalUnimodular