科学計算のほとんどの人は、共有メモリの並列化に関して、準標準としてOpenMPを使用しています。
pthread上でOpenMPを使用する理由(読みやすさ以外)はありますか?後者はより基本的なようであり、最適化する方が速くて簡単かもしれないと思います。
科学計算のほとんどの人は、共有メモリの並列化に関して、準標準としてOpenMPを使用しています。
pthread上でOpenMPを使用する理由(読みやすさ以外)はありますか?後者はより基本的なようであり、最適化する方が速くて簡単かもしれないと思います。
基本的には、並列化に対してどのレベルの制御が必要かということになります。OpenMP は、いくつかの #pragma ステートメントを追加してコードの並列バージョンを非常に迅速に作成するだけでよい場合に最適です。MIMD コーディングまたは複雑なキューイングで本当に興味深いことをしたい場合は、これらすべてを OpenMP で行うことができますが、その場合はスレッド化を使用する方がおそらくはるかに簡単です。OpenMP には、pthread と同様に、さまざまなプラットフォーム用の多くのコンパイラが現在サポートしているという点で、移植性の点でも同様の利点があります。
したがって、あなたは絶対に正しいです。並列化を微調整する必要がある場合は、pthreads を使用してください。できるだけ少ない作業で並列化したい場合は、OpenMP を使用してください。
どちらに進むにしても、頑張ってください!
もう 1 つの理由: OpenMP はタスクベースであり、Pthreads はスレッドベースです。これは、OpenMP がコア数と同じ数のスレッドを割り当てることを意味します。したがって、スケーラブルなソリューションが得られます。生のスレッドを使用してそれを行うのはそれほど簡単な作業ではありません。
2 番目の意見: OpenMP はリダクション機能を提供します: スレッドで部分的な結果を計算し、それらを結合する必要がある場合。1 行のコードを使用するだけで実装できます。しかし、生のスレッドを使用すると、より多くの作業を行う必要があります。
要件について考え、理解しようとしてください。OpenMP で十分でしょうか? 多くの時間を節約できます。
OpenMP には、OpenMP をサポートし、プラグマで動作するコンパイラが必要です。これの利点は、OpenMP をサポートせずにコンパイルしても (現在の PCC または Clang/LLVM など)、コードがコンパイルされることです。また、Charles Leiserson が DIY マルチスレッドについて書いた記事もご覧ください。
Pthreads はライブラリの POSIX 標準 ( IEEE POSIX 1003.1c ) ですが、 OpenMP 仕様はコンパイラに実装されます。そうは言っても、さまざまな pthread 実装 (OpenBSD rthreads、NPTL など) と、OpenMP をサポートする多数のコンパイラ (-fopenmp フラグを使用した GCC、MSVC++ 2008 など) があります。
Pthreads は、複数のプロセッサが使用可能な場合、および使用可能なプロセッサの数に対してコードが最適化されている場合にのみ、並列化に有効です。その結果、OpenMP のコードはより簡単にスケーラブルになります。OpenMP でコンパイルされるコードと、pthreads を使用するコードを混在させることもできます。
質問は「Cまたはアセンブリをプログラムする必要があるか」という質問に似ています。CはOpenMPであり、アセンブリはpthreadです。
pthreadを使用すると、はるかに優れた並列化を実行できます。つまり、アルゴリズムとハードウェアに非常に厳密に調整されます。ただし、これは大変な作業になります。
pthreadを使用すると、並列化が不十分なコードを作成するのもはるかに簡単になります。
pthreads で OpenMP を使用する (読みやすさ以外の) 理由はありますか?
マイクはこれに触れました:
OpenMP には、pthreads と同様に、さまざまなプラットフォーム用の多くのコンパイラが現在サポートしているという点で、移植性の点でも同様の利点があります。
Crypto++はクロスプラットフォームです。つまり、Windows、Linux、OS X、および BSD で実行されます。べき乗剰余や剰余乗算など、演算が高価になる可能性がある場所 (および同時操作を実行できる場所) でのスレッド化サポートに OpenMP を使用します。
Windows は pthread をサポートしていませんが、最新の Windows コンパイラは OpenMP をサポートしています。したがって、非 * nix への移植性が必要な場合は、OpenMP が適切な選択であることがよくあります。
また、Mike も次のように指摘しています。
OpenMP は、いくつかの #pragma ステートメントを追加してコードの並列バージョンを非常に迅速に作成するだけでよい場合に最適です。
以下は、Bernstein がRSA 署名と Rabin-Williams 署名で説明したように、Tweaked Roots を使用して Rabin-Williams 署名で使用されるいくつかの値を事前計算する Crypto++ の例です... :
void InvertibleRWFunction::Precompute(unsigned int /*unused*/)
{
ModularArithmetic modp(m_p), modq(m_q);
#pragma omp parallel sections
{
#pragma omp section
m_pre_2_9p = modp.Exponentiate(2, (9 * m_p - 11)/8);
#pragma omp section
m_pre_2_3q = modq.Exponentiate(2, (3 * m_q - 5)/8);
#pragma omp section
m_pre_q_p = modp.Exponentiate(m_q, m_p - 2);
}
}
これは、Mike の観察と一致します。きめ細かな制御と同期は実際には必要ありませんでした。実行速度を上げるために並列化が使用され、同期はソース コードで無料で行われました。
OpenMP が利用できない場合、コードは次のようになります。
m_pre_2_9p = modp.Exponentiate(2, (9 * m_p - 11)/8);
m_pre_2_3q = modq.Exponentiate(2, (3 * m_q - 5)/8);
m_pre_q_p = modp.Exponentiate(m_q, m_p - 2);