2016-08-11 2 views
1

2 열과 변수 nr 행으로 구성된 ascii 파일을 읽으려고 시도합니다. 읽기는 프로세서 0에 의해 수행되고 데이터는 MPI_Bcast (...)를 사용하여 분산됩니다. 나는 2 차원 버퍼를 직접 브로드 캐스트하는 방법을 찾지 못했기 때문에 데이터를 포함하고 다른 모든 procs로 전송되는 1-dim 버퍼 배열을 만들어야했습니다. 데이터. 배열 arr 할당에 문제가 있습니다. 데이터를 인쇄하려고하면 처음 세 행이 인쇄 된 다음 세그먼트 오류가 발생합니다. 대부분 몇 가지 실수가있을 수 있습니다.C에서 mpi를 사용하는 함수에 2 차원 배열을 할당하고 채우기

가능한 한 간단하게 예제를 만들려고했습니다. 내 코드 : 당신이 짐작으로

//global variables 
... 
double **testarray; 
int  dim; 
... 
int main(int argc, char **argv){ 
    ... 
    ... 
    read_file("test.txt",&testarray,&dim); 
} 

int read_file(char* infilename,double ***arr,int *rowsout) 
{ 

    FILE* infile; 
    int i,j,ch,number_of_lines=0; 
    int rows=0;  
    //first count lines 
    if(myid==0)  //myid is processor id 
    { 
    infile = fopen(infilename, "r"); 
    do 
    { 
     ch = fgetc(infile); 
     if(ch == '\n') 
     number_of_lines++; 
    } while (ch != EOF); 
    if(ch != '\n' && number_of_lines != 0) 
     number_of_lines++; 
    //close file 
    fclose(infile); 
    rows=number_of_lines-1; 
    *rowsout=rows; 
    } 
    // every proc should know about length of file in order 
    //to be able to allocate memory 
    MPI_Bcast(rowsout,1,MPI_INT,0,MPI_COMM_WORLD); 

    //allocate memory 
    double *buf;  //1D-buffer for 2D-array 
    MPI_Alloc_mem((*rowsout)*2*sizeof(double), MPI_INFO_NULL, &buf); 
    MPI_Alloc_mem((*rowsout)*sizeof(double*), MPI_INFO_NULL,arr); 
    for (i = 0; i < (*rowsout); i++) { 
    MPI_Alloc_mem(2*sizeof(double),MPI_INFO_NULL,&arr[i]); 
    } 
    // Now read file on proc 0 
    if(myid==0) 
    { 
    infile=fopen(infilename,"r"); 
    for(i=0;i<rows;i++) 
    { 
     for(j=0;j<2;j++) 
     { 
     fscanf(infile,"%lf",arr[i][j]); 
     printf("arr[%d][%d]:%e\n",i,j,(*arr)[i][j]); 
     } 
    } 
    fclose(infile); 
    } 
    return 0; 

    //dont go further, error occurs before loop finishs 
    MPI_Bcast(buf,(rows)*2,MPI_DOUBLE,0,MPI_COMM_WORLD); 

    //now reconstruct array from buffer 
    for(i=0;i<(*rowsout);i++) 
    { 
    for(j=0;j<2;j++) 
    { 
     *arr[i][j]=buf[i*2+j]; 
    } 
    } 
    MPI_Free_mem(buf); 
    return 0; 
} 
+0

나는'arr'을 할당하는 것을 보았습니다. 그래서이 MPI가 무엇인지 모르겠지만 보통'malloc()'을 사용하면'free()'와 일치 할 필요가 있습니다. 모든 사람); 아마도'(* arr) [i] '를 모두 풀어 준 다음 마침내'* arr'을 해방해야 할 것입니다. 또한, C99 이상을 사용하지 않고 C89/M $에서 실행되지 않는다는 것을 알고 있다면, main()에서 명시 적으로'return 0;을해야합니다. 디버거를 사용하여이 단계를 밟아 보았습니까? 또한'rowsout'과'rows'를 모두 가질 이유가없는 것 같습니까? 또한 동일한 파일을 두 번 읽는다면 왜 파일을 닫고 다시 열어야합니까? – RastaJedi

