2016-10-18 2 views
0

Zunächst einmal habe ich this code als Referenz verwendet, die die Verwendung von MPI_Gather ohne MPI_Scatter als das ist, was ich hier erreichen möchte. Ich arbeite schon lange daran und kann das Problem einfach nicht lösen. Dieser Sobel-Kantenerkennungsalgorithmus verstärkt die Umrisse von Objekten innerhalb von Bildern.MPI Sammeln nur sammeln von Root-Prozess

Ich werde meinen Code unten posten, da es nicht zu viel gibt, aber ich gebe zuerst eine schnelle Code-Beschreibung.

Ich versuche, ein sequenzielles Programm in ein paralleles Programm zu konvertieren. Also ist der ganze Nicht-MPI-Code korrekt.

So kann es nur einen Fehler mit meinem Code MPI irgendwo geben.

int main(int argc, char **argv) { 

    FILE *inFile, *oFile; 
    int grayImage[N][N], edgeImage[N][N]; 
    char type[2]; 
    int w, h, max; 
    int r, g, b, y, x, i, j, sum, sumx, sumy; 
    int tid; 

    int GX[3][3], GY[3][3]; 
    double elapsed_time; 
    struct timeval tv1, tv2; 
    int error = 0; 
    char buffer[BUFSIZ]; 
    int rank, NP; 

    // Code lies here for reading from the image file and storing into the grayImage array. 
    // This works so I saw no reason to include it 

    /* 3x3 Sobel masks. */ 
    GX[0][0] = -1; GX[0][1] = 0; GX[0][2] = 1; 
    GX[1][0] = -2; GX[1][1] = 0; GX[1][2] = 2; 
    GX[2][0] = -1; GX[2][1] = 0; GX[2][2] = 1; 

    GY[0][0] = 1; GY[0][1] = 2; GY[0][2] = 1; 
    GY[1][0] = 0; GY[1][1] = 0; GY[1][2] = 0; 
    GY[2][0] = -1; GY[2][1] = -2; GY[2][2] = -1; 



    MPI_Init(NULL, NULL); 

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

    // This calculates the block size.MPI 
    // On 4 processors the block size for a 100x100 image would be 25x100 each 

    int blksz = (int)ceil((double)N/NP); 

    // This creates a local array for each processor, soon to be gathered 

    int tempEdge[blksz][N]; 

    // this line shows it's working correctly 

    printf("processor %d, width: %d, height: %d, blksz: %d, begin: %d, end: %d\n", rank, w, h, blksz, rank*blksz, (rank+1)*blksz); 

    for(x=rank*blksz; x < (rank+1)*blksz && x<h; x++){ 

     // Any code in this loop can be ignored as it works correctly. 

     for(y=0; y < w; ++y){ 

      sumx = 0; 
      sumy = 0; 
      // handle image boundaries 
      if(x==0 || x==(h-1) || y==0 || y==(w-1)) 
       sum = 0; 
      else{ 
       //x gradient approx 
       for(i=-1; i<=1; i++) { 
        for(j=-1; j<=1; j++){ 
         sumx += (grayImage[x+i][y+j] * GX[i+1][j+1]); 
        } 
       } 
       //y gradient approx 
       for(i=-1; i<=1; i++) { 
        for(j=-1; j<=1; j++){ 
         sumy += (grayImage[x+i][y+j] * GY[i+1][j+1]); 
        } 
       } 
       //gradient magnitude approx 
       sum = (abs(sumx) + abs(sumy)); 
      } 
      tempEdge[x][y] = clamp(sum); 
     } 
    } 

    // Here is the line I am guessing is causing the problem 

    MPI_Gather(&tempEdge, w*blksz, MPI_INT, 
       &edgeImage, w*blksz, MPI_INT, 0, 
       MPI_COMM_WORLD); 


    // Finally, I output edgeImage to a file here. 

    if(rank==0){ 

     // output edgeImage to File 

    } 

    MPI_Finalize(); 

    return 0;  
} 

Das Eingangsbild ich verwende, ist dies:

enter image description here

Aber der Ausgang nur geben diese:

enter image description here

Wie Sie es sehen können, ist nur die oberes Viertel (N/4) oder blksz des Bildes.

Dies würde bedeuten, dass MPI_Gather nur von Prozess mit Rang 0 sammelt?

Ich habe so viel Zeit damit verbracht, jede Hilfe würde sehr geschätzt werden!

Antwort

2

Machen Sie MPI Collectives nicht verantwortlich für Fehler im Rest Ihres Codes. Es ist wirklich ein Wunder, dass Ihr Code zerbrochene Bilder ohne Segmentierung erzeugt. Werfen Sie einen Blick auf diesen Teil:

int tempEdge[blksz][N]; 
      ~~~~~ 

for(x = rank*blksz; x < (rank+1)*blksz && x<h; x++){ 
     ~~~~~~~~~~ 
    for(y = 0; y < w; ++y){ 
     ... 
     tempEdge[x][y] = clamp(sum); (1) 
       ~ 
    } 
} 

Für jeden Rang> 0 schreibt der Code über das Ende des Arrays. Fixieren Sie die Anweisung an (1) zu lesen:

tempEdge[x - rank*blksz][y] = clamp(sum); 

Entfernen Sie auch die & s im MPI_Gather Aufruf:

MPI_Gather(tempEdge, w*blksz, MPI_INT, 
      edgeImage, w*blksz, MPI_INT, 0, 
      MPI_COMM_WORLD); 

Es wird auch mit & arbeiten, aber das ist technisch nicht korrekt. Wenn Sie darauf bestehen, die -Adresse des Operators zu verwenden, verwenden Sie stattdessen &tempEdge[0][0] und &edgeImage[0][0].

+0

Ich kann wirklich nicht glauben, dass ich das verpasst habe! Jetzt fühle ich mich dumm, dies auf SO zu veröffentlichen. Vielen Dank für den ganzen Code! –

+0

Ich weiß, Debugging MPI-Code ist schwer, wie man die Anzahl der verwendbaren parallelen Debugger an den Fingern einer Hand zählen kann und die meisten von ihnen sind kommerziell. –