雅可比迭代求解线性方程组(MPI)

雅可比迭代求解线性方程组(MPI),输入参数后报错,请问要怎么改

#include <mpi.h>
#include <iostream>
#include <cmath>
#include <iomanip>

#define MAXSIZE 100
using namespace std;

int main(int argc, char** argv) {
    int size, rank;
    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    double A[MAXSIZE][MAXSIZE], x[MAXSIZE], b[MAXSIZE], re[MAXSIZE];
    int n;
    double e;
    int count = 0;

    if (rank == 0) {
        cout << "请输入原方程的阶数:";
        cin >> n;
        cout << "请输入原方程的增广矩阵:";
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                cin >> A[i][j];
            }
            cin >> b[i];
        }
        cout << "请输入初始迭代向量值";
        for (int i = 0; i < n; ++i) {
            cin >> x[i];
        }
        cout << "请输入误差上限";
        cin >> e;
    }

    MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);
    MPI_Bcast(&e, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    MPI_Bcast(A, n * MAXSIZE, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    MPI_Bcast(b, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
    MPI_Bcast(x, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);

    int rows_per_process = ceil(1.0 * n / size);
    int rows = min(rows_per_process, n - rank * rows_per_process);
    int start_row = rank * rows_per_process;

    MPI_Barrier(MPI_COMM_WORLD);

    while (true) {
        double local_max_err = 0.0;
        for (int i = start_row; i < start_row + rows; ++i) {
            re[i] = 0;
            for (int j = 0; j < n; ++j) {
                if (i != j) {
                    re[i] += -A[i][j] * x[j];
                }
            }
            re[i] = (re[i] + b[i]) / A[i][i];
            local_max_err = max(local_max_err, fabs(x[i] - re[i]));
        }
        MPI_Allreduce(MPI_IN_PLACE, &local_max_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
        MPI_Allgather(&re[start_row], rows, MPI_DOUBLE, &x[0], rows, MPI_DOUBLE, MPI_COMM_WORLD);
        ++count;
        if (local_max_err < e) break;
    }

    if (rank == 0) {
        cout << "迭代次数:" << count << endl;
        cout << "解向量为:";
        for (int i = 0; i < n; ++i) {
            cout << setprecision(4) << x[i] << " ";
        }
        cout << endl;
    }

    MPI_Finalize();
    return 0;
}

img

img

本次回答借鉴于GPT4

  1. 确保输入的矩阵阶数n不超过MAXSIZE,否则会导致数组溢出。可以在输入n时添加校验:
cin >> n;
if (n > MAXSIZE) {
    cout << "阶数过大,超出范围!" << endl;
    return -1; 
}
  1. 确保矩阵中的元素以及增广向量中的元素输入正确,是数字格式。可以在输入每个元素时添加校验,如果输入的不是数字则提醒重新输入:
cin >> A[i][j];
if (!cin) {  // 如果上次输入发生错误
    cin.clear();  // 清除错误状态
    cin.ignore(1024, '\n');  // 忽略输入缓冲区中输入的非数字字符  
    cout << "请输入数字:";
}  
  1. 确保输入的误差上限e是一个正常的数值,不会导致除零错误或其他计算错误。添加输入校验:
cin >> e; 
if (e <= 0) {
    cout << "请输入正数误差上限:";
}
  1. 确保MPI初始化和 Finalize 调用正确,根据系统环境添加相关参数:
MPI_Init(&argc, &argv);
// ...
MPI_Finalize();

除此之外,还应检查矩阵是否可逆,输入的初值是否适当等。这些因素都可能导致迭代难以收敛或产生异常。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 关于该问题,我找了一篇非常好的博客,你可以看看是否有帮助,链接:MPI_02 获取进程数量
  • 除此之外, 这篇博客: MPI学习笔记中的 理论上说MPI所有的通信功能可以用它的6个基本的调用来实现 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    1. MPI_Init(&argc, &argv) //初始化MPI执行环境,建立多个MPI进程之间的联系,为后续通信做准备。
    2. MPI_Finalize() //结束MPI执行环境。
    3. MPI_Comm_rank (MPI_COMM_WORLD, &rank); //标识各个MPI进程的,给出调用该函数的进程的进程号
    4. MPI_Comm_size (MPI_COMM_WORLD, &size); //用来标识相应进程组中有多少个进程
    5. MPI_Send(buf,counter,datatype,dest,tag,comm);
    bufcounterdatatypedesttagcomm
    发送缓冲区的起始地址,可以是数组或结构指针非负整数,发送的数据个数发送数据的数据类型整型,目的的进程号整型,消息标志MPI进程组所在的通信域

    将发送缓冲区buf中的counter个datatype类型的数据发送到dest目的进程,本次发送的消息标志是tag(用于和MPI_Recv tag 匹配)

    6.MPI_Recv(buf,count,datatype,source,tag,comm,status);

    bufcounterdatatypesourcetagcommstatus
    接收缓冲区的起始地址,可以是数组或结构指针非负整数,可接收的数据个数接收数据的数据类型整型,发送源进程号整型,消息标志MPI进程组所在的通信域返回状态

    MPI_Recv(&buf, 1, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
    可以用于接收任意源,任意tag的消息.

    status是MPI定义的一个数据类型,返回状态变量

                                   status
    status.MPI_SOURCEstatus.MPI_TAGstatus.MPI_error

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^