すべての MPI 通信呼び出しは、ランクと呼ばれるエンティティに対応します。現在、すべての MPI 実装は、ランクがOS プロセスに等しいという解釈に従います。つまり、メモリ空間を共有しないエンティティです。原則として、メッセージタグを作成することで個々のスレッドに対処できることは、回避策 (またはむしろハック) です。たとえば、MPI_ANY_TAG
無限ループや中央プロセス全体のディスパッチメカニズムを使用せずに、複数のスレッドに対して類似のものを実装してみてください。
MPI-3.0 の初期段階で、いわゆるエンドポイントを含める提案がありました。これは基本的に、一連のランクをプロセス内の一連のスレッドに分散できるようにするメカニズムです。提案は投票メカニズムを通過しなかったため、テキストをさらに改良する必要があります。
とはいえ、以下は、pt2pt 操作で集合呼び出しを再実装せずに、目的を達成するもっともらしい方法です。
#pragma omp parallel shared(gbuf) private(buf,tid)
{
tid = omp_get_thread_num();
...
// Gather threads' data into the shared buffer 'gbuf'
// Data should start at gbuf[rank * num_threads * data_per_thread]
memcpy(gbuf + (rank*num_threads + tid)*data_per_thread,
buf, data_per_thread*size);
// Make sure all threads have finished copying their chunks
// then gather the data from all the other ranks
#pragma omp barrier
#pragma omp single
{
MPI_Allgather(MPI_IN_PLACE, 0, MPI_TYPE_NULL,
gbuf, num_threads*data_per_thread, data_type, comm);
}
...
}
buf
これは、最初に各スレッドのローカル バッファからグローバル受信バッファにデータを収集することによって機能しますgbuf
。この例では単純なmemcpy
ものが使用されていますが、複雑な派生データ型が使用されている場合は、より複雑になる可能性があります。ローカル データが適切に収集されると、インプレースMPI_Allgather
を使用して他のプロセスから断片を収集します。このsingle
構成により、プロセスごとに 1 つのスレッドのみが gather-to-all 呼び出しを行うことが保証されます。
スレッドの数がすべてのプロセスで同じでない場合は、MPI_Allgatherv
代わりに使用する必要があります。