2014-01-12 32 views
0

我刚开始使用MPI编程,并决定使用OpenMPI进行简单的分布式qsort。要分发的我,我要排序我试图使用MPI_Scatterv阵列的部分,但是下面的代码段错误:MPI_Scatterv segfault

#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?我在从worker代码中分配输入缓冲区时做错了什么?

回答

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应在码的末尾被释放。

是你想要做什么?祝你好运qsort!我认为你不是第一个使用MPI对整数进行排序的人。请参阅parallel sort using mpi。您在0处理函数上生成随机数然后分散它们的方法是正确的选择。我想你会被他的TD_Trier()通信功能捕获。即使您更改tri_fusion(T, 0, size - 1);qsort(...) ......

再见,

弗朗西斯

+0

非常感谢你的解释和有用的提示!作为一名初学者,我发现有关MPI的文档很缺乏 - 确定有很多参考文献,但大多数材料都很差解释。我甚至没有想到,根进程也会向自己发送数据(事后看来这是非常有意义的)。可悲的是我不能+代表你的贡献,因为我太新了:( –

+0

@SidCasey:不客气!没问题:你接受了我的答案,我不能要求更多! – francis

+1

我不是Deino,但我确实喜欢他关于MPI的参考页面,你可以试试看看它。http://mpi.deino.net/mpi_functions/MPI_Scatter.html –