当我尝试发送2D整数数组时,为什么MPI_Send会阻塞?

瓦伦丁·梅西耶(Valentin Mercier)

我正在尝试使用mpi执行分形图片并行计算。我将程序分为4部分:

  1. 平衡每个等级的行数
  2. 对行的每一行属性进行计算
  3. 发送行数和行数到等级0
  4. 处理等级为0的数据(对于测试,只需打印int)

第1步和第2步正在工作,但是当我尝试将行发送到第0级时,程序正在停止并阻塞。我知道MPI_Send可以阻止bu,在这里没有理由。

这是第2步:

步骤1 :

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

/* Include the MPI library for function calls */
#include <mpi.h>

/* Define tags for each MPI_Send()/MPI_Recv() pair so distinct messages can be
 * sent */
#define OTHER_N_ROWS_TAG 0
#define OTHER_PIXELS_TAG 1

int main(int argc, char **argv) {
  const int nRows = 513;
  const int nCols = 513;
  const int middleRow = 0.5 * (nRows - 1);
  const int middleCol = 0.5 * (nCols - 1);
  const double step = 0.00625;
  const int depth = 100;
  int pixels[nRows][nCols];
  int row;
  int col;
  double xCoord;
  double yCoord;
  int i;
  double x;
  double y;
  double tmp;
  int myRank;
  int nRanks;
  int evenSplit;
  int nRanksWith1Extra;
  int myRow0;
  int myNRows;
  int rank;
  int otherNRows;
  int otherPixels[nRows][nCols];

  /* Each rank sets up MPI */
  MPI_Init(&argc, &argv);

  /* Each rank determines its ID and the total number of ranks */
  MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
  MPI_Comm_size(MPI_COMM_WORLD, &nRanks);
  printf("My rank is %d \n",myRank);
  evenSplit = nRows / nRanks;
  nRanksWith1Extra = nRows % nRanks;

/*Each rank determine the number of rows that he will have to perform (well balanced)*/
  if (myRank < nRanksWith1Extra) {

    myNRows = evenSplit + 1;
    myRow0 = myRank * (evenSplit + 1);
  }
  else {
    myNRows = evenSplit;
    myRow0 = (nRanksWith1Extra * (evenSplit + 1)) +
      ((myRank - nRanksWith1Extra) * evenSplit);
  }
/*__________________________________________________________________________________*/

第2步 :

/*_____________________PERFORM CALCUL ON EACH PIXEL________________________________ */
  for (row = myRow0; row < myRow0 + myNRows; row++) {

    /* Each rank loops over the columns in the given row */
    for (col = 0; col < nCols; col++) {

      /* Each rank sets the (x,y) coordinate for the pixel in the given row and 
       * column */
      xCoord = (col - middleCol) * step;
      yCoord = (row - middleRow) * step;

      /* Each rank calculates the number of iterations for the pixel in the
       * given row and column */
      i = 0;
      x = 0;
      y = 0;
      while ((x*x + y*y < 4) && (i < depth)) {
        tmp = x*x - y*y + xCoord;
        y = 2*x*y + yCoord;
        x = tmp;
        i++;
      }

      /* Each rank stores the number of iterations for the pixel in the given
       * row and column. The initial row is subtracted from the current row
       * so the array starts at 0 */
      pixels[row - myRow0][col] = i;
    }
      //printf("one row performed by %d \n",myRank);

  }
      printf("work done by %d \n",myRank);
/*_________________________________________________________________________________*/

第三步:

/*__________________________SEND DATA TO RANK 0____________________________________*/

  /* Each rank (including Rank 0) sends its number of rows to Rank 0 so Rank 0
   * can tell how many pixels to receive */
  MPI_Send(&myNRows, 1, MPI_INT, 0, OTHER_N_ROWS_TAG, MPI_COMM_WORLD);
  printf("test \n");
  /* Each rank (including Rank 0) sends its pixels array to Rank 0 so Rank 0
   * can print it */
  MPI_Send(&pixels, sizeof(int)*myNRows * nCols, MPI_BYTE, 0, OTHER_PIXELS_TAG,
      MPI_COMM_WORLD);
  printf("enter ranking 0 \n");
/*_________________________________________________________________________________*/

第四步:

/*________________________TREAT EACH ROW IN RANK 0_________________________________*/
  /* Only Rank 0 prints so the output is in order */
  if (myRank == 0) {

    /* Rank 0 loops over each rank so it can receive that rank's messages */
    for (rank = 0; rank < nRanks; rank++){

      /* Rank 0 receives the number of rows from the given rank so it knows how
       * many pixels to receive in the next message */
      MPI_Recv(&otherNRows, 1, MPI_INT, rank, OTHER_N_ROWS_TAG,
      MPI_COMM_WORLD, MPI_STATUS_IGNORE);

      /* Rank 0 receives the pixels array from each of the other ranks
       * (including itself) so it can print the number of iterations for each
       * pixel */
      MPI_Recv(&otherPixels, otherNRows * nCols, MPI_INT, rank,
          OTHER_PIXELS_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

      /* Rank 0 loops over the rows for the given rank */
      for (row = 0; row < otherNRows; row++) {

        /* Rank 0 loops over the columns within the given row */
        for (col = 0; col < nCols; col++) {

          /* Rank 0 prints the value of the pixel at the given row and column
           * followed by a comma */
          printf("%d,", otherPixels[row][col]);
        }

        /* In between rows, Rank 0 prints a newline character */
        printf("\n");
      }
    }
  }

  /* All processes clean up the MPI environment */
  MPI_Finalize();

  return 0;
}

我想了解它为什么会阻塞,您能解释一下吗?我是MPI的新用户,我不仅想拥有一个正在运行的程序,还想了解它。

先感谢您。

Zulan

MPI_Send通过定义的标准的一个阻塞操作。

请注意,阻塞表示:

只有安全地存储了消息数据和信封后,它才会返回,以便发送者可以自由地修改发送缓冲区。该消息可能直接复制到匹配的接收缓冲区中,或者可能被复制到临时系统缓冲区中。

试图让等级使用MPI_Send向自己发送消息MPI_Recv是一个僵局。

针对您的情况的惯用模式是使用适当的集体通信操作MPI_GatherMPI_Gatherv

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

当我尝试并行拟合多个模型时,为什么tensorflow / keras会阻塞?

为什么我们不能将2D整数数组初始化为指针?

当我尝试删除[]数组时,为什么我的程序会抛出SIGABRT?

c中的整数数组(例如int a []):为什么当我使用a [i]访问它们时返回错误的值?

为什么2D数组的行为就像1D指针数组而不是1D整数数组?

当我尝试从自定义数组中删除元素时,为什么Java会向我显示“越界”异常?

当我尝试写入2D数组时出现未处理的异常

当MPI_Send调用累积时,为什么MPI_Recv失败

通过MPI_Send发送一个int数组

当我尝试搜索时,为什么Chrome会将我发送到Google主页?

在2D数组上进行迭代时,为什么循环顺序会影响性能?

尝试映射2d数组时,为什么会得到“ u”的输出?

2D数组:当我将ptr声明为int ptr [4] [4]时,为什么ptr和* ptr相同?

为什么当我循环遍历List MapsArrays时,它会将相同的2d int数组写入文本文件?

当我尝试呈现此 .NET 视图时,为什么会获得此“InvalidOperationException”?

当我告诉Gradle运行Java 14时,为什么Gradle会尝试使用Java 8?

当我尝试拟合线性混合效应模型时,为什么statsmodels会引发IndedxError?

当我尝试转换为int时,ruby为什么会引发错误?

当我尝试从Firebase检索数据库信息时,SwiftUI为什么会显示错误?

当我尝试创建计数器时,为什么 thinkscript 会抛出这些问题?

当我尝试使用 Firebase 注销用户时,为什么 Redux 会抛出空错误?

当我将字符串数组和整数数组合并到合并数组中时,我想在合并数组时使用什么数据类型

为什么当我传递整数数据框以在R中应用函数时,变量被转换了?

为什么MPI_Send接受void *源?

为什么我的整数数组显示随机值?

为什么取消对整数数组的指针(在2d数组中)的返回(或衰减到)指向第一个元素的指针?

当我尝试在结构数组中提供值时,为什么我的程序停止了?

当我尝试打印封面数组时,为什么我的输出为空?

您可以使用MPI_Send和MPI_Recv发送数组中的数组吗?