我试图从MPI配置中的节点收集一些不同矩阵的行。到目前为止,我已经让程序使用下面的代码接收一行到另一个进程,即代码会将矩阵recv
更改为数字1..7
,但理想情况是我和#39 ; d喜欢这样做是改变前两行,第一行是1..7
,第二行是8..14
,但是当我更改发送/接收计数时,这不会发生第55/57行。这些街区应该在记忆中连续布局,所以我不确定我目前在哪里出错,任何帮助都会受到赞赏。
代码:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
double **allocMatrix(int dim) {
int i;
double **matrix;
matrix = (double **)malloc(dim*sizeof(double *));
for(i=0; i < dim; i++) {
matrix[i] = (double *)malloc(dim*sizeof(double));
}
return matrix;
}
void printMatrix(double **values, int size) {
int i, j;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
printf("%10lf ", values[i][j]);
}
printf("\n");
}
}
int main(int argc, char* argv[]) {
MPI_Init(&argc, &argv);
int size, rank, i, j;
int dimensions = 7;
MPI_Comm_size(MPI_COMM_WORLD, &size);//number of processes
MPI_Comm_rank(MPI_COMM_WORLD, &rank);//rank for each process
double **send = allocMatrix(dimensions);
double **recv = allocMatrix(dimensions);
int count = 0;
for (i=0; i<dimensions; i++) {
for (j=0; j<dimensions; j++) {
if (rank == 0) {
recv[i][j] = 0;
} else {
send[i][j] = ++count;
}
}
}
MPI_Datatype arrType;
MPI_Type_vector(1, dimensions, 0, MPI_DOUBLE, &arrType);
MPI_Type_commit(&arrType);
int recvCounts[size];
int displs[size];
recvCounts[0] = 0;
displs[0] = 0;
recvCounts[1] = 1;
displs[1] = 0;
MPI_Gatherv(&(send[0][0]), 1, arrType,
&(recv[0][0]), recvCounts, displs, arrType,
0, MPI_COMM_WORLD);
if (rank == 0) {
printMatrix(recv, dimensions);
}
MPI_Finalize();
return 0;
}
输出:
make gatherv
mpicc -Wall -o gatherv gatherv.c && ./gather
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
期望的输出:
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000
8.000000 9.000000 10.00000 11.00000 12.00000 13.00000 14.00000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
答案 0 :(得分:1)
此代码中有两点可以修改:
矩阵的分配效果很好,有时可能很有用,但行在内存中不连续,因为malloc()
被称为dim+1
次。您可以通过为like in this answer和其他许多值分配所有值的空间来确保行在内存中是连续的。这种2D数组是可以被像lapack和fftw这样的库使用的数组......而且MPI_Gatherv()
也会喜欢它。 malloc()
将被调用两次:一次用于指向行,一次用于值。
如果更改recvCounts[]
中的值,则要发送的项目数必须相应更改。由于所有进程都以相同的方式填充recvCounts[]
,并且由于接收类型和发送类型相同(arrType
),因此使用recvCounts[rank]
作为MPI_Gatherv()
的第二个参数是好的伎俩。
顺便说一句,对于第一个问题来说这是一个非常好的问题!
这里的代码可由mpicc main.c -o main
编译并由mpirun -np 42 main
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
double **allocMatrix(int dim) {
int i;
double **matrix;
//allocate space for values at once, so as to be contiguous in memory
matrix = (double **)malloc(dim*sizeof(double *));
matrix[0] = (double *)malloc(dim*dim*sizeof(double));
for(i=1; i < dim; i++) {
matrix[i]=&matrix[0][dim*i];
//matrix[i] = (double *)malloc(dim*sizeof(double));
}
return matrix;
}
void printMatrix(double **values, int size) {
int i, j;
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
printf("%10lf ", values[i][j]);
}
printf("\n");
}
}
//function to free the matrix
void freeMatrix(double **values) {
free(values[0]);
free(values);
}
int main(int argc, char* argv[]) {
MPI_Init(&argc, &argv);
int size, rank, i, j;
int dimensions = 7;
MPI_Comm_size(MPI_COMM_WORLD, &size);//number of processes
MPI_Comm_rank(MPI_COMM_WORLD, &rank);//rank for each process
double **send = allocMatrix(dimensions);
double **recv = allocMatrix(dimensions);
int count = 0;
for (i=0; i<dimensions; i++) {
for (j=0; j<dimensions; j++) {
if (rank == 0) {
recv[i][j] = 0;
} else {
send[i][j] = ++count;
}
}
}
MPI_Datatype arrType;
MPI_Type_vector(1, dimensions, 0, MPI_DOUBLE, &arrType);
MPI_Type_commit(&arrType);
int recvCounts[size];
int displs[size];
// a loop to initialize counts and displacements
for(i=0;i<size;i++){
recvCounts[i]=0;
displs[i]=0;
}
recvCounts[0] = 0;
displs[0] = 0;
if(size>1){
recvCounts[1] = 2;// two lines sent
displs[1] = 0;//to the start of matrix
}
//second argument of mpi_gatherv() is now recvCounts[rank]
MPI_Gatherv(&(send[0][0]), recvCounts[rank], arrType,
&(recv[0][0]), recvCounts, displs, arrType,
0, MPI_COMM_WORLD);
if (rank == 0) {
printMatrix(recv, dimensions);
}
//free the matrices
freeMatrix(recv);
freeMatrix(send);
MPI_Finalize();
return 0;
}