2016-08-11 7 views
1

Im 2行の列と可変nrの行からなるasciiファイルを読み込みます。読み取りはプロセッサ0によって行われ、データはMPI_Bcast(...)を使用して分散されます。データを含む1次元のバッファ配列を作成しなければならず、2次元を直接ブロードキャストする方法が見つからないため、他のすべてのprocsに送信されます。データ。 配列arrの割り当てに問題があります。データを印刷しようとすると、最初の3行が印刷され、次にセグメント化エラーが発生します。ほとんどの場合、いくつかの間違いがあります。Cでmpiを使用する関数で2d配列を割り当てて塗りつぶします

私はできるだけ単純な例を作ることを実際に試みました。 私のコード:

//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'の両方を持つ理由はないようですね。また、同じファイルを2回読んでいる場合は、それを閉じて再度開いてみてください。 – RastaJedi

+0

'arr'を直接読んでいるのであれば、なぜ' buf'を持っているのか分かりません。また、あなたのループは最下位にあります(あなたの関数の早い段階で返ってきたので決して到達しないので、このループとフリーには決して到達しません)、おそらく '(* arr)[i] [j]' '* arr [i] [j]'。また、FYIだけで、 '(* rowsout)'の前後のかっこは必要ありません。また、 'do'ループは' ch'が 'EOF'に等しいときだけ終了するので、' '\ n'''と後で同じでないかどうかをテストするのは無意味で、 'number_of_lines'を1つだけ余分にして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 

Iここにあなたのコードの修正版(マイナスMPIのもの)があります間違いがあなたのfscanf()行にあると考えてください。 fscanf()は、"%lf"を使用しているときにdouble *が必要ですが、代わりにarr[i][j]を渡しています。それには2つの問題があります。arrは実際に2次元配列へのポインタなので、最初にそれを尊重する必要があります((*arr)doubleのアドレスが必要なため、&&(*arr)[i][j]を使用する必要があります。

+0

ありがとうございました。そのシリアルコードですが、私はそれを並列にしようとします。 –

+0

ええ、私はそのMPIのことについてはわかりませんが、少なくともあなたのセグメンテーションを修正します(または、とにかく、あなたがしていたように 'arr'を読み込もうとするsegfaultsがあったからです)。'fopen()'とおそらくあなたのallocのエラーチェックも忘れないでください。 – RastaJedi

+0

お世話になりました...本当にありがとうございます。可能な限り普遍的なコードを作成したい場合は、実際には複雑になっています^^。私もsizeof ** arrとsizeof *** arrを使うことができるのか分かりませんでした....本当にスマートです –

関連する問題