gpt4 book ai didi

c - MPI 收集多个 vector

转载 作者:太空宇宙 更新时间:2023-11-04 03:42:11 25 4
gpt4 key购买 nike

我正在尝试从 MPI 配置中的节点收集一些不同矩阵的行。到目前为止,我已经得到了使用下面的代码将一行接收到另一个进程的程序,即代码会将矩阵 recv 更改为数字 1..7 但理想情况下,我希望它做的是更改前两行,第一行的数字 1..7 和第二行的 8..14,但是当我更改第 55/57 行的发送/接收计数时,这不会发生。这些 block 应该在内存中连续布置,所以我不确定我目前哪里出错了,我们将不胜感激。

代码:

#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

最佳答案

这段代码有两点可以修改:

  • 矩阵的分配工作良好,有时可能有用,但行在内存中不连续,因为 malloc() 被调用 dim+1次。您可以通过一次为所有值分配空间来确保行在内存中是连续的 like in this answer和许多其他人。这种二维数组可以被 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;
}

关于c - MPI 收集多个 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27564410/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com