c - 创建 MPI 结构时出现问题,调用 MPI_Bcast 时出现错误 11

标签 c struct mpi mpich

我想在进程之间传输一个结构,为此我正在尝试创建一个 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;

我尝试按照 this thread 中的建议构建我的代码.

程序代码:

    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);
    }

我们将不胜感激。
编辑:帮助解决问题,而不是边缘有用的 StackOverflow 术语

最佳答案

这部分是错误的:

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_TABUMPI_PATH 数据类型已经涵盖NUM_CITIES 元素。当您指定相应的 block 大小也为 NUM_CITIES 时,生成的数据类型将尝试访问 NUM_CITIES * NUM_CITIES 元素,可能会导致段错误(信号 11)。

blocklengths 的所有元素设置为 1 或替换 types 中的 MPI_TABUMPI_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 句柄,它是整数索引或指针(依赖于实现)。如果 antACO_Ant 类型,它将与 sizeof(ant) 一起工作,但如果您调用 MPI_Bcast(ant, NUM_ANTS, . ..),那么 ant 要么是一个指针,在这种情况下 sizeof(ant) 只是指针大小,要么是一个数组,其中case sizeof(ant)NUM_ANTS 的倍数。正确的调用是:

MPI_Type_create_resized(tmp_type, 0, sizeof(ACO_Ant), &ant_type);
MPI_Type_commit(&ant_type);

请不要在您自己的变量或函数名称中使用 MPI_ 作为前缀。这使得代码不可读并且非常具有误导性(“这是预定义的 MPI 数据类型还是用户定义的数据类型?”)

至于最后一个问题,作者可能有不同的结构。只要您使用正确数量的重要元素调用 MPI_Type_create,就没有什么能阻止您使用更大的数组。

注意:您不必提交从未在通信调用中直接使用的 MPI 数据类型。即,这两行是不必要的:

MPI_Type_commit(&MPI_TABU);
MPI_Type_commit(&MPI_PATH);

关于c - 创建 MPI 结构时出现问题,调用 MPI_Bcast 时出现错误 11,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55678073/

相关文章:

c - 通用二维数组

c - 防止 MSYS 'bash' 终止捕获 ^C 的进程

python - 使用 Python 作为界面时的奇怪控件

c - 如何从 typedef 生成静态结构

你能在 MPI 中即时请求额外的处理器吗?

mpi - 当我尝试发送 2D int 数组时,为什么 MPI_Send 会阻塞?

c - 在 Swift 3 中读取 TrueType 'cmap' 格式 4 子表

go - 如何在方法中返回结构变量

multiprocessing - MPI 未使用分配的所有 CPU

C:取消引用指向不完整类型错误的指针