我有一个结构:
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);
收集我的root后,看到all_best只包含1个普通元素,而其他元素则只有垃圾。 all_best的类型是tour *。
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);
}
欢迎任何想法。
答案 0 :(得分:3)
除了将不正确的长度传递给MPI_Gather
之外,MPI实际上并不遵循指针指针。使用这样的结构化类型,您将发送distance
的值和path
指针的值(本质上是一个在发送到其他进程时没有意义的地址)。如果假设distance
基本上给出path
中的元素数量,那么您可以通过MPI_Gather
和MPI_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_paths
中连接所有路径。您可以从counts[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
如何分配(和大小)的一些信息,则很难给出具体的解决方案。