[英]MPI Gather only gathering from Root Process
First off, I've been using this code as a reference, which shows the use of MPI_Gather
without MPI_Scatter
as that is what I am trying to achieve here. 首先,我一直在使用此代码作为参考,它显示了在没有
MPI_Scatter
的MPI_Gather
下使用MPI_Gather
MPI_Scatter
因为这就是我在此处要实现的目标。 I've been working on this for a long time now and just can't figure out the issue. 我已经为此进行了很长时间的研究,只是无法弄清问题所在。 This sobel edge detection algorithm strengthens the outlines of objects inside images.
这种sobel边缘检测算法可增强图像内对象的轮廓。
I will post my code below, as there is not too much, but I'll give a quick code description first. 由于没有太多内容,我将在下面发布我的代码,但首先我将给出一个简短的代码描述。
I am trying to convert a sequential program into a parallel program. 我正在尝试将顺序程序转换为并行程序。 So all the non-MPI code is correct.
因此,所有非MPI代码都是正确的。
So there can only be a mistake with my MPI
code somewhere. 因此,我的
MPI
代码在某处只能有一个错误。
int main(int argc, char **argv) {
FILE *inFile, *oFile;
int grayImage[N][N], edgeImage[N][N];
char type[2];
int w, h, max;
int r, g, b, y, x, i, j, sum, sumx, sumy;
int tid;
int GX[3][3], GY[3][3];
double elapsed_time;
struct timeval tv1, tv2;
int error = 0;
char buffer[BUFSIZ];
int rank, NP;
// Code lies here for reading from the image file and storing into the grayImage array.
// This works so I saw no reason to include it
/* 3x3 Sobel masks. */
GX[0][0] = -1; GX[0][1] = 0; GX[0][2] = 1;
GX[1][0] = -2; GX[1][1] = 0; GX[1][2] = 2;
GX[2][0] = -1; GX[2][1] = 0; GX[2][2] = 1;
GY[0][0] = 1; GY[0][1] = 2; GY[0][2] = 1;
GY[1][0] = 0; GY[1][1] = 0; GY[1][2] = 0;
GY[2][0] = -1; GY[2][1] = -2; GY[2][2] = -1;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &NP);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// This calculates the block size.MPI
// On 4 processors the block size for a 100x100 image would be 25x100 each
int blksz = (int)ceil((double)N/NP);
// This creates a local array for each processor, soon to be gathered
int tempEdge[blksz][N];
// this line shows it's working correctly
printf("processor %d, width: %d, height: %d, blksz: %d, begin: %d, end: %d\n", rank, w, h, blksz, rank*blksz, (rank+1)*blksz);
for(x=rank*blksz; x < (rank+1)*blksz && x<h; x++){
// Any code in this loop can be ignored as it works correctly.
for(y=0; y < w; ++y){
sumx = 0;
sumy = 0;
// handle image boundaries
if(x==0 || x==(h-1) || y==0 || y==(w-1))
sum = 0;
else{
//x gradient approx
for(i=-1; i<=1; i++) {
for(j=-1; j<=1; j++){
sumx += (grayImage[x+i][y+j] * GX[i+1][j+1]);
}
}
//y gradient approx
for(i=-1; i<=1; i++) {
for(j=-1; j<=1; j++){
sumy += (grayImage[x+i][y+j] * GY[i+1][j+1]);
}
}
//gradient magnitude approx
sum = (abs(sumx) + abs(sumy));
}
tempEdge[x][y] = clamp(sum);
}
}
// Here is the line I am guessing is causing the problem
MPI_Gather(&tempEdge, w*blksz, MPI_INT,
&edgeImage, w*blksz, MPI_INT, 0,
MPI_COMM_WORLD);
// Finally, I output edgeImage to a file here.
if(rank==0){
// output edgeImage to File
}
MPI_Finalize();
return 0;
}
The input image I am using is this: 我正在使用的输入图像是这样的:
But the output is only giving this: 但是输出仅给出以下内容:
As you can see it is only the top quarter (N/4), or blksz
of the image. 如您所见,它只是图像的前四分之一(N / 4)或
blksz
。
This would imply that MPI_Gather
is only gathering from process with rank 0? 这意味着
MPI_Gather
仅从等级为0的进程中收集吗?
I've been spending so much time on this, any help would be hugely appreciated! 我已经花了很多时间在此上,任何帮助将不胜感激!
Do not blame MPI collectives for bugs in the rest of your code. 不要将其余代码中的错误归咎于MPI集体。 It is actually a miracle that your code produces broken images without segfaulting.
实际上,您的代码产生损坏的图像而没有段错误实际上是一个奇迹。 Just take a look at that part:
只需看一下那部分:
int tempEdge[blksz][N];
~~~~~
for(x = rank*blksz; x < (rank+1)*blksz && x<h; x++){
~~~~~~~~~~
for(y = 0; y < w; ++y){
...
tempEdge[x][y] = clamp(sum); (1)
~
}
}
For any rank > 0 the code writes past the end of the array. 对于任何大于0的秩,代码将写入数组的末尾。 Fix the statement at (1) to read:
将语句(1)修改为:
tempEdge[x - rank*blksz][y] = clamp(sum);
Also, remove the &
s in the MPI_Gather
call: 另外,删除
MPI_Gather
调用中的&
:
MPI_Gather(tempEdge, w*blksz, MPI_INT,
edgeImage, w*blksz, MPI_INT, 0,
MPI_COMM_WORLD);
It will work with &
too, but that is technically incorrect. 它也可以与
&
一起使用,但这在技术上是不正确的。 If you insist on using the address-of operator, then use &tempEdge[0][0]
and &edgeImage[0][0]
instead. 如果您坚持使用地址运算符,请改用
&tempEdge[0][0]
和&edgeImage[0][0]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.