6

構造体のベクトルを格納するアプリケーションがあります。これらの構造体は、メモリやギガフロップスなどのシステム上の各GPUに関する情報を保持します。システムごとに異なる数のGPUがあります。

一度に複数のマシンで実行されるプログラムがあり、このデータを収集する必要があります。私はMPIに非常に慣れていませんが、ほとんどの部分を使用できますが、これらの動的なサイズのベクトルを収集/受信MPI_Gather()する方法を知りたいです。

class MachineData
{
    unsigned long hostMemory;
    long cpuCores;
    int cudaDevices;
    public:
    std::vector<NviInfo> nviVec; 
    std::vector<AmdInfo> amdVec;
    ...
};

struct AmdInfo
{
    int platformID;
    int deviceID;
    cl_device_id device;
    long gpuMem;
    float sgflops;
    double dgflops;
};

クラスタ内の各マシンは、のインスタンスにデータを入力しますMachineData。これらのインスタンスをそれぞれ収集したいのですが、収集の方法がわかりませんnviVec。またamdVec、マシンごとに長さが異なるためです。

4

1 に答える 1

8

MPI_GATHERVと組み合わせて使用MPI_GATHER​​すると、それを実現できます。MPI_GATHERVはの可変バージョンでMPI_GATHERあり、ルートランクが各送信プロセスから異なる数の要素を収集できるようにします。ただし、ルートランクでこれらの数値を指定するには、各ランクが保持している要素の数を知る必要があります。これは、その前に単純な単一要素を使用して実現できますMPI_GATHER。このようなもの:

// To keep things simple: root is fixed to be rank 0 and MPI_COMM_WORLD is used

// Number of MPI processes and current rank
int size, rank;
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);

int *counts = new int[size];
int nelements = (int)vector.size();
// Each process tells the root how many elements it holds
MPI_Gather(&nelements, 1, MPI_INT, counts, 1, MPI_INT, 0, MPI_COMM_WORLD);

// Displacements in the receive buffer for MPI_GATHERV
int *disps = new int[size];
// Displacement for the first chunk of data - 0
for (int i = 0; i < size; i++)
   disps[i] = (i > 0) ? (disps[i-1] + counts[i-1]) : 0;

// Place to hold the gathered data
// Allocate at root only
type *alldata = NULL;
if (rank == 0)
  // disps[size-1]+counts[size-1] == total number of elements
  alldata = new int[disps[size-1]+counts[size-1]];
// Collect everything into the root
MPI_Gatherv(vectordata, nelements, datatype,
            alldata, counts, disps, datatype, 0, MPI_COMM_WORLD);

また、構造体のMPI派生データ型(datatype上記のコード)を登録する必要があります(バイナリ送信は機能しますが、移植性がなく、異種セットアップでは機能しません)。

于 2012-08-23T10:38:44.733 に答える