只想做个有钱的富婆花迪 2023-06-09 21:14 采纳率: 69.2%
浏览 30
已结题

mpi(c语言)程序为什么出现[cb81ea2c449b:01915] Read -1, expected 9000, errno = 1


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"mpi.h"

int isShui(int k)
{
    if(k == 0||k == 1) return 0;
    char num_str[4];
    sprintf(num_str, "%d", k);
    int digits = strlen(num_str);
    int total = 0;
    for (int i = 0; i < digits; i++) {
        int digit = num_str[i] - '0';
        total += digit * digit * digit* digit;
    }
    return k == total;
}

int main(int argc,char **argv)
{
    int rank,size;
    int i,j,cnt;
    int n;
    int *num;
    int a = 1000,b = 10000;
    n = b-a;
    MPI_Init(&argc,&argv);
    MPI_Comm_size(MPI_COMM_WORLD,&size);
    MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    if(rank==0)
    {
//        printf("Please input n:\n");
//        scanf("%d",&n);
        num = (int*)malloc(sizeof(int)*n);
        //printf("Please input %d data:\n",n);
        int i;
        for(i=0,j=a;i<n;i++,j++)
            num[i] = j;
            //scanf("%d",&num[i]);
    }
    MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);
//scatterv 
//    //********************************************************************
//     // 计算每个进程负责处理的数据量
    int* recvcounts = (int*) malloc(size * sizeof(int));
    int* displs = (int*) malloc(size * sizeof(int));
    int cs = n / size;
    int r = n % size;
    for (int i = 0; i < size; i++) {
        recvcounts[i] = cs;
        if (i < r) {
            recvcounts[i] += 1;  
        }
        displs[i] = (i > 0 ? displs[i-1] + recvcounts[i-1] : 0);
    }

    // 将数据 scatterv 分发到每个进程
    int* recvbuf = (int*) malloc(recvcounts[rank] * sizeof(int));
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Scatterv(num, recvcounts, displs, MPI_INT,
                 recvbuf, recvcounts[rank], MPI_INT, 0, MPI_COMM_WORLD);
    //***********************************************************


   int *suarr = (int*)malloc(sizeof(int)*recvcounts[rank]);
    for(i = 0,j = 0;i<recvcounts[rank];i++)
    {
        if(isShui(recvbuf[i]))//判断素数 
        {
            suarr[j] = recvbuf[i];
            j++;
        }
    }
    MPI_Reduce(&j,&cnt,1,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);//总共cnt个素数 
    
    
    //Gatherv
    //********************************************************************************** 
    MPI_Gather(&j,1,MPI_INT,recvcounts,1,MPI_INT,0,MPI_COMM_WORLD);//接收数量的数组 
    recvcounts[rank] = j; 
    for(i = 0;i<size;i++)
    displs[i] = (i>0?displs[i-1]+recvcounts[i-1]:0);
    int *ans = (int*)malloc(sizeof(int)*cnt);
    MPI_Gatherv(suarr,j,MPI_INT,ans,recvcounts,displs,MPI_INT,0,MPI_COMM_WORLD);
    //***********************************************************************************
    if(rank == 0)
    {
        for(i = 0;i<cnt;i++)
        {
            printf("%d ",ans[i]);
        }
        printf("\n");
    }
    MPI_Finalize();
    return 0;
}

img


虽然结果可以打印出来,但是为什么会出现红色框里面的内容,改怎么解决。
该程序的原题目为:
若一个四位数,它的每个位上的数字的4次幂之和等于它本身。例如:1634=14+63+33+44。请编写一个并行程序,把1000-9999之间的数分配给各进程,找出其中的水仙花数并打印出来。在你的主目录下,保存的文件名为rose.c。

  • 写回答

