MPI C语言代码仅输出矩阵最后一行的问题排查与修正
MPI生成倍数矩阵错误分析与修正
问题背景
编写MPI程序生成每行元素为对应行号倍数的矩阵(如第一行1 2 3 4,第二行2 4 6 8等),但实际运行后所有行均为最后一行内容(4 8 12 16)。
原代码
#include <stdio.h> #include <mpi.h> int main (int argc, char **argv) { int num_procs; int rank; int n; int lst[n]; // int lst2[n]; int matrix[n][n]; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_size (MPI_COMM_WORLD, &num_procs); MPI_Comm_rank (MPI_COMM_WORLD, &rank); //printf("%d: hello (p=%d)\n", rank, num_procs); n=num_procs; if (rank==0){ for (int i=0;i<n;i++) { lst[i]=(i+1)*(rank+1); // printf("%d ",lst[i]); } // printf("\n"); for (int i=0;i<n;i++){ matrix[0][i]=lst[i]; } for (int k=1;k<num_procs;k++){ MPI_Recv(&lst,n,MPI_INT,k,0,MPI_COMM_WORLD,&status); for (int j=0;j<n;j++){ matrix[k][j]=lst[j]; } // for (int i=0;i<n;i++) { // printf("%d ",lst[i]); // } // printf("\n"); } for (int i=0;i<n;i++){ for (int j=0;j<n;j++){ printf("%d ", matrix[i][j]); if (j==n-1){printf("\n");} } } } else{ for (int i=0;i<n;i++) { lst[i]=(i+1)*(rank+1); // printf("%d ",lst[i]); } // printf("\n"); MPI_Send(&lst[0],n,MPI_INT,0,0,MPI_COMM_WORLD); } MPI_Finalize(); }
实际输出
4 8 12 16 4 8 12 16 4 8 12 16 4 8 12 16
期望输出
1 2 3 4 2 4 6 8 3 6 9 12 4 8 12 16
错误原因
核心问题是变长数组(VLA)的初始化顺序错误:
- 定义
lst[n]和matrix[n][n]时,变量n尚未被赋值(此时n是未初始化的垃圾值)。 - C语言中变长数组的大小必须在定义时确定,后续给
n赋值num_procs不会改变已分配的数组内存大小,属于未定义行为。 - 这种错误导致内存布局混乱,后续的赋值、MPI通信操作会破坏矩阵内存,最终所有行被最后一次写入的数据覆盖。
修正方法
调整变量初始化顺序,确保在定义变长数组前n已经被正确赋值:
- 将
n=num_procs;移到变长数组定义之前; - 遵循MPI初始化→获取进程数→给
n赋值→定义变长数组的顺序。
修正后的代码
#include <stdio.h> #include <mpi.h> int main (int argc, char **argv) { int num_procs; int rank; int n; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_size (MPI_COMM_WORLD, &num_procs); MPI_Comm_rank (MPI_COMM_WORLD, &rank); // 先给n赋值,再定义变长数组 n=num_procs; int lst[n]; int matrix[n][n]; if (rank==0){ for (int i=0;i<n;i++) { lst[i]=(i+1)*(rank+1); } for (int i=0;i<n;i++){ matrix[0][i]=lst[i]; } for (int k=1;k<num_procs;k++){ MPI_Recv(&lst,n,MPI_INT,k,0,MPI_COMM_WORLD,&status); for (int j=0;j<n;j++){ matrix[k][j]=lst[j]; } } for (int i=0;i<n;i++){ for (int j=0;j<n;j++){ printf("%d ", matrix[i][j]); if (j==n-1){printf("\n");} } } } else{ for (int i=0;i<n;i++) { lst[i]=(i+1)*(rank+1); } MPI_Send(&lst[0],n,MPI_INT,0,0,MPI_COMM_WORLD); } MPI_Finalize(); }
验证结果
运行修正后的代码,将得到符合预期的输出:
1 2 3 4 2 4 6 8 3 6 9 12 4 8 12 16
内容的提问来源于stack exchange,提问作者S K Shree Ram
相关产品推荐
相关产品推荐

