我是MPI的新手。我正在尝试编写一些简单的代码。这是:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <mpi.h>
#include <unistd.h>
#define ONE 0
#define TWO 1
int main(int argc, char * argv[])
{
int dimension = 5;
float ** matrix;
float * mat1;
float * mat2;
int i,j,numNeighbor, processReceived,rank,size,retval;
int k = 0;
retval = MPI_Init(&argc, &argv);
MPI_Request sendRequest[2], recvRequest[2];
MPI_Status status[2];
MPI_Datatype row;
MPI_Type_vector(dimension, 1, dimension, MPI_FLOAT, &row);
MPI_Type_commit(&row);
if(retval != MPI_SUCCESS)
{
MPI_Abort(MPI_COMM_WORLD, retval);
return EXIT_FAILURE;
}
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
mat1 = malloc(dimension*sizeof(float));
mat2 = malloc(dimension*sizeof(float));
matrix = malloc(dimension*sizeof(float*));
for(i=0; i<dimension; i++)
{
matrix[i] = malloc(dimension*sizeof(float));
}
printf("MATRIX OF RANK %d\n", rank);
for(i=0; i<dimension; i++)
{
for(j=0; j<dimension; j++)
{
matrix[i][j] = (float)(rank+1)*(i*2+j);
printf("%2.1f ",matrix[i][j]);
}
printf("\n");
}
printf("\n");
MPI_Isend(&(matrix[0][0]), 1, row, 1-rank, rank, MPI_COMM_WORLD, sendRequest + ONE);
MPI_Isend(&(matrix[0][0]), dimension, MPI_FLOAT, 1-rank, rank, MPI_COMM_WORLD, sendRequest + TWO);
MPI_Irecv(mat1,dimension, MPI_FLOAT, 1-rank, 1-rank, MPI_COMM_WORLD, recvRequest + ONE);
MPI_Irecv(mat2,dimension, MPI_FLOAT, 1-rank, 1-rank, MPI_COMM_WORLD, recvRequest + TWO);
for(i=0; i<2; i++)
{
MPI_Waitany(2,recvRequest, &processReceived, status);
printf("Process Received : %d of rank : %d\n", processReceived,rank);
if(processReceived == ONE)
{
printf("%d ",rank);
for(j=0; j<dimension; j++) printf("# %6.1f ",mat1[j]);
printf("\n");
}
if(processReceived == TWO)
{
printf("%d ",rank);
for(j=0; j<dimension; j++) printf("@ %6.1f ",mat2[j]);
printf("\n");
}
}
MPI_Waitall(2, sendRequest, status);
free(mat1);
free(mat2);
for(i=0;i<dimension;i++) free(matrix[i]);
free(matrix);
MPI_Type_free(&row);
MPI_Finalize();
return 0;
}
这是我的输出:
MATRIX OF RANK 1
0.0 2.0 4.0 6.0 8.0
4.0 6.0 8.0 10.0 12.0
8.0 10.0 12.0 14.0 16.0
12.0 14.0 16.0 18.0 20.0
16.0 18.0 20.0 22.0 24.0
MATRIX OF RANK 0
0.0 1.0 2.0 3.0 4.0
2.0 3.0 4.0 5.0 6.0
4.0 5.0 6.0 7.0 8.0
6.0 7.0 8.0 9.0 10.0
8.0 9.0 10.0 11.0 12.0
Process Received : 0 of rank : 0
0 # 0.0 # 0.0 # 12.0 # 14.0 # 16.0
Process Received : 1 of rank : 0
0 @ 0.0 @ 0.0 @ 12.0 @ 14.0 @ 16.0
Process Received : 0 of rank : 1
1 # 0.0 # 0.0 # 6.0 # 7.0 # 8.0
Process Received : 1 of rank : 1
1 @ 0.0 @ 0.0 @ 6.0 @ 7.0 @ 8.0
我认为我在使用这个程序是因为我将每个进程的一行和一列发送到另一个进程。然后我打印在每个过程中收到的任何内容。但正如你所看到的那样,这不是我认为我会拥有的输出。我在等待的是:
输出示例:
Process Received : 0 of rank : 0
0 # 0.0 # 2.0 # 4.0 # 6.0 # 8.0
Process Received : 1 of rank : 0
0 # 0.0 # 4.0 # 8.0 # 12.0 # 16.0
任何人都可以解释一下我的天赋真的很好吗?这是我使用的唯一功能,因此您可以在自己的机器中运行它。对于此示例,您只能使用2个进程。
mpiexec -n 2 ./name_exe
答案 0 :(得分:2)
问题来自于matrix
中的数据存储不是线性的。正如在代码中定义的那样,matrix
是一个指针数组,所有指针都指向一些独立的内存段。
但是,您的代码假定&matrix[0][0]
指向linearised行主矩阵的开头。
嗯,要解决这个问题,你只需要通过以下方式分配矩阵来遵守这个:
matrix = malloc(dimension*sizeof(float*)); //nothing new here
matrix[0] = malloc(dimension*dimension*sizeof(float));
for(i=1; i<dimension; i++) matrix[i]=matrix[i-1]+dimension;
然后你像以前一样使用matrix
,但对于释放部分,它变为:
free(matrix[0]);
free(matrix);
有了这个,代码应该可以工作。