创建 MPI 结构时出现问题,调用时出现错误 11 MPI_Bcast
Problem creating an MPI struct, error 11 when calling MPI_Bcast
我想在进程之间传输一个结构,为此我正在尝试创建一个 MPI 结构。该代码用于蚁群优化 (ACO) 算法。
C 结构的头文件包含:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <math.h>
#include <mpi.h>
/* Constants */
#define NUM_CITIES 100 // Number of cities
//among others
typedef struct {
int city, next_city, tabu[NUM_CITIES], path[NUM_CITIES], path_index;
double tour_distance;
} ACO_Ant;
我尝试按照 中的建议构建我的代码。
程序代码:
int main(int argc, char *argv[])
{
MPI_Datatype MPI_TABU, MPI_PATH, MPI_ANT;
// Initialize MPI
MPI_Init(&argc, &argv);
//Determines the size (&procs) of the group associated with a communicator (MPI_COMM_WORLD)
MPI_Comm_size(MPI_COMM_WORLD, &procs);
//Determines the rank (&rank) of the calling process in the communicator (MPI_COMM_WORLD)
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Type_contiguous(NUM_CITIES, MPI_INT, &MPI_TABU);
MPI_Type_contiguous(NUM_CITIES, MPI_INT, &MPI_PATH);
MPI_Type_commit(&MPI_TABU);
MPI_Type_commit(&MPI_PATH);
// Create ant struct
//int city, next_city, tabu[NUM_CITIES], path[NUM_CITIES], path_index;
//double tour_distance;
int blocklengths[6] = {1,1, NUM_CITIES, NUM_CITIES, 1, 1};
MPI_Datatype types[6] = {MPI_INT, MPI_INT, MPI_TABU, MPI_PATH, MPI_INT, MPI_DOUBLE};
MPI_Aint offsets[6] = { offsetof( ACO_Ant, city ), offsetof( ACO_Ant, next_city), offsetof( ACO_Ant, tabu), offsetof( ACO_Ant, path ), offsetof( ACO_Ant, path_index ), offsetof( ACO_Ant, tour_distance )};
MPI_Datatype tmp_type;
MPI_Aint lb, extent;
MPI_Type_create_struct(6, blocklengths, offsets, types, &tmp_type);
MPI_Type_get_extent( tmp_type, &lb, &extent );
//Tried all of these
MPI_Type_create_resized( tmp_type, lb, extent, &MPI_ANT );
//MPI_Type_create_resized( tmp_type, 0, sizeof(MPI_ANT), &MPI_ANT );
//MPI_Type_create_resized( tmp_type, 0, sizeof(ant), &MPI_ANT );
MPI_Type_commit(&MPI_ANT);
printf("Return: %d\n" , MPI_Bcast(ant, NUM_ANTS, MPI_ANT, 0, MPI_COMM_WORLD));
}
但是一旦程序执行到 MPI_Bcast 命令,它就会崩溃并显示错误代码 11,我认为是 MPI_ERR_TOPOLOGY as per this manual.段错误(信号 11)。
我也不确定某些代码为什么是原始程序的作者 -
有人可以解释为什么他们创造
MPI_Aint displacements[3];
MPI_Datatype typelist[3];
大小为 3,当结构有 2 个变量时?
int block_lengths[2];
代码:
void ACO_Build_best(ACO_Best_tour *tour, MPI_Datatype *mpi_type /*out*/)
{
int block_lengths[2];
MPI_Aint displacements[3];
MPI_Datatype typelist[3];
MPI_Aint start_address;
MPI_Aint address;
block_lengths[0] = 1;
block_lengths[1] = NUM_CITIES;
typelist[0] = MPI_DOUBLE;
typelist[1] = MPI_INT;
displacements[0] = 0;
MPI_Address(&(tour->distance), &start_address);
MPI_Address(tour->path, &address);
displacements[1] = address - start_address;
MPI_Type_struct(2, block_lengths, displacements, typelist, mpi_type);
MPI_Type_commit(mpi_type);
}
我们将不胜感激。
编辑:帮助解决问题,不是边缘有用的 Whosebug 术语
这部分是错误的:
int blocklengths[6] = {1,1, NUM_CITIES, NUM_CITIES, 1, 1};
MPI_Datatype types[6] = {MPI_INT, MPI_INT, MPI_TABU, MPI_PATH, MPI_INT, MPI_DOUBLE};
MPI_Aint offsets[6] = { offsetof( ACO_Ant, city ), offsetof( ACO_Ant, next_city), offsetof( ACO_Ant, tabu), offsetof( ACO_Ant, path ), offsetof( ACO_Ant, path_index ), offsetof( ACO_Ant, tour_distance )};
MPI_TABU
和 MPI_PATH
数据类型已经涵盖了 NUM_CITIES
个元素。当您指定相应的块大小也为 NUM_CITIES
时,生成的数据类型将尝试访问 NUM_CITIES * NUM_CITIES
元素,可能会导致段错误(信号 11)。
要么将blocklengths
的所有元素设置为1
,要么将types
数组中的MPI_TABU
和MPI_PATH
替换为MPI_INT
。
这部分也错了:
MPI_Type_create_struct(6, blocklengths, offsets, types, &tmp_type);
MPI_Type_get_extent( tmp_type, &lb, &extent );
//Tried all of these
MPI_Type_create_resized( tmp_type, lb, extent, &MPI_ANT );
//MPI_Type_create_resized( tmp_type, 0, sizeof(MPI_ANT), &MPI_ANT );
//MPI_Type_create_resized( tmp_type, 0, sizeof(ant), &MPI_ANT );
MPI_Type_commit(&MPI_ANT);
用 MPI_Type_get_extent
返回的值调用 MPI_Type_create_resized
是没有意义的,因为它只是复制类型而没有实际调整它的大小。使用 sizeof(MPI_ANT)
是错误的,因为 MPI_ANT
不是 C 类型而是 MPI 句柄,它是整数索引或指针(依赖于实现)。如果 ant
是 ACO_Ant
类型,它将与 sizeof(ant)
一起工作,但是如果你调用 MPI_Bcast(ant, NUM_ANTS, ...)
,那么 ant
要么是一个指针,在这种情况下 sizeof(ant)
只是指针大小,或者它是一个数组,在这种情况下 sizeof(ant)
比它必须的大 NUM_ANTS
倍。正确的叫法是:
MPI_Type_create_resized(tmp_type, 0, sizeof(ACO_Ant), &ant_type);
MPI_Type_commit(&ant_type);
请不要在您自己的变量或函数名称中使用 MPI_
作为前缀。这使得代码不可读并且非常具有误导性("is that a predefined MPI datatype or a user-defined one?")
至于最后一个问题,作者可能有不同的结构。只要您使用正确数量的重要元素调用 MPI_Type_create
,就没有什么能阻止您使用更大的数组。
注意:您不必提交从未在通信调用中直接使用的 MPI 数据类型。即,这两行是不必要的:
MPI_Type_commit(&MPI_TABU);
MPI_Type_commit(&MPI_PATH);
我想在进程之间传输一个结构,为此我正在尝试创建一个 MPI 结构。该代码用于蚁群优化 (ACO) 算法。
C 结构的头文件包含:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <math.h>
#include <mpi.h>
/* Constants */
#define NUM_CITIES 100 // Number of cities
//among others
typedef struct {
int city, next_city, tabu[NUM_CITIES], path[NUM_CITIES], path_index;
double tour_distance;
} ACO_Ant;
我尝试按照
程序代码:
int main(int argc, char *argv[])
{
MPI_Datatype MPI_TABU, MPI_PATH, MPI_ANT;
// Initialize MPI
MPI_Init(&argc, &argv);
//Determines the size (&procs) of the group associated with a communicator (MPI_COMM_WORLD)
MPI_Comm_size(MPI_COMM_WORLD, &procs);
//Determines the rank (&rank) of the calling process in the communicator (MPI_COMM_WORLD)
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Type_contiguous(NUM_CITIES, MPI_INT, &MPI_TABU);
MPI_Type_contiguous(NUM_CITIES, MPI_INT, &MPI_PATH);
MPI_Type_commit(&MPI_TABU);
MPI_Type_commit(&MPI_PATH);
// Create ant struct
//int city, next_city, tabu[NUM_CITIES], path[NUM_CITIES], path_index;
//double tour_distance;
int blocklengths[6] = {1,1, NUM_CITIES, NUM_CITIES, 1, 1};
MPI_Datatype types[6] = {MPI_INT, MPI_INT, MPI_TABU, MPI_PATH, MPI_INT, MPI_DOUBLE};
MPI_Aint offsets[6] = { offsetof( ACO_Ant, city ), offsetof( ACO_Ant, next_city), offsetof( ACO_Ant, tabu), offsetof( ACO_Ant, path ), offsetof( ACO_Ant, path_index ), offsetof( ACO_Ant, tour_distance )};
MPI_Datatype tmp_type;
MPI_Aint lb, extent;
MPI_Type_create_struct(6, blocklengths, offsets, types, &tmp_type);
MPI_Type_get_extent( tmp_type, &lb, &extent );
//Tried all of these
MPI_Type_create_resized( tmp_type, lb, extent, &MPI_ANT );
//MPI_Type_create_resized( tmp_type, 0, sizeof(MPI_ANT), &MPI_ANT );
//MPI_Type_create_resized( tmp_type, 0, sizeof(ant), &MPI_ANT );
MPI_Type_commit(&MPI_ANT);
printf("Return: %d\n" , MPI_Bcast(ant, NUM_ANTS, MPI_ANT, 0, MPI_COMM_WORLD));
}
但是一旦程序执行到 MPI_Bcast 命令,它就会崩溃并显示错误代码 11,我认为是 MPI_ERR_TOPOLOGY as per this manual.段错误(信号 11)。
我也不确定某些代码为什么是原始程序的作者 - 有人可以解释为什么他们创造
MPI_Aint displacements[3];
MPI_Datatype typelist[3];
大小为 3,当结构有 2 个变量时?
int block_lengths[2];
代码:
void ACO_Build_best(ACO_Best_tour *tour, MPI_Datatype *mpi_type /*out*/)
{
int block_lengths[2];
MPI_Aint displacements[3];
MPI_Datatype typelist[3];
MPI_Aint start_address;
MPI_Aint address;
block_lengths[0] = 1;
block_lengths[1] = NUM_CITIES;
typelist[0] = MPI_DOUBLE;
typelist[1] = MPI_INT;
displacements[0] = 0;
MPI_Address(&(tour->distance), &start_address);
MPI_Address(tour->path, &address);
displacements[1] = address - start_address;
MPI_Type_struct(2, block_lengths, displacements, typelist, mpi_type);
MPI_Type_commit(mpi_type);
}
我们将不胜感激。
编辑:帮助解决问题,不是边缘有用的 Whosebug 术语
这部分是错误的:
int blocklengths[6] = {1,1, NUM_CITIES, NUM_CITIES, 1, 1};
MPI_Datatype types[6] = {MPI_INT, MPI_INT, MPI_TABU, MPI_PATH, MPI_INT, MPI_DOUBLE};
MPI_Aint offsets[6] = { offsetof( ACO_Ant, city ), offsetof( ACO_Ant, next_city), offsetof( ACO_Ant, tabu), offsetof( ACO_Ant, path ), offsetof( ACO_Ant, path_index ), offsetof( ACO_Ant, tour_distance )};
MPI_TABU
和 MPI_PATH
数据类型已经涵盖了 NUM_CITIES
个元素。当您指定相应的块大小也为 NUM_CITIES
时,生成的数据类型将尝试访问 NUM_CITIES * NUM_CITIES
元素,可能会导致段错误(信号 11)。
要么将blocklengths
的所有元素设置为1
,要么将types
数组中的MPI_TABU
和MPI_PATH
替换为MPI_INT
。
这部分也错了:
MPI_Type_create_struct(6, blocklengths, offsets, types, &tmp_type);
MPI_Type_get_extent( tmp_type, &lb, &extent );
//Tried all of these
MPI_Type_create_resized( tmp_type, lb, extent, &MPI_ANT );
//MPI_Type_create_resized( tmp_type, 0, sizeof(MPI_ANT), &MPI_ANT );
//MPI_Type_create_resized( tmp_type, 0, sizeof(ant), &MPI_ANT );
MPI_Type_commit(&MPI_ANT);
用 MPI_Type_get_extent
返回的值调用 MPI_Type_create_resized
是没有意义的,因为它只是复制类型而没有实际调整它的大小。使用 sizeof(MPI_ANT)
是错误的,因为 MPI_ANT
不是 C 类型而是 MPI 句柄,它是整数索引或指针(依赖于实现)。如果 ant
是 ACO_Ant
类型,它将与 sizeof(ant)
一起工作,但是如果你调用 MPI_Bcast(ant, NUM_ANTS, ...)
,那么 ant
要么是一个指针,在这种情况下 sizeof(ant)
只是指针大小,或者它是一个数组,在这种情况下 sizeof(ant)
比它必须的大 NUM_ANTS
倍。正确的叫法是:
MPI_Type_create_resized(tmp_type, 0, sizeof(ACO_Ant), &ant_type);
MPI_Type_commit(&ant_type);
请不要在您自己的变量或函数名称中使用 MPI_
作为前缀。这使得代码不可读并且非常具有误导性("is that a predefined MPI datatype or a user-defined one?")
至于最后一个问题,作者可能有不同的结构。只要您使用正确数量的重要元素调用 MPI_Type_create
,就没有什么能阻止您使用更大的数组。
注意:您不必提交从未在通信调用中直接使用的 MPI 数据类型。即,这两行是不必要的:
MPI_Type_commit(&MPI_TABU);
MPI_Type_commit(&MPI_PATH);