2条回答 默认 最新

  • 辞轩. 2023-06-11 11:40
    关注

    这个问题发生的可能原因是由于程序试图读取一个无效的内存地址或者读取数据的长度超出了这个内存区域的范围,这往往会导致运行时出现异常和错误。

    在你的代码中,可能与以下这一行相关:

    MPI_Gatherv(suarr,j,MPI_INT,ans,recvcounts,displs,MPI_INT,0,MPI_COMM_WORLD);
    

    你在调用 MPI_Gatherv 函数时,第二个参数为 j,表示需要发送的数据的长度。因此,这个参数要确保在发送时数据长度至少为 0。在你的代码中,你并没有对这个长度进行正确的初始化操作,可能导致在 MPI_Gatherv 函数中读取了不合法的数据。这个问题可能在你某个进程中发生,当这个进程的数据长度小于 j 时会尝试读取无效的数据进而导致错误。

    为了解决这个问题,你可以对第二个参数进行正确的初始化操作。在你的代码中,j 记录的是当前进程中水仙花数的个数。

    你可以在所有进程中,即在调用 isShui 函数之前,统计出 num 中水仙花数需要的内存大小,并将这个值广播到所有进程。因此,你可以在调用 MPI_Gatherv 函数之前,统计出所有进程中水仙花数的个数(即 cnt),并将这个值存储在一个数组中。这个数组的大小应为进程的个数(MPI_Comm_size 返回的值)。

    具体的修改方式如下,修改后的变量名称我们使用了 recvcounts

    int* recvcounts = (int*) malloc(size * sizeof(int));
    int* displs = (int*) malloc(size * sizeof(int));
    int cs = n / size;
    int r = n % size;
    for (int i = 0; i < size; i++) {
        recvcounts[i] = cs;
        if (i < r) {
            recvcounts[i] += 1;  
        }
        displs[i] = (i > 0 ? displs[i-1] + recvcounts[i-1] : 0);
    }
    
    // 统计所有进程中水仙花数的个数
    MPI_Reduce(&j,&cnt,1,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);
    
    int* recvbuf = (int*) malloc(recvcounts[rank] * sizeof(int));
    MPI_Barrier(MPI_COMM_WORLD);
    MPI_Scatterv(num, recvcounts, displs, MPI_INT,
                 recvbuf, recvcounts[rank], MPI_INT, 0, MPI_COMM_WORLD);
    
    int *suarr = (int*)malloc(sizeof(int)*recvcounts[rank]);
    for(i = 0,j = 0;i<recvcounts[rank];i++) {
        if(isShui(recvbuf[i])) {
            suarr[j] = recvbuf[i];
            j++;
        }
    }
    
    // 将统计的所有进程中水仙花数的个数存储在 recvcounts 中
    MPI_Gather(&j,1,MPI_INT,recvcounts,1,MPI_INT,0,MPI_COMM_WORLD);
    

    MPI_Gatherv 函数中的参数修改如下:

    MPI_Gatherv(suarr, j, MPI_INT, ans, recvcounts, displs, MPI_INT, 0, MPI_COMM_WORLD);
    

    这样就能正确地进行 MPI_Gatherv 了。同时,由于在函数调用之前的缺失引起的错误是随机的(它取决于进程和数组大小等变量的排列方式),因此你可能需要尝试多次运行你的程序,来验证这个修改是否真正解决了问题。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月12日
  • 创建了问题 6月9日

悬赏问题

  • ¥30 搭建面包板由NE555N和SN74LS90N组成的计时电路时出了问题
  • ¥15 无源定位系统的时差估计误差标准差
  • ¥15 请问这个代码哪里有问题啊
  • ¥20 python--version在命令端输入结果Python is not defined怎么办?还有pip不是exe格式是不是没安装成功?
  • ¥15 通过GaussianView进行结构微调消除虚频
  • ¥15 调用transformers库
  • ¥15 由于导出的数据名字中带有/,导致Matlab打不开,怎么办?
  • ¥15 新硬盘安装的程序总是崩溃,提示遇到错误
  • ¥15 openpcdet自制数据集评估bev精度和3d精度相同
  • ¥15 excel 上下按钮 显示行