C语言使用MPI I/O处理大向量计算上三角距离矩阵报错求助
问题修复说明
核心报错原因
你遇到的mca_fbtl_posix_pwritev: error in writev:Invalid argument错误由多个问题共同导致,规模小时未触发边界溢出所以能正常运行,规模到80000时问题暴露:
- 32位int类型溢出:计算前序行总元素数时用int类型存储累加和,SIZE=80000时上三角总元素数约32亿,远超32位int最大值(约21亿),溢出后得到负数偏移量,传入writev时触发非法参数错误
- 偏移量计算逻辑错误:偏移量单位匹配逻辑不严谨,且用循环累加计算总元素数效率低易出错
- 无效写入逻辑:当
local_dim=0(最后一行上三角无元素)时强制设为1,写入多余数据破坏文件结构 - 通信和IO逻辑冗余:循环调用MPI_Scatter、循环内加MPI_Barrier都是不必要的错误用法
修复后的完整代码
#include <stdio.h> #include <mpi.h> #include <stdlib.h> #include <math.h> int main(int argc, char *argv[]) { int procid, numprocs, ierr, *a, SIZE, num_rows; SIZE = 80000; MPI_File fh; double *x, *y; a = (int*) malloc(SIZE*sizeof(int)); x =(double*) malloc(SIZE*sizeof(double)); y =(double*) malloc(SIZE*sizeof(double)); ierr = MPI_Init(&argc, &argv); ierr = MPI_Comm_rank(MPI_COMM_WORLD, &procid); ierr = MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Status status; MPI_Offset offset; num_rows = SIZE/numprocs; // 可自行补充SIZE不能被numprocs整除的兼容逻辑,本测试用例默认可整除 for (int i = 0; i < SIZE; i ++) { a[i] = i+1; x[i] = i+1; y[i] = i+2; } int *local_a = (int*) malloc(num_rows*sizeof(int)); // 修复:单次Scatter完成索引数组分发,不需要循环调用 MPI_Scatter(a, num_rows, MPI_INT, local_a, num_rows, MPI_INT, 0, MPI_COMM_WORLD); MPI_File_open(MPI_COMM_WORLD, "data.bin", MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &fh); for (int i = 0; i < num_rows; i++) { int p1 = local_a[i]; int local_dim = SIZE - p1; // 修复:最后一行无元素直接跳过,不做无效写入 if (local_dim <= 0) continue; double *Dist = (double*) malloc(local_dim*sizeof(double)); // 修复:用数学公式直接计算偏移量,避免循环累加和int溢出 // 前p1-1行总元素数 = (p1-1)*SIZE - p1*(p1-1)/2,乘以double的字节数得到偏移 offset = ((MPI_Offset)(p1-1)*SIZE - (MPI_Offset)p1*(p1-1)/2) * sizeof(double); // 修复:用乘法和sqrt计算距离,替换低效的pow调用 double x1 = x[p1-1], y1 = y[p1-1]; for (int j = p1; j < SIZE; j++) { double dx = x1 - x[j]; double dy = y1 - y[j]; Dist[j-p1] = sqrt(dx*dx + dy*dy); } MPI_File_write_at(fh, offset, Dist, local_dim, MPI_DOUBLE, &status); free(Dist); } // 修复:移除循环内冗余的MPI_Barrier,仅在关闭文件前做一次同步即可 MPI_Barrier(MPI_COMM_WORLD); MPI_File_close(&fh); ierr = MPI_Finalize(); free(a); free(x); free(y); free(local_a); return ierr; }
内容的提问来源于stack exchange,提问作者Prateek
相关产品推荐
相关产品推荐

