为啥 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 中不起作用? [复制]