0

openmp スレッド間で MPI_Allgather のような機能を使用しようとしています。これで、すべてのスレッドがまとめてデータのコピーを作成できます (ただし、各スレッドはその一部のみを生成します)。

実際、MPI_SEND と MPI_RECV の「タグ」フィールドにスレッド ID を使用することで、openmp スレッド間の通信が可能になります。しかし、MPI_Allgather はそのようには機能していないようです。

2 つの MPI プロセスがあります。各プロセスには 2 つの openmp スレッドがあります。これら 4 つのスレッドのそれぞれがデータの一部を計算します。MPI_Allgather を使用して、すべてのスレッドがデータを結合し、結合されたデータのコピーを持つようにしたいと考えています。しかし、MPI_Allgather は MPI プロセスの粒度でのみ機能するようです。

それを行う方法についての提案をいただければ幸いです。

ありがとう!

4

1 に答える 1

1

すべての 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代わりに使用する必要があります。

于 2013-09-27T11:49:40.447 に答える