0

MPI初心者です。事前に計算され、バイナリ ファイルに格納されている多数の数値配列gmat (double 型、次元 1x14000000) があります。約 100 MB のメモリを使用します (14000000 x8 バイト /1024 /1024)。この配列に対して何らかの計算を行う MPI コードを書きたいと思います (たとえば、gmatプロセスのすべての要素をランク数で乗算します)。この配列gmat自体は、実行時に一定のままです。コードは次のようなものになっているはずです

#include <iostream>
#include "mpi.h"
double* gmat;
long int imax;

int main(int argc, char* argv[])
{
void performcomputation(int rank); // this function performs the computation and will be called by all processes

imax=atoi(argv[1]); // user inputs the length of gmat 

MPI::Init();
rank = MPI::COMM_WORLD.Get_rank();
size = MPI::COMM_WORLD.Get_size(); //i will use -np 16 = 4 processors x 4 cores

if rank==0 // read the gmat array using one of the processes
{
gmat = new double[imax];
// read values of gmat from a file
// next line is supposed to broadcast values of gmat to all processes which will use it
MPI::COMM_WORLD.Bcast(&gmat,imax,MPI::DOUBLE,1);     
}

MPI::COMM_WORLD.Barrier();
performcomputation(rank);  
MPI::Finalize();  

return 0;
} 

void performcomputation(int rank)
{
int i;
for (i=0;i <imax; i++)
cout << "the new value is" << gmat[i]*rank << endl; 
}    

私の質問は、16 個のプロセス (-np 16) を使用してこのコードを実行した場合、gmat はそれらすべてで同じですか? つまり、コードは各プロセスの gmat を格納するためにメモリ内で 16 x 100 MB を使用しますか、それとも gmat をグローバルに定義したので 100 MB しか使用しませんか? また、非常に多くの数値を読み取るのに時間がかかるため、さまざまなプロセスが gmat をファイルから個別に読み取ることは望ましくありません。これを行うより良い方法は何ですか? ありがとう。

4

1 に答える 1

1

まず、MPI C++ バインディングを使用しないでください。これらは MPI-2.2 で廃止され、MPI-3.0 で削除されたため、仕様の一部ではなくなりました。つまり、将来の MPI 実装では C++ バインディングを提供する必要さえありません。インターフェイスがどのように見えるか。

とはいえ、コードには非常によくある間違いが含まれています。

if rank==0 // read the gmat array using one of the processes
{
   gmat = new double[imax];
   // read values of gmat from a file
   // next line is supposed to broadcast values of gmat to all processes which will use it
   MPI::COMM_WORLD.Bcast(&gmat,imax,MPI::DOUBLE,1);     
}

ここには 4 つのエラーがあるため、これは機能しません。まず、gmatランク 0 でのみ割り当てられ、他のランクでは割り当てられないため、これは望ましくありません。次に、ポインタが指すデータのアドレスではなくBcast、ポインタのアドレスをgmat指定しています (つまり、&演算子を使用しないでください)。ランクからもブロードキャストしますが、ブロードキャストルート引数として0配置します。1しかし、最も重要なエラーは、それMPI_BCASTが集合通信呼び出しであり、正常に完了するためには、すべてのランクが引数の同じ値で呼び出す必要があることです。root正しいコード (C++ バインディングの代わりに C バインディングを使用) は次のとおりです。

gmat = new double[imax];

if (rank == 0)
{
   // read values of gmat from a file
}
MPI_Bcast(gmat, imax, MPI_DOUBLE, 0, MPI_COMM_WORLD);
//        ^^^^                   ^^^
//        no &                root == 0

各ランクには の独自のコピーがありgmatます。最初はすべての値が異なります (たとえば、メモリ アロケータに依存するランダムまたはすべてゼロ)。ブロードキャスト後、すべてのコピーはgmatランク 0の のコピーと同じになります。各ランクが の要素に異なる数をperformcomputation()乗算するため、各コピーの呼び出し後は再び異なります。gmatあなたの質問に対する答えは次のとおりです。コードは各ランクで 100 MiB を使用するため、合計で 16 x 100 MiB になります。

MPI は分散メモリを扱います。プロセスは、変数がローカルかグローバルかに関係なく、変数を共有しません。データを共有する唯一の方法は、ポイントツーポイント通信 (例: MPI_SEND/ MPI_RECV)、集団呼び出し (例: MPI_BCAST)、または一方的な通信 (例: MPI_PUT/ MPI_GET) などの MPI 呼び出しを使用することです。

于 2013-09-23T13:59:33.433 に答える