C OpenMP 並列 For ループ: std::vector の代替
std::vector は、並列 for ループで一般的に使用される多用途のデータ構造です。 OpenMP でループします。ただし、特に速度を優先する場合やループ中のサイズ変更で問題が発生する場合など、代替手段の方が適している状況もあります。
共有データ構造のオプションの 1 つは、OpenMP 4.0 で カスタム削減を使用することです。の #pragma omp は削減を宣言します。これにより、クリティカル セクションの必要性が減り、並列コードが簡素化されます。
順序を維持するためのもう 1 つの代替案は、順序付けされた セクションによる静的スケジューリングを採用することです。これにより、各スレッドがベクターの特定の部分に順番に書き込まれることが保証され、後でマージする必要がなくなります。
サイズ変更が必要なシナリオでは、スレッドの追跡に ポインター配列 を使用するメソッドが使用されます。固有のプレフィックス合計を採用できます。このアプローチにより、クリティカル パスでのサイズ変更のオーバーヘッドが回避されます。
これらの代替案のコード例は次のとおりです:
// Custom reduction #pragma omp declare reduction (merge: std::vector<int>: omp_out.insert(omp_out.end(), omp_in.begin(), omp_in.end()) std::vector<int> vec; #pragma omp parallel for reduction(merge: vec) for (int i = 0; i < 100; i++) vec.push_back(i);
// Static scheduling with ordered sections std::vector<int> vec; #pragma omp parallel { int ithread = omp_get_thread_num(); int nthreads = omp_get_num_threads(); #pragma omp single { prefix = new size_t[nthreads + 1]; prefix[0] = 0; } std::vector<int> vec_private; #pragma omp for schedule(static) nowait for (int i = 0; i < 100; i++) { vec_private.push_back(i); } prefix[ithread + 1] = vec_private.size(); #pragma omp barrier #pragma omp single { for (int i = 1; i < (nthreads + 1); i++) prefix[i] += prefix[i - 1]; vec.resize(vec.size() + prefix[nthreads]); } std::copy(vec_private.begin(), vec_private.end(), vec.begin() + prefix[ithread]); } delete[] prefix;
特定のケースに適した代替案の選択は、要件によって異なります。そしてパフォーマンスに関する考慮事項。実験とプロファイリングは、最適なソリューションを決定するのに役立ちます。
以上がC OpenMP 並列 For ループの std::vector の代替手段は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。