【问题标题】:MPI_Scatterv segfaultMPI_Scatterv 段错误
【发布时间】:2014-01-12 14:53:07
【问题描述】:

我刚开始使用 MPI 编程,并决定使用 OpenMPI 制作一个简单的分布式 qsort。为了分发我想要排序的部分数组,我尝试使用 MPI_Scatterv,但是下面的代码段错误:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>

#define ARRAY_SIZE 26
#define BUFFER_SIZE 2048

int main(int argc, char** argv) {
    int my_rank, nr_procs;

    int* data_in, *data_out;
    int* sizes;
    int* offsets;

    srand(time(0));

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &nr_procs);
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

    // everybody generates the control tables
    int nr_workers = nr_procs-1;
    sizes = malloc(sizeof(int)*nr_workers);
    offsets = malloc(sizeof(int)*nr_workers);

    int nr_elems = ARRAY_SIZE/nr_workers;

    // basic distribution
    for (int i = 0; i < nr_workers; ++i) {
        sizes[i] = nr_elems;
    }
    // distribute the remainder
    int left = ARRAY_SIZE%nr_workers;
    int curr_worker = 0;
    while (left) {
        ++sizes[curr_worker];
        curr_worker = (++curr_worker)%nr_workers;
        --left;
    }   
    // offsets
    int curr_offset = 0;
    for (int i = 0; i < nr_workers; ++i) {
        offsets[i] = curr_offset;
        curr_offset += sizes[i];
    }


    if (my_rank == 0) {
        // root
        data_in = malloc(sizeof(int)*ARRAY_SIZE);
        data_out = malloc(sizeof(int)*ARRAY_SIZE);
        for (int i = 0; i < ARRAY_SIZE; ++i) {
            data_in[i] = rand();
        }

        for (int i = 0; i < nr_workers; ++i) {
            printf("%d at %d\n", sizes[i], offsets[i]);
        }

        MPI_Scatterv (data_in, sizes, offsets, MPI_INT, data_out, ARRAY_SIZE, MPI_INT, 0, MPI_COMM_WORLD);


    } else {
        // worker
        printf("%d has %d elements!\n",my_rank, sizes[my_rank-1]);
        // alloc the input buffer
        data_in = malloc(sizeof(int)*sizes[my_rank-1]);

        MPI_Scatterv(NULL, NULL, NULL, MPI_INT, data_in, sizes[my_rank-1], MPI_INT, 0, MPI_COMM_WORLD);

        printf("%d got:\n", my_rank);
        for (int i = 0; i < sizes[my_rank-1]; ++i) {
            printf("%d ", data_in[i]);
        }
        printf("\n");
    }

    MPI_Finalize();
    return 0;
}

我将如何使用 Scatterv?我从工作代码内部分配输入缓冲区是否有问题?

【问题讨论】:

    标签: c mpi openmpi


    【解决方案1】:

    我更改了您代码中的某些部分以使其正常工作。

    MPI_Scatter() 将向每个处理器发送数据,包括他自己。根据您的程序,处理器 0 需要 ARRAY_SIZE 整数,但 sizes[0] 要小得多。 其他进程还有其他问题:MPI_Scatter 将发送sizes[my_rank] 整数,但预计sizes[my_rank-1]...

    这是一个将data_in从0分散到所有处理器的代码,包括0。因此我将1添加到nr_workers

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <time.h>
    #include <mpi.h>
    
    #define ARRAY_SIZE 26
    #define BUFFER_SIZE 2048
    
    int main(int argc, char** argv) {
        int my_rank, nr_procs;
    
        int* data_in, *data_out;
        int* sizes;
        int* offsets;
    
        srand(time(0));
    
        MPI_Init(&argc, &argv);
        MPI_Comm_size(MPI_COMM_WORLD, &nr_procs);
        MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
    
        // everybody generates the control tables
        int nr_workers = nr_procs;
        sizes = malloc(sizeof(int)*nr_workers);
        offsets = malloc(sizeof(int)*nr_workers);
    
        int nr_elems = ARRAY_SIZE/nr_workers;
    
        // basic distribution
        for (int i = 0; i < nr_workers; ++i) {
            sizes[i] = nr_elems;
        }
        // distribute the remainder
        int left = ARRAY_SIZE%nr_workers;
        int curr_worker = 0;
        while (left) {
            ++sizes[curr_worker];
            curr_worker = (++curr_worker)%nr_workers;
            --left;
        }   
        // offsets
        int curr_offset = 0;
        for (int i = 0; i < nr_workers; ++i) {
            offsets[i] = curr_offset;
            curr_offset += sizes[i];
        }
    
        if (my_rank == 0) {
            // root
            data_in = malloc(sizeof(int)*ARRAY_SIZE);
    
            for (int i = 0; i < ARRAY_SIZE; ++i) {
                data_in[i] = rand();
                printf("%d %d \n",i,data_in[i]);
            }
    
            for (int i = 0; i < nr_workers; ++i) {
                printf("%d at %d\n", sizes[i], offsets[i]);
            }
    
    
        } else {
            printf("%d has %d elements!\n",my_rank, sizes[my_rank]);
        }
        data_out = malloc(sizeof(int)*sizes[my_rank]);
    
        MPI_Scatterv (data_in, sizes, offsets, MPI_INT, data_out, sizes[my_rank], MPI_INT, 0, MPI_COMM_WORLD);
    
        printf("%d got:\n", my_rank);
        for (int i = 0; i < sizes[my_rank]; ++i) {
            printf("%d ", data_out[i]);
        }
        printf("\n");
        free(data_out);
        if(my_rank==0){
            free(data_in);
        }
        MPI_Finalize();
        return 0;
    }
    

    关于内存管理,data_indata_out 应在代码末尾释放。

    这是你想做的吗?祝你好运!我认为您不是第一个使用 MPI 对整数进行排序的人。见parallel sort using mpi。您在 0 进程上生成随机数然后分散它们的方法是正确的方法。我想你会对他的TD_Trier() 交流功能感兴趣。即使您将tri_fusion(T, 0, size - 1); 更改为qsort(...)...

    再见,

    弗朗西斯

    【讨论】:

    • 非常感谢您的解释和有用的提示!作为一个初学者,我发现关于 MPI 的文档非常缺乏 - 确实有很多参考资料,但大多数材料的解释都很糟糕。我什至没有想到,根进程也将数据发送给自己(事后看来这是完全合理的)。可悲的是,我不能为你的贡献 +rep 你,因为我太新了:(
    • @SidCasey:不客气!没问题:你接受了我的回答,我不能要求更多!
    • 我不是 Deino,但我确实喜欢他关于 MPI 的参考页面。你可以试试看。 mpi.deino.net/mpi_functions/MPI_Scatter.html
    猜你喜欢
    • 2021-04-17
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    相关资源
    最近更新 更多