为啥 MPI_SEND 在我的 for 循环中不起作用?如果明确说明它工作正常

Posted

技术标签:

【中文标题】为啥 MPI_SEND 在我的 for 循环中不起作用?如果明确说明它工作正常【英文标题】:Why doesn't MPI_SEND work within my for loop? It works fine if explicitly stated为什么 MPI_SEND 在我的 for 循环中不起作用?如果明确说明它工作正常 【发布时间】:2016-05-16 16:41:11 【问题描述】:

我正在尝试向 p-1 进程发送一个号码。进程 0 将此值发送给所有其他进程。我使用 MPI_SEND 命令来执行此操作。当我为 3 个进程明确写出 MPI_SEND 命令时,它工作正常。但是当我想把它放在一个循环中时,它会给我输出以及分段错误代码。这是我的代码:

#include <stdlib.h>
#include <mpi.h>
#include "a1.h"

//AUTHORS
//LAKSHAN SIVANANTHAN - 1150161
//RAZMIG PAPISSIAN - 1152517

int main(int argc, char** argv)

  RGB *image;
  int width, height, max;
  int windowLength = atoi(argv[3]);
  int my_rank, p, local_height, source, i;

  int dest;

  MPI_Status status;

  MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &p);
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

  int *processorRows;
  processorRows = (int*)malloc(sizeof(int)*(p+1));

  if (my_rank == 0) 

    printf("Process %d is reading...\n", my_rank);
    image = readPPM(argv[1], &width, &height, &max); 

    //calculate rows to each process

    for (i=0; i<p; i++) 

      processorRows[i] = height/p;

    

    for (i=0; i< height%p; i++)

      processorRows[i]++;
    

    for (dest=1; dest<p; dest++) 

      MPI_Send(processorRows + dest, 1, MPI_INT, dest, 0, MPI_COMM_WORLD);
      //MPI_Send(processorRows + 2, 1, MPI_INT, 2, 0, MPI_COMM_WORLD);
      //MPI_Send(processorRows + 3, 1, MPI_INT, 3, 0, MPI_COMM_WORLD);
    

  
  else 

    MPI_Recv(processorRows, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
    printf("I am Process %d and will run %d rows...\n", my_rank, *processorRows);

   

  //processImage(width, height, image, windowLength);
  //writePPM(argv[2], width, height, max, image);

  free(image);
  free(processorRows);

  MPI_Finalize();
  return(0);


如果我要删除 for 循环,将“dest”替换为 1,并取消注释其他 2 行 MPI_SEND,它在运行 mpirun -np 4 ./program 时完全正常

不知道这里发生了什么......

【问题讨论】:

【参考方案1】:

我不确定您要完成什么。但是,从声明中

进程 0 将此值发送给所有其他进程。

从代码的部分来看,我希望您从 Process-0 分散到所有其他 PE,而不是这种发送-接收循环技巧。

删除所有发送-接收对并删除循环,只需使用单个分散操作。这是 MPI_Scatter 操作的链接https://www.open-mpi.org/doc/v1.8/man3/MPI_Scatter.3.php。如果你不确定分散操作,看看这个简洁的解释http://mpitutorial.com/tutorials/mpi-scatter-gather-and-allgather/

看起来,processorRows数组的大小就是使用的进程总数的大小。而且,您正尝试将此 processorRows 数组的每个元素发送到所有其他行列。因此,您的代码应如下所示:

int *processorRows;
processorRows = (int*)malloc(sizeof(int)*(p+1));

if (my_rank == 0) 
    printf("Process %d is reading...\n", my_rank);
    image = readPPM(argv[1], &width, &height, &max); 

    for (i=0; i<p; i++) 
        processorRows[i] = height/p;
    

    for (i=0; i< height%p; i++)
        processorRows[i]++;
    
   
MPI_Scatter(processorRows, 1, MPI_INT, processorRows, 1, MPI_INT, 0, MPI_COMM_WORLD);

【讨论】:

【参考方案2】:

我删除了

#include "a.h"

image = readPPM(argv[1], &width, &height, &max); 

因为我没有这些类,所以手动将高度设置为 10 并且代码有效。也许问题出在height 变量上?

【讨论】:

虽然这向我们暗示了这个错误的可能来源;在使用 MPI 方面还有其他一些事情,从根本上来说是不必要的; 1.缺少使用 MPI_Collectives(在这种情况下为分散)并尝试使用 send-receive 2 实现手动编码算法。我什至不知道他为什么要维护一个 processorRows 数组,本质上是他只需将 rank==0 的高度发送给每个 PE,每个 PE 可以计算自己的 local_height。这两个建议可以彻底消除这个错误的原因。 而且,我们还应该记住作者说过当我明确写出3个进程的MPI_SEND命令时,它工作正常。,所以如果这个说法实际上是正确的,那么我们从 image 得到 height 也应该是正确的!!!

以上是关于为啥 MPI_SEND 在我的 for 循环中不起作用?如果明确说明它工作正常的主要内容,如果未能解决你的问题,请参考以下文章

INSERT INTO STATEMENT 在我的 for-each 循环中不起作用

为啥正常的 for 循环允许为结构字段分配值,而 for range 在 Golang 中不起作用? [复制]

为啥我的主循环在 tkinter 中不起作用?

为啥嵌套循环在 laravel 中不起作用

为啥我的 while 循环中的条件在 python 中不起作用?

为啥我的 WHERE 子句在我的组合框中不起作用