我有一个存储结构的向量的应用程序。 这些结构容纳约像存储器和千兆触发器/ s的系统上的每个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
,因为它们的长度在每台机器上各不相同。
您可以使用MPI_GATHERV
结合MPI_GATHER
来实现这一目标。 MPI_GATHERV
是可变版本MPI_GATHER
并且它允许根秩来收集来自每个发送处理元件的数目differt。 但是,为了根排名来指定这些数字它必须知道每个等级是多少元素控股。 这可以通过使用简单的单一元件来实现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
在上面的代码中)的结构(二进制发送会工作,但不会是便携,也不会在异构设置工作)。