MPI 中的鬼细胞交换模式

Ghost cell exchange pattern in MPI

本文关键字:交换 模式 细胞 MPI      更新时间:2023-10-16

我正在使用MPI实现分布式图像(灰度(卷积。我现有的模式是在根进程中将图像读取为一维扁平数组,然后将它们分散到所有进程(行分解(,然后在根进程中执行MPI_Gather,然后将图像再次写出为一维展平数组。显然,这并没有给出预期的结果,因为使用图像卷积,情况在边界上变得棘手。

因此,为了改进上述模式,我想实现所谓的ghost cell exchange模式,其中进程在伪代码中交换ghost rows.行:

if (rank == 0) {
    src = null
    dest = rank + 1
}
if (rank == size - 1) {
    src = rank - 1
    dest = null
} else {
   src = rank - 1
   dest = rank + 1
}
MPI_SendRecv(&sendbuf[offset], slen, dest..
             &recvbuf[offset], rlen, src);

如何为每个进程上的"虚影行"分配内存?我应该预先分配内存然后分散吗?我不想采用"自定义数据类型"解决方案,因为对于我正在考虑的问题范围来说,这是一个矫枉过正。

理想情况下,幽灵细胞应该与正常细胞属于同一内存块。这样,您可以保持寻址方案简单。在该方案中,图像由完整行的倍数分布,使用 MPI_ScatterMPI_Gather 。在非边界排名中,您为两个额外的虚影行分配了足够的内存:

height = total_hight / ranks;
std::vector<float> data(width * (height + 2));
float* image = &data[width];
float* ghost_north = &data[0]
float* ghost_south = &data[width * (height + 1)]
float* inner_north = image;
float* inner_south = &image[width * (height - 1)]
MPI_Scatter(root_image, width * height, MPI_FLOAT,
            image, width * height, MPI_FLOAT, ...);
...
iterations {
    MPI_SendRecv(inner_north, width, MPI_FLOAT, north, tag,
                 ghost_north, width, MPI_FLOAT, north, tag, ...)
    MPI_SendRecv(inner_south, width, MPI_FLOAT, south, tag,
                 ghost_south, width, MPI_FLOAT, south, tag, ...)
   ... compute ...
}
MPI_Gather(image, width * height, MPI_FLOAT,
           root_image, width * height, MPI_FLOAT, ...);

此伪代码不考虑特殊边界情况。

简单一维分割的问题在于通信成本和额外的光晕数据不是最佳的。特别是对于较小的图像和较多的参与等级。

这是Rolf Rabenseifner关于MPI的数据分解和halo通信方法的一个很好的例子。他还解释了如何改进沟通方法。对于 2D 分解,您将需要派生的 MPI 数据类型来进行初始通信和垂直边界。