使用MPI_Gatherv触发段错误,需实现输入abcd输出abbcccdddd
解决MPI_Gatherv段错误问题,实现abcd→abbcccdddd的需求
嘿,我帮你梳理下代码里的问题,顺便给出能正常运行的修正版本~你的需求是每个进程对应输入字符串的一个字符,生成该字符重复rank+1次的片段,最后用MPI_Gatherv收集拼接成结果对吧?现在出现段错误,主要是MPI_Gatherv的关键参数没设置对,还有一些细节没处理好。
先说说代码里的核心问题
- 缺失
MPI_Gatherv必需的参数:你代码里的disps[...]是不完整的,MPI_Gatherv需要两个关键数组:recvcounts:每个进程要发送的数据长度(这里每个进程是rank+1个字符)displs:每个进程的数据在根进程接收缓冲区中的起始偏移位置
没定义这两个数组的话,MPI会访问非法内存,直接触发段错误。
- 字符串终止符没处理:不管是本地生成的重复片段还是最终结果,都得加
\0,不然打印的时候会出现乱码或者内存访问问题。 - 数据发送长度未明确:每个进程要发送的字符数是
rank+1,但你没把这个值传递给MPI_Gatherv,导致根进程不知道该接收多少数据。
修正后的完整代码
#include <stdio.h> #include <mpi.h> #include <string.h> int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); int rank, size; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // 这里固定处理4个字符(对应4个进程),如果需要动态适配可以调整 const int input_len = 4; char input_str[input_len + 1]; // 输入字符串缓冲区,留位置存终止符 char local_char; // 每个进程接收的单个字符 char local_repeat[100]; // 本进程生成的重复字符片段 char final_result[100]; // 根进程存储最终结果的缓冲区 // 根进程负责输入字符串 if (rank == 0) { printf("请输入4个字符的字符串:"); scanf("%s", input_str); // 简单校验输入长度是否符合要求 if (strlen(input_str) != input_len) { printf("输入长度必须是4个字符哦!\n"); MPI_Abort(MPI_COMM_WORLD, 1); } } // 将输入的每个字符分散到对应进程 MPI_Scatter(input_str, 1, MPI_CHAR, &local_char, 1, MPI_CHAR, 0, MPI_COMM_WORLD); // 生成当前进程的重复字符片段:重复rank+1次 int local_len = rank + 1; for (int i = 0; i < local_len; i++) { local_repeat[i] = local_char; } local_repeat[local_len] = '\0'; // 给本地片段加终止符 // 准备MPI_Gatherv需要的recvcounts和displs数组 int recv_counts[input_len]; int displacements[input_len]; int current_offset = 0; for (int i = 0; i < input_len; i++) { recv_counts[i] = i + 1; // 第i个进程发送i+1个字符 displacements[i] = current_offset; current_offset += recv_counts[i];// 更新下一个进程的偏移位置 } // 用Gatherv收集所有进程的片段到根进程 MPI_Gatherv(local_repeat, local_len, MPI_CHAR, final_result, recv_counts, displacements, MPI_CHAR, 0, MPI_COMM_WORLD); // 根进程打印最终结果 if (rank == 0) { final_result[current_offset] = '\0'; // 给最终结果加终止符 printf("生成结果:%s\n", final_result); } MPI_Finalize(); return 0; }
关键修正点解释
recv_counts和displacements数组:recv_counts[i] = i+1:对应进程i要发送i+1个字符(进程0发1个,进程1发2个,以此类推)displacements计算每个进程数据在根进程缓冲区的起始位置:进程0从0开始,进程1从1开始,进程2从1+2=3开始,进程3从3+3=6开始,这样拼接后正好是a+bb+ccc+dddd=abbcccdddd
- 字符串终止符:不管是本地生成的片段还是最终结果,都添加了
\0,避免打印时出现内存垃圾 - 输入校验:根进程简单检查输入长度,确保和我们预设的4个字符匹配,避免后续逻辑出错
编译运行步骤
用MPI编译器编译:
mpicc mpi_gatherv_demo.c -o mpi_gatherv_demo
运行时必须用4个进程(对应4个字符的输入):
mpiexec -n 4 ./mpi_gatherv_demo
输入abcd后,就能得到你想要的abbcccdddd啦~
内容的提问来源于stack exchange,提问作者Ujjwal Maheshwari
相关产品推荐
相关产品推荐