+0

'arr'을 직접 읽는 중 왜'buf'를 가지고 있는지 모르겠습니다. 또한 맨 아래에있는 루프는 (함수에서 일찍 돌아 오기 때문에 결코 도달 할 수 없을뿐만 아니라이 루프와 프리에 도달하지 못했을뿐만 아니라)'(* arr) [i] [j]'가 있어야하고 그렇지 않습니다. '* arr [i] [j]'. 또한 단지 FYI,'(* rowsout)'주위의 괄호는 필요하지 않습니다. 또한'do' 루프는'ch'가'EOF'와 같을 때만 끝나기 때문에,''\ n'''과 같지 않다면 나중에 테스트하는 것은 무의미합니다. 그리고'number_of_lines'를 1을 빼기 위해 여분으로 만드는 것입니다 '* rowsout'은 무의미합니다. – RastaJedi

+0

그리고'* rowsout'을 직접 사용할 수 있기 때문에 실제로는 number_of_lines가 필요하지 않습니다. – RastaJedi

답변

1

당신은 당신의 arr 몇 가지 문제가 있습니다.

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

void read_file(char *filename, double ***arr, int *rowsout); 

int main(void) 
{ 
    double **testarray; 
    int dim; 

    read_file("test.txt", &testarray, &dim); 

    return 0; 
} 

void read_file(char *filename, double ***arr, int *rowsout) 
{ 
    FILE *infile; 
    int i, j, ch; 

    infile = fopen(filename, "r"); 

    do 
    { 
      ch = fgetc(infile); 
      if (ch == '\n') 
        ++*rowsout; 
    } while (ch != EOF); 
    rewind(infile); 

    *arr = malloc(sizeof **arr * *rowsout); 

    for (i = 0; i < *rowsout; ++i) 
      (*arr)[i] = malloc(sizeof ***arr * 2); 

    for (i = 0; i < *rowsout; ++i) 
    { 
      for (j = 0; j < 2; ++j) 
      { 
        fscanf(infile, "%lf", &(*arr)[i][j]); 
        printf("(*arr)[%d][%d]: %e\n", i, j, (*arr)[i][j]); 
      } 
    } 

    fclose(infile); 
    for (i = 0; i < *rowsout; ++i) 
      free((*arr)[i]); 
    free(*arr); 
} 

예 입력 : 있는 test.txt

0.01 0.02 
0.3 0.4 
5.0 6.0 

예 출력 :

(*arr)[0][0]: 1.000000e-02 
(*arr)[0][1]: 2.000000e-02 
(*arr)[1][0]: 3.000000e-01 
(*arr)[1][1]: 4.000000e-01 
(*arr)[2][0]: 5.000000e+00 
(*arr)[2][1]: 6.000000e+00 

나는 여기에 코드의 고정 된 버전 (마이너스 MPI 물건)입니다 실수가 귀하의 fscanf() 행과 함께 있다고 생각하십시오. fscanf()"%lf"을 사용할 때 double *을 원하지만 arr[i][j]을 전달하는 경우 두 가지가 있습니다. arr은 실제로 2 차원 배열에 대한 포인터이기 때문에 먼저이를 ((*arr)), 두 번째로 추론해야합니다 주소가 double이어야하므로 & : &(*arr)[i][j]을 사용해야합니다.

+0

고마워요. 직렬 코드지만 병렬화하려고 노력할 것입니다. –

+0

그래, 그 MPI 물건에 대해 잘 모르겠지만, 적어도 당신의 segfault를 수정 (또는 어쨌든, 왜냐하면 나는 당신에게'arr'을 읽으려는 segfaults가 있었기 때문에).fopen()과 아마도 alloc에 ​​대한 에러 검사도 잊지 마라. – RastaJedi

+0

노력해 주셔서 감사합니다 ... 정말 고맙습니다. 가능한 범용 코드를 만들고 싶을 때 정말 복잡해지고 있습니다 ^^. 또한 sizeof ** arr 및 sizeof *** arr을 사용할 수 있다는 것을 알지 못했습니다 .... 정말 똑똑합니다. –

관련 문제