2016-05-14 106 views
0

我有一个动态二维数组,它是在连续的内存空间中分配的,但是如果我试图将这个数组分散到两个使用MPI_Scatter的MPI进程中将会导致分段错误,粘贴在这里:MPI_Scatter动态二维数组行导致分段错误

dynamic_2d_array.h

#ifndef _DYNAMIC_2D_ARRAY_H_ 
#define _DYNAMIC_2D_ARRAY_H_ 

#include <stdio.h> 
#include <stdlib.h> 

//typedef double real; 
typedef float real; 

real **allocate_dynamic_2d_array(int nrows, int ncols); 
void free_dynamic_2d_array(real** array_dynamic); 
void print_matrix(real** array_dynamic, int nrows, int ncols, char* fmt_string); 

real** allocate_dynamic_2d_array(int nrows, int ncols) { 
    /* here is the method to correct the non-contiguous memory problem */ 
    int i; 
    real** array_dynamic=(real**)malloc(nrows*sizeof(real*)); 
    real* data=(real*)malloc(nrows*ncols*sizeof(real)); 
    for (i=0; i<nrows; i++){ 
     array_dynamic[i]=&(data[ncols*i]); 
    } 
    return array_dynamic; 
} 

void free_dynamic_2d_array(real** array_dynamic){ 
    free((void*)array_dynamic[0]); 
    free((void*)array_dynamic); 
} 

void print_matrix(real** array_dynamic, int nrows, int ncols, char* fmt_string) { 
//void print_matrix(real array_dynamic[][4], int nrows, int ncols, char* fmt_string) { 
    int i,j; 
    for (i = 0; i < nrows; i++){ 
     for (j = 0; j < ncols; j++){ 
      printf(fmt_string, array_dynamic[i][j]); 
     } 
     printf("\n"); 
    } 
} 

#endif // #ifndef _DYNAMIC_2D_ARRAY_H_ 

这里是scatter_mat.h:

#include <stdio.h> 
#include <stdlib.h> 
#include "mpi.h" 
#include "dynamic_2d_array.h" 

int main(int argc, char ** argv) 
{ 
    MPI_Init(&argc, &argv); 
    int rank, psize, root = 0; 
    int i,j; 
    int ncols; 
    int M=48,N=3; 
    real *sub_mat; 
    real **A; 

    MPI_Comm_size(MPI_COMM_WORLD, &psize); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    if (rank==0) { 
     A = allocate_dynamic_2d_array(M,N);   
     printf("before scatter:\n"); 
     int idx=0; 
     for (i=0;i<M;i++){ 
      for (j=0;j<N;j++) { 
       A[i][j]=idx++; 
       printf("%4.1f\t",A[i][j]); 
      } 
      printf("\n"); 
     } 
    } 

    ncols = M/psize; 
    sub_mat = (real*)malloc(N*ncols*sizeof(real)); 

    MPI_Scatter(&(A[0][0]),N*ncols,MPI_FLOAT,sub_mat,N*ncols,MPI_FLOAT,root,MPI_COMM_WORLD); 

    for (i=0;i<ncols*N;i++) 
     printf("%3.1f\t",sub_mat[i]); 
    printf("\n"); 

    if (rank==0) { 
     free_dynamic_2d_array(A); 
    } 

    free(sub_mat); 
    MPI_Finalize(); 
    return 0; 
} 

如果我编译使用mpicc一个nd使用mpirun -np 2运行它,它会导致rank 1的分段错误,更让我困惑的是它使用调试模式(mpicc -g)很好,但是在释放模式下崩溃,我想必须有一些内存访问问题,但我无法弄清楚,有没有人可以提供一些建议?

下面是MPI编译器的信息:

$ mpiexec --version 
mpiexec (OpenRTE) 1.6.2 

Report bugs to http://www.open-mpi.org/community/help/ 
$ mpicc -show 
icc -I/usr/local/packages/openmpi/1.6.2/Intel-13.0.0/include -L/usr/local/packages/openmpi/1.6.2/Intel-13.0.0/lib -lmpi -ldl -lm -Wl,--export-dynamic -lrt -lnsl -libverbs -libumad -lpthread -lutil 

非常感谢!

+0

昨天晚上我发现它似乎MPI有一些问题驱散动态二维数组指针,所以目前的解决方法是在开始时通过定义一个“float * sendp;”来使用另一个float *指针指向A然后在'A = allocate_dynamic_2d_array(M,N);'后面添加'sendp =&(A [0] [0])',然后用MPI_Scatter中的sendp替换'&(A [0] [0])'至少不会返回分段错误。 –

回答

1

问题是,您在所有等级中取消&(A[0][0]),但它仅在根级别中分配。将NULL作为第一个参数传递到MPI_Scatter除了在根目录之外的所有等级中。

您还应该将ncols重命名为nrows(语义上)。

+0

感谢您的回答,但它似乎不是原因,实际上我已经尝试在if(rank == 0)之前添加'A = NULL',这仍然会导致分段错误。在MPI_Scatter中,除根之外的所有A指针都被忽略,对吗? –

+0

另外,Scatter是一个集体操作,我们不能这样做:'if(rank == 0)MPI_Scatter(xxx)',你如何做出判断? –

+0

这是行不通的? 'MPI_Scatter(rank == root?&(A [0] [0]):NULL,...)' – gudok