简体   繁体   English

MPI仅从根进程收集

[英]MPI Gather only gathering from Root Process

First off, I've been using this code as a reference, which shows the use of MPI_Gather without MPI_Scatter as that is what I am trying to achieve here. 首先,我一直在使用此代码作为参考,它显示了在没有MPI_ScatterMPI_Gather下使用MPI_Gather MPI_Scatter因为这就是我在此处要实现的目标。 I've been working on this for a long time now and just can't figure out the issue. 我已经为此进行了很长时间的研究,只是无法弄清问题所在。 This sobel edge detection algorithm strengthens the outlines of objects inside images. 这种sobel边缘检测算法可增强图像内对象的轮廓。

I will post my code below, as there is not too much, but I'll give a quick code description first. 由于没有太多内容,我将在下面发布我的代码,但首先我将给出一个简短的代码描述。

I am trying to convert a sequential program into a parallel program. 我正在尝试将顺序程序转换为并行程序。 So all the non-MPI code is correct. 因此,所有非MPI代码都是正确的。

So there can only be a mistake with my MPI code somewhere. 因此,我的MPI代码在某处只能有一个错误。

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;    
}

The input image I am using is this: 我正在使用的输入图像是这样的:

在此处输入图片说明

But the output is only giving this: 但是输出仅给出以下内容:

在此处输入图片说明

As you can see it is only the top quarter (N/4), or blksz of the image. 如您所见,它只是图像的前四分之一(N / 4)或blksz

This would imply that MPI_Gather is only gathering from process with rank 0? 这意味着MPI_Gather仅从等级为0的进程中收集吗?

I've been spending so much time on this, any help would be hugely appreciated! 我已经花了很多时间在此上,任何帮助将不胜感激!

Do not blame MPI collectives for bugs in the rest of your code. 不要将其余代码中的错误归咎于MPI集体。 It is actually a miracle that your code produces broken images without segfaulting. 实际上,您的代码产生损坏的图像而没有段错误实际上是一个奇迹。 Just take a look at that part: 只需看一下那部分:

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)
               ~
   }
}

For any rank > 0 the code writes past the end of the array. 对于任何大于0的秩,代码将写入数组的末尾。 Fix the statement at (1) to read: 将语句(1)修改为:

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

Also, remove the & s in the MPI_Gather call: 另外,删除MPI_Gather调用中的&

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

It will work with & too, but that is technically incorrect. 它也可以与&一起使用,但这在技术上是不正确的。 If you insist on using the address-of operator, then use &tempEdge[0][0] and &edgeImage[0][0] instead. 如果您坚持使用地址运算符,请改用&tempEdge[0][0]&edgeImage[0][0]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM