MPI中的图像处理

时间:2018-08-02 16:03:00

标签: mpi

这是我尝试在MPI中编码经典的平滑像素平均算法。我几乎可以正常工作,但是光晕交换发生了一些奇怪的事情,可以看到边缘的线条。我似乎找不到该错误。我可以正确交换光晕吗?我应该收集最终阵列的哪一部分?

https://pastebin.com/4rtFnSJ5

int next = rank + 1;
int prev = rank - 1;

if (next >= size) {
  next = MPI_PROC_NULL;
}

if (prev < 0) {
  prev = MPI_PROC_NULL;
}

int rows = y / px;
int cols = x;
int d = 1;

for (int iter = 0; iter < TotalIter; iter++) {
  for (int i = 0; i < rows + 2; i++)
    for (int j = 0; j < cols + 2; j++)
      for (int k = 0; k < rgb; k++)
        new[i][j * rgb + k] = 0;

  for (int i = 1; i < rows + 1; i++) {

    int iMin = -min(d, i - 1);
    int iMax = min(d, (rows + 1 - i - 1));

    for (int j = 1; j < cols + 1; j++) {
      int jMin = -min(d, j - 1);
      int iMax = min(d, (cols + 1 - j - 1));

      int counter = 0;

      for (int p = iMin; p <= iMax; p++)
        for (int q = jMin; q <= jMax; q++) {
          counter = counter + 1;
          for (int k = 0; k < rgb; k++) {
            new[i][j * rgb + k] += old[i + p][(j + q) * rgb + k];
          }
        }

      for (int k = 0; k < rgb; k++) {
        new[i][j * rgb + k] -= old[i][j * rgb + k];
        new[i][j * rgb + k] /= (counter - 1);
      }
    }
  }

  for (int i = 2; i < rows; i++)
    for (int j = 2; j < cols; j++)
      for (int k = 0; k < rgb; k++) {
        old[i][j * rgb + k] = new[i][j * rgb + k];
      }

  MPI_Sendrecv(&old[rows][1], cols * rgb, MPI_INT, next, 1, &old[0][1],
               cols * rgb, MPI_INT, prev, 1, MPI_COMM_WORLD, &status);

  MPI_Sendrecv(&old[1][1], cols * rgb, MPI_INT, prev, 2, &old[rows + 1][1],
               cols * rgb, MPI_INT, next, 2, MPI_COMM_WORLD, &status);
}

 for (int i = 1; i< rows+1; i++)
    for (int j = 1; j< cols+1; j++)
        for (int k = 0; k< rgb; k++) {
           buf[i-1][(j-1)*rgb+k] =  old[i][j*rgb+k] ;
         }

MPI_Gather(&buf[0][0], rows *cols *rgb, MPI_INT, &Finalbuffer[0][0],
           rows *cols *rgb, MPI_INT, 0, MPI_COMM_WORLD);

在8个MPI进程上运行时,输出看起来像这样。我可以清楚地看到分隔线。因此,我认为我没有适当地进行光环交换。 enter image description here

1 个答案:

答案 0 :(得分:2)

好的,所以这里有很多问题。

首先,您的代码只能与d = 1一起使用,因为您只交换深度为1的光环。如果要处理距离为d的邻居,则需要交换深度为d的光环。

第二,在第一次扫描阵列之后进行第一次光环交换 ,这样您就可以在迭代1上读取垃圾光环数据-您需要进行光环交换,然后才能开始处理阵列。

第三,当您将新副本复制回旧版本时,您将从索引2开始:您需要包括从1到行和从1到lcols的所有像素。

最后,您的Imin,Imax等逻辑似乎是错误的。您不想在并行程序中截断边缘的范围-您需要移开边缘以获取光晕数据。我只设置了Imin = -d,Imax = d等。

通过这些修复,代码似乎可以正常运行,即没有明显的光晕效果,但是在不同数量的进程上仍然可以得到不同的结果。

PS我也很高兴看到您使用了我自己的MPI示例之一http://www.archer.ac.uk/training/course-material/2018/07/intro-epcc/exercises/cfd.tar.gz中的“ arraymalloc2d”代码。我很高兴看到这些培训规范对人们有用!