You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MPI_Scatterv分发二维数组列时出现段错误问题

MPI_Scatterv分发二维数组列触发段错误的解决方法

问题场景

我有一个尺寸为N×M(N=13,M=17)的二维数组,使用8个进程按列分发数据:进程0获取3列,其余进程各获取2列(每列包含13个整数)。代码逻辑看似正确,但调用MPI_Scatterv函数时触发了段错误。

原代码

#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define N 13
#define M 17

int main(int argc, char *argv[]){
    int matrix[N*M];
    int menum, nproc, i, j;
    
    MPI_Init(&argc, &argv);
    
    MPI_Comm_rank(MPI_COMM_WORLD, &menum);
    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
    
    //Matrix initialization
    if (menum == 0) {
        for (i = 0; i < N; i++) {
            for (j = 0; j < M; j++) {
                matrix[(i*M)+j] = i * M + j;
            }
        }
    }
    
    //Every process has its vector of size nloc*mloc
    int nloc = N;
    int mloc = menum < M%nproc ? (M/nproc)+1 : M/nproc;
    int *recv_vec = (int *)malloc(nloc*mloc*sizeof(int));
    
    //Create a custom datatype for a vector of nloc integers
    MPI_Datatype col_type;
    MPI_Type_vector(nloc, 1, M, MPI_INT, &col_type);
    MPI_Type_commit(&col_type);
    
    //Distributing data to other processes
    int sendcounts[]={3,2,2,2,2,2,2,2};
    int displs[]={0,3,5,7,9,11,13,15};
    MPI_Scatterv(matrix, sendcounts, displs, col_type, recv_vec, nloc*mloc, MPI_INT, 0, MPI_COMM_WORLD);
    
    //Freeing up memory and terminate MPI environment
    free(recv_vec);
    MPI_Type_free(&col_type);
    MPI_Finalize();

    return 0;
}

问题原因

MPI_Type_vector创建的col_type虽然能正确描述数组中的一列,但它的**extent(类型跨度)**是基于原数组的行宽M计算的(即M*sizeof(int))。当MPI_Scatterv使用这个类型计算后续列的偏移时,会错误地按原数组行宽跳转,导致访问超出数组范围,触发段错误。

解决方案

使用MPI_Type_create_resized()调整自定义类型的extent,让它匹配单个整数的字节数(sizeof(int)),这样MPI_Scatterv就能正确计算每个进程数据的起始偏移位置。

修改后的代码

#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define N 13
#define M 17

int main(int argc, char *argv[]){
    int matrix[N*M];
    int menum, nproc, i, j;
    
    MPI_Init(&argc, &argv);
    
    MPI_Comm_rank(MPI_COMM_WORLD, &menum);
    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
    
    //Matrix initialization
    if (menum == 0) {
        for (i = 0; i < N; i++) {
            for (j = 0; j < M; j++) {
                matrix[(i*M)+j] = i * M + j;
            }
        }
    }
    
    //Every process has its vector of size nloc*mloc
    int nloc = N;
    int mloc = menum < M%nproc ? (M/nproc)+1 : M/nproc;
    int *recv_vec = (int *)malloc(nloc*mloc*sizeof(int));
    
    //Create a custom datatype for a vector of nloc integers
    MPI_Datatype col_type, resized_col_type;
    MPI_Type_vector(nloc, 1, M, MPI_INT, &col_type);
    // 调整类型的extent,使其按单个整数的大小计算偏移
    MPI_Type_create_resized(col_type, 0, sizeof(int), &resized_col_type);
    MPI_Type_commit(&resized_col_type);
    
    //Distributing data to other processes
    int sendcounts[]={3,2,2,2,2,2,2,2};
    int displs[]={0,3,5,7,9,11,13,15};
    // 使用调整后的类型resized_col_type
    MPI_Scatterv(matrix, sendcounts, displs, resized_col_type, recv_vec, nloc*mloc, MPI_INT, 0, MPI_COMM_WORLD);
    
    //Freeing up memory and terminate MPI environment
    free(recv_vec);
    MPI_Type_free(&col_type);
    MPI_Type_free(&resized_col_type);
    MPI_Finalize();

    return 0;
}

修改要点

  1. 新增resized_col_type,通过MPI_Type_create_resized()将原类型的跨度调整为单个整数的大小,确保列偏移计算正确。
  2. MPI_Scatterv中替换为调整后的类型作为发送数据类型。
  3. 新增对调整后类型的资源释放操作。

内容的提问来源于stack exchange,提问作者Amato.g

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 06:16:02