0

我有一个结构:

typedef struct 
{ 
double distance;
int* path;
} tour;

然后我试图从所有进程中收集结果:

   MPI_Gather(&best, sizeof(tour), MPI_BEST, all_best, sizeof(tour)*proc_count, MPI_BEST, 0, MPI_COMM_WORLD);

收集我的根目录后,看到 all_best 仅包含 1 个正常元素和其他元素中的垃圾。all_best 的类型是游览*。

MPI_BEST 的初始化:

 void ACO_Build_best(tour *tour,int city_count, MPI_Datatype *mpi_type /*out*/)
 {
int block_lengths[2];
MPI_Aint displacements[2];
MPI_Datatype typelist[2];
MPI_Aint start_address;
MPI_Aint address;

block_lengths[0] = 1;
block_lengths[1] = city_count;

typelist[0] = MPI_DOUBLE;
typelist[1] = MPI_INT;

MPI_Address(&(tour->distance), &displacements[0]);
MPI_Address(&(tour->path), &displacements[1]);

displacements[1] = displacements[1] - displacements[0];
displacements[0] = 0;

MPI_Type_struct(2, block_lengths, displacements, typelist, mpi_type);
MPI_Type_commit(mpi_type);
}

欢迎任何想法。

4

1 回答 1

3

除了将不正确的长度传递给 之外MPI_Gather,MPI 实际上并不遵循指向指针的指针。使用这种结构化类型,您将发送指针的值distance和值path(本质上是一个在发送到其他进程时没有意义的地址)。如果假设distance本质上给出了 中的元素数量,那么您可以通过和path的组合来实现您的目标:MPI_GatherMPI_Gatherv

首先,收集长度:

int counts[proc_count];

MPI_Gather(&best->distance, 1, MPI_INT, counts, 1, MPI_INT, 0, MPI_COMM_WORLD);

现在counts填充了正确的长度,您可以继续并使用它MPI_Gatherv来接收所有路径:

int disps[proc_count];

disps[0] = 0;
for (int i = 1; i < proc_count; i++)
   disps[i] = disps[i-1] + counts[i-1];
// Allocate space for the concatenation of all paths
int *all_paths = malloc((disps[proc_count-1] + counts[proc_count-1])*sizeof(int));
MPI_Gatherv(best->path, best->distance, MPI_INT,
            all_paths, counts, disps, MPI_INT, 0, MPI_COMM_WORLD);

现在你有所有路径的串联all_pathscounts[i]您可以通过获取从位置开始的元素disps[i]来检查或提取单个路径all_paths。或者你甚至可以构建一个tour结构数组并让它们使用已经分配和填充的路径存储:

tour *all_best = malloc(proc_count*sizeof(tour));
for (int i = 0; i < proc_count; i++)
{
   all_best[i].distance = counts[i];
   all_best[i].path = &all_paths[disps[i]];
}

或者您可以复制这些段:

for (int i = 0; i < proc_count; i++)
{
   all_best[i].distance = counts[i];
   all_best[i].path = malloc(counts[i]*sizeof(int));
   memcpy(all_best[i].path, &all_paths[disps[i]], counts[i]*sizeof(int));
}
// all_paths is not needed any more and can be safely free()-ed

编辑:因为我忽略了tour结构的定义,所以上面的代码实际上适用于:

struct
{
   int distance;
   int *path;
}

其中distance包含 中重要元素的数量path。这与您的情况不同,但是如果没有有关如何tour.path分配(和调整大小)的一些信息,很难给出具体的解决方案。

于 2012-12-07T13:12:21.087 回答