2011-01-15 12 views
2

Ich habe versucht, eine Matrix von Zeile zu allen Prozessoren Streuung, aber es führte zu einem Segmentierungsfehler .. Ich weiß nicht, was ich falsch mache .. Hier ist mein CodeScatter eine Matrix - MPI

 if(rank == 0) { 
        A_row = 10; 
        A_col = 10; 
        /* calculate the strip size */ 
        strip_size = A_row/size; 

        /* genarate Matrix A */ 
        A = (double **)malloc(sizeof(double*) * 10); 
        int k = 0; 
        for(i = 0; i < 10; i++) { 
          A[i] = (double*)malloc(sizeof(double) * 10); 
          for(j = 0; j < 10; j++) { 
            A[i][j] = k; 
            k++; 
            printf("%lf ", A[i][j]); 
          } 
          printf("\n"); 
        } 
      } 

      /* Broadcasting the row, column size of Matrix A as well as strip size and Matrix B*/ 
      MPI_Bcast(&A_row, 1, MPI_INT, 0, MPI_COMM_WORLD); 
      MPI_Bcast(&A_col, 1, MPI_INT, 0, MPI_COMM_WORLD); 
      MPI_Bcast(&strip_size, 1, MPI_INT, 0, MPI_COMM_WORLD); 

      /* defining a datatype for sub-matrix */ 
      MPI_Type_vector(strip_size, A_col, A_col, MPI_DOUBLE, &strip); 
      MPI_Type_commit(&strip); 

      strip_A = (double **)malloc(sizeof(double*)*strip_size); 
      for(i= 0; i< strip_size; i++) { 
        strip_A[i] = (double*)malloc(sizeof(double)*A_col); 
      } 

      MPI_Scatter(&A[0][0], 1, strip, &strip_A[0][0], 1, strip, 0, MPI_COMM_WORLD); 

      for(i = 0; i < strip_size; i++) { 
        if(i == 0) { 
          printf("rank = %d\n", rank); 
        } 
        for(j = 0; j < A_col; j++) { 
          printf("%lf ", strip_A[i][j]); 
        } 
        printf("\n"); 
      } 

Kann mir jemand sagen, was falsch ist ...

hier mein Fehler ist, wenn ich

mpirun -np 2 ./a.out 



0.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 
10.000000 11.000000 12.000000 13.000000 14.000000 15.000000 16.000000 17.000000 18.000000 19.000000 
20.000000 21.000000 22.000000 23.000000 24.000000 25.000000 26.000000 27.000000 28.000000 29.000000 
30.000000 31.000000 32.000000 33.000000 34.000000 35.000000 36.000000 37.000000 38.000000 39.000000 
40.000000 41.000000 42.000000 43.000000 44.000000 45.000000 46.000000 47.000000 48.000000 49.000000 
50.000000 51.000000 52.000000 53.000000 54.000000 55.000000 56.000000 57.000000 58.000000 59.000000 
60.000000 61.000000 62.000000 63.000000 64.000000 65.000000 66.000000 67.000000 68.000000 69.000000 
70.000000 71.000000 72.000000 73.000000 74.000000 75.000000 76.000000 77.000000 78.000000 79.000000 
80.000000 81.000000 82.000000 83.000000 84.000000 85.000000 86.000000 87.000000 88.000000 89.000000 
90.000000 91.000000 92.000000 93.000000 94.000000 95.000000 96.000000 97.000000 98.000000 99.000000 

rank = 1 
42.000000 43.000000 44.000000 45.000000 46.000000 47.000000 48.000000 49.000000 0.000000 0.000000 
52.000000 53.000000 54.000000 55.000000 56.000000 57.000000 58.000000 59.000000 0.000000 0.000000 
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
[seismicmstm:07338] *** Process received signal *** [seismicmstm:07338] Signal: 
Segmentation fault (11) 
[seismicmstm:07338] Signal code: 
(128) [seismicmstm:07338] Failing at 
address: (nil) 
-------------------------------------------------------------------------- mpirun noticed that process rank 1 with PID 7338 on node seismicmstm.cluster exited on signal 11 (Segmentation fault). 
-------------------------------------------------------------------------- 
+0

Für den Anfang, die Linie, die Sie die segfault bekommen Sie? – suszterpatt

Antwort

6

Es gibt ein paar Dinge hier los. Die gute Nachricht ist, dass die schwierigsten Dinge - die Erstellung des Datentyps mpi und die Grundstruktur des Aufrufs MPI_Scatter - korrekt sind.

Das erste Problem ist, dass die MPI_Scatter-Linie & (A [0] [0]) verwendet - aber in allen außer Rang 0 haben Sie nicht festgelegt, dass A auf etwas zeigt! Also dereferenzieren Sie einen zufälligen Zeiger zweimal, und da ist Ihr Segfault.

