我用 C/MPI 编写了一个程序,它简单地将 NxN 矩阵拆分为子矩阵(对于行),然后使用例程 MPI_Scatterv 将其提供给所有进程。维度 N 不一定是进程数的倍数。我决定给等于 DIM % 大小的多个进程多一行。代码如下;它不起作用,我不明白为什么。错误消息是这样的: 工作中止: 等级:节点:退出代码[:错误消息] 0: PACI: -1073741819: 进程 0 在未调用 finalize 的情况下退出
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define DIM 4
#define ROOT 0
float **alloc (int, int);
void init (float **, int, int);
void print (float **, int, int);
int main(int argc, char *argv[])
{
int rank,
size,
dimrecv,
i;
int *sendcount = NULL, *displs = NULL;
float **matrix, **recvbuf;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
dimrecv = (int)(DIM / size);
if(rank < (DIM % size))
dimrecv += 1 ;
recvbuf = alloc(dimrecv, DIM);
if (rank == ROOT)
{
matrix = alloc(DIM, DIM);
init(matrix, DIM, DIM);
sendcount = (int*)calloc(size, sizeof(int));
displs = (int*)calloc(size, sizeof(int));
int total = 0;
printf("MATRIX %d x %d", DIM, DIM);
print(matrix, DIM, DIM);
displs[0] = 0;
for (i = 0; i < size; i++)
{
if (i < DIM % size)
sendcount[i] = (ceil((float)DIM/size))*DIM;
else
sendcount[i] = (floor((float)DIM/size))*DIM;
total += sendcount[i];
if (i + 1 < size)
displs[i + 1] = total;
}
}
MPI_Scatterv(&(matrix[0][0]), sendcount, displs, MPI_FLOAT,
recvbuf, dimrecv*DIM, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
printf("\n\n");
for(i = 0; i< size; i++)
{
MPI_Barrier(MPI_COMM_WORLD);
if (i == rank)
{
printf("SUBMATRIX P%d", i);
print(recvbuf, dimrecv, DIM);
}
}
free(matrix[0]);
free(matrix);
free(recvbuf[0]);
free(recvbuf);
/* quit */
MPI_Finalize();
return 0;
}
float **alloc(int rows, int cols)
{
int i;
float *num_elem = (float *)calloc(rows*cols, sizeof(float));
float **matrix= (float **)calloc(rows, sizeof(float*));
for (i=0; i<rows; i++)
matrix[i] = &(num_elem[cols*i]);
return matrix;
}
void init (float **matrix, int rows, int cols)
{
int i, j;
srand(time(NULL));
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++)
matrix[i][j] = 1 + (rand() % 5);
}
}
void print (float **matrix, int rows, int cols)
{
int i, j;
for (i = 0; i < rows; i++) {
printf("\n");
for (j = 0; j < cols; j++)
printf("%.1f ", matrix[i][j]);
}
}
我该如何解决这个问题,使用带有双指针的动态分配?我以静态方式编写了相同的程序并且它有效!非常感谢。 人。
最佳答案
您需要更加注意哪个进程/rank 正在分配内存,以及哪个进程/rank 正在释放内存。
在您当前的实现中,您需要 rank == ROOT
来分配和初始化 matrix
、sendcount
和 displs
。你会希望每个等级分配和初始化 sendcount
和 displs
(否则,当他们每个进入 MPI_Scatterv
他们怎么知道他们到底是什么?会收到吗?)。最后,他们还需要分配但不初始化recvbuf
。此缓冲区的初始化发生在 MPI_Scatterv
例程内部。
[旁注:从技术上讲,您不需要让每个级别都初始化 sendcount
和 displs
,尽管这肯定是最快的。如果只有 rank == ROOT
进程有计算这些值的知识,那么在进入 MPI_Scatterv
例程。]
当然,您随后必须确保只有正确的列才能释放它们之前分配的正确内存。
这在您的静态初始化中起作用的原因是,当您最初静态定义数组时,每个等级都“分配”了内存。假设您天真地这样做,您之前可能在该实现中使用了过多的内存(因为,如上所示,并非每个等级都需要为您正在使用的每个矩阵/数组分配内存)。
希望这对您有所帮助。
关于c - MPI_Scatterv 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33614560/