Ein subtileres Problem, wie von Suszterpatt vorgeschlagen, ist, dass es keine Garantie gibt, dass Ihre Zeilen von zugeordnetem Speicher zusammenhängend sind, so dass Ihre Streufunktion möglicherweise nicht funktioniert, selbst wenn Sie die oben genannten beheben. Sie versuchen, strip_size * A_col doubles von irgendwo in A nach strip_A zu senden, aber strip_A darf nicht aus so vielen doppelten zusammenhängen - es könnte A_col verdoppelt werden, und dann ein Padding, dann A_col verdoppelt - oder in der Tat, die verschiedenen Zeilen könnten verstreut sein über die ganze Erinnerung. Die drei Arten des Fixierens sind in der Reihenfolge der Leichtigkeit (IMHO): (a) die Daten im Speicher zusammenhängend zu machen, indem das gesamte Array erzeugt wird und dann die zweidimensionalen C-Arrays erzeugt werden, um auf die richtigen Stellen zu zeigen; (b) um jeweils nur eine Zeile zu senden; oder (c) um einen MPI-Datentyp zu erzeugen, der tatsächlich widerspiegelt, wie Ihre Daten (vielleicht zufällig) im Speicher abgebildet werden.

Ein Ansatz (a), der (nach Größe für A_row gleichmäßig aufgeteilt, sowieso) scheint zu funktionieren sieht aus wie folgt:

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

int main(int argc, char** argv) { 
    int rank, size; 
    int strip_size, A_row, A_col; 
    double **A, **strip_A, *Adata, *stripdata; 
    MPI_Datatype strip; 
    int i,j; 

    MPI_Init(&argc,&argv) ; 

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

     if(rank == 0) { 
        A_row = 10; 
        A_col = 10; 
        /* calculate the strip size */ 
        strip_size = A_row/size; 

        /* genarate Matrix A */ 
        Adata = (double *)malloc(sizeof(double)*A_row*A_col); 
        A = (double **)malloc(sizeof(double*) * A_row); 
        for(i = 0; i < A_row; i++) { 
          A[i] = &(Adata[i*A_col]); 
        } 
        int k = 0; 
        for(i = 0; i < A_row; i++) { 
          for(j = 0; j < A_col; j++) { 
            A[i][j] = k; 
            k++; 
          } 
        } 
      } 

      /* Broadcasting the row, column size of Matrix A as well as strip size and Matrix B*/ 
      MPI_Bcast(&A_row, 1, MPI_INT, 0, MPI_COMM_WORLD); 
      MPI_Bcast(&A_col, 1, MPI_INT, 0, MPI_COMM_WORLD); 
      MPI_Bcast(&strip_size, 1, MPI_INT, 0, MPI_COMM_WORLD); 

      /* defining a datatype for sub-matrix */ 
      MPI_Type_vector(strip_size, A_col, A_col, MPI_DOUBLE, &strip); 
      MPI_Type_commit(&strip); 

      stripdata = (double *)malloc(sizeof(double)*strip_size*A_col); 
      strip_A = (double **)malloc(sizeof(double*)*strip_size); 
      for(i= 0; i< strip_size; i++) { 
        strip_A[i] = &(stripdata[i*A_col]); 
      } 

      MPI_Scatter(Adata, 1, strip, &(strip_A[0][0]), 1, strip, 0, MPI_COMM_WORLD); 
      //MPI_Scatter(Adata, A_col*strip_size, MPI_DOUBLE, &(strip_A[0][0]), A_col*strip_size, MPI_DOUBLE, 0, MPI_COMM_WORLD); 

      for(i = 0; i < strip_size; i++) { 
        if(i == 0) { 
          printf("rank = %d\n", rank); 
        } 
        for(j = 0; j < A_col; j++) { 
          printf("%lf ", strip_A[i][j]); 
        } 
        printf("\n"); 
      } 

    MPI_Type_free(&strip); 
    free(strip_A); 
    free(stripdata); 
    free(Adata); 
    free(A); 
    return 0; 
} 
+1

Ich denke, dass der Code einen Segmentierungsfehler in den letzten Zeilen haben wird, weil jeder Prozess oder Knoten versuchen wird, Speicher von der ursprünglichen Matrix zu befreien. Ich kann schreiben, wenn (Rang == 0) {frei (Adata); befreie ein);} –

1

betreibe ich denke, dass letztlich, was Sie falsch machen, ist Ihre Matrix als ein Array von Arrays zu speichern. Ich denke, Sie werden feststellen, dass die Dinge viel leichter werden, wenn Sie sie in einem einzigen Array speichern (in der Reihenfolge Reihenfolge der Zeilen oder Spalten, je nachdem, was Ihnen gefällt).

+0

Also, kann ich Matrix nicht als Array von Arrays streuen ... Wird es nicht möglich sein, es zu implementieren .... – veda

+0

Nur wenn Sie sicherstellen können, dass die Daten zusammenhängend im Speicher sind, da es eine Voraussetzung für ist Streuen. – suszterpatt

+1

..und nicht nur zum streuen! Beim Erstellen des Vektortyps deklarieren Sie, dass der Typ aus A_cols besteht * strip_size zusammenhängende doubles (strip_size Blöcke von A_cols doubles, wobei jeder Block durch A_cols doubles getrennt ist). Jede Kommunikation - send, recv, allreduce, was auch immer - unter Verwendung dieses Typs erfordert zusammenhängende Daten. –