高斯消去法解线性方程组(MPI)

用一上午的时间,用MPI编写了高斯消去法解线性方程组。这次只是针对单线程负责一个线程方程的求解,对于超大规模的方程组,需要按行分块,后面会在这个基础上进行修改。总结一下这次遇到的问题:

(1)MPI_Allreduce()函数的使用;

(2)MPI_Allgather()函数的使用;

(3)线程之间不使用通信函数进行值传递(地址传递)是没有办法使用其他线程的数据,这是设计并行程序中最容易忽视的一点。

  1 #include "stdio.h"
  2 #include "mpi.h"
  3 #include "malloc.h"
  4
  5 #define n 4
  6 #define BLOCK_LOW(id,p,n) ((id) * (n)/(p))
  7 #define BLOCK_HIGH(id,p,n) (BLOCK_LOW((id)+1,p,n)-1)
  8 #define BLOCK_SIZE(id,p,n) (BLOCK_LOW((id)+1,p,n)-BLOCK_LOW((id),p,n))
  9 #define BLOCK_OWNER(index,p,n) (((p) * ((index)+1)-1)/(n))
 10 #define MIN(a,b) ((a)<(b)?(a):(b))
 11 int NotIn(int id,int *picked);
 12 struct {
 13 double value;
 14 int index;
 15 }local,global;
 16
 17 int main(int argc,char *argv[])
 18 {
 19   int id,p;
 20   MPI_Init(&argc,&argv);
 21   MPI_Comm_rank(MPI_COMM_WORLD,&id);
 22   MPI_Comm_size(MPI_COMM_WORLD,&p);
 23
 24   //double a[n][n+1] = {{4,6,2,-2,8},{2,0,5,-2,4},{-4,-3,-5,4,1},{8,18,-2,3,40}};
 25   double a[n][n+1] = {{2,1,-5,1,8},{1,-3,0,-6,9},{0,2,-1,2,-5},{1,4,-7,6,0}};
 26
 27   int i,j;
 28   int index;
 29
 30   int *picked;
 31   picked = (int *)malloc(sizeof(int) * n);   //记录已被选中的行
 32   for(i=0;i<n;i++)
 33     picked[i] = -1;
 34
 35   for(i=0;i<n;i++)
 36   {
 37
 38       if(NotIn(id,picked))    //判断该行是否已被选中,没有选择则进行下一步
 39       {
 40       local.value = a[id][i];
 41       local.index = id;
 42       }
 43       else
 44       {
 45       local.value = -100;   //假设各个参数最小值不小于-100
 46           local.index = id;
 47       }
 48
 49       MPI_Allreduce(&local,&global,1,MPI_DOUBLE_INT,MPI_MAXLOC,MPI_COMM_WORLD);   // 归约最大的值,并存入到global中
 50      // printf(" i = %d,id =%d,value = %f,index = %d\n",i,id,global.value,global.index);
 51       picked[i] = global.index;
 52
 53     if(id == global.index)
 54      {
 55        MPI_Bcast(&global.index,1,MPI_INT,id,MPI_COMM_WORLD);
 56      }
 57
 58      MPI_Allgather(&a[id][0],n+1,MPI_DOUBLE,a,n+1,MPI_DOUBLE,MPI_COMM_WORLD);           //每个线程解决的是对应行的求解,例如:线程号为0的线程仅得到0行的解,但是第1行的改动,0线程没有办法得到,只有1线程自己才知道,所以需要使用MPI_Allg          ather()函数进行去收集,并将结果存入到各个线程中,最后各个线程得到a为最新解
 59
 60      if(NotIn(id,picked))
 61      {
 62        double temp = 0 - a[id][i] / a[picked[i]][i];
 63        for(j=i;j<n+1;j++)
 64        {
 65            a[id][j] += a[picked[i]][j] * temp;
 66        }
 67      }
 68
 69   }
 70
 71   MPI_Gather(&a[id][0],n+1,MPI_DOUBLE,a,n+1,MPI_DOUBLE,0,MPI_COMM_WORLD);  //      //解上三角形,因为都需要使用到上一线程的数值,这样造成通信开销增大,不如直接让单一线程去求解上三角形矩阵
 72   if(id == 0)
 73   {
 74      for(i=0;i<n;i++)
 75      {
 76     for(j=0;j<n+1;j++)
 77     {
 78        printf("%f\t",a[i][j]);
 79      }
 80      printf("\n");
 81      }
 82
 83     /* for(i=0;i<n;i++)
 84      {
 85        printf("%d\t",picked[i]);
 86      }
 87      */
 88      double *x;
 89      x = (double *)malloc(sizeof(double) * n);
 90      for(i=(n-1);i>=0;i--)   //这里还有一个小插曲,在这一行的后面加了”;“,导致i变成-1,使程序报错 Segmentation fault (11),在Linux下经常遇到这个问题,大体2点:1.占用的内存超出了系统内存 2.循环中,数组越界
 91      {
 92         //printf("\n n =%d,i = %d",n,i);
 93         x[i] = a[picked[i]][n] / a[picked[i]][i];
 94         printf("x[%d] = %f\n",i,x[i]);
 95         for(j=0;j<n;j++)
 96         {
 97             a[picked[j]][n] = a[picked[j]][n] - x[i] * a[picked[j]][i] ;
 98             a[picked[j]][i] = 0;
 99         }
100
101      }
102    }
103
104
105   MPI_Finalize();
106   return 0;
107 }
108
109
110 int NotIn(int id,int *picked)
111 {
112   int i;
113   for(i=0;i<n;i++)
114   {
115     if(id == picked[i])
116     {
117       return 0;
118     }
119   }
120   return 1;
121 }
时间: 2024-08-05 04:47:52

高斯消去法解线性方程组(MPI)的相关文章

选主元的高斯-约旦(Gauss-Jordan)消元法解线性方程组/求逆矩阵

做数据结构课设时候查的资料,主要是看求逆矩阵方面的知识的. 选主元的高斯-约当(Gauss-Jordan)消元法在很多地方都会用到,例如求一个矩阵的逆矩阵.解线性方程组(插一句:LM算法求解的一个步骤),等等.它的速度不是最快的,但是它非常稳定(来自网上的定义:一个计算方法,如果在使用此方法的计算过程中,舍入误差得到控制,对计算结果影响较小,称此方法为数值稳定的),同时它的求解过程也比较清晰明了,因而人们使用较多.下面我就用一个例子来告诉你Gauss-Jordan法的求解过程吧.顺便再提及一些注

数学-线性代数-#2 用消元法解线性方程组

线性代数-#2 用消元法解线性方程组 #2实现了#1中的承诺,介绍了求解线性方程组的系统方法--消元法. 既然是一种系统的方法,其基本步骤可以概括如下: 1.将方程组改写为增广矩阵: 为了省去传统消元法中反复出现但是没有应用价值的未知数符号和运算符,我们可以将线性方程组表示为增广矩阵的形式,也就是把"Ax=b"中的b附在A右侧; 2.确定第一列中的一个非零元素为主元,以方框框起示之.此元素所在行即为主元行: 一般第n个主元选在第n行.若在进行行变换(交换上下行)后仍没有可供选择的非零元

Matlab应用实例(9)—A\b解线性方程组

说明:A\b用来求解线性方程组,只要写出系数矩阵A和资源向量b,就可以用左除的方法(高斯消元法)得到解.其调用格式为X=A\b. [例1]求下列线性方程组: 解:写成矩阵形式有: 用MATLAB进行求解 主函数: A=[1 -2 3;3 -2 1;1 1 -1]; b=[2;7;1]; X=A\b 解得: X = 1.6250 -1.5000 -0.8750 版权声明:本文为博主原创文章,未经博主允许不得转载.

Eigen解线性方程组

一. 矩阵分解: 矩阵分解 (decomposition, factorization)是将矩阵拆解为数个矩阵的乘积,可分为三角分解.满秩分解.QR分解.Jordan分解和SVD(奇异值)分解等,常见的有三种:1)三角分解法 (Triangular Factorization),2)QR 分解法 (QR Factorization),3)奇异值分解法 (Singular Value Decompostion). LU三角分解: 三角分解法是将原正方 (square) 矩阵分解成一个上三角形矩阵

高斯消去法解线性系统

高斯消去法分为两个过程:第一步是前向消元(forward elimination),也就是将系数矩阵转化成上三角矩阵的过程:第二步是回代(back substitution)过程,自底向上求解方程组的过程. 选择主元(pivoting),主元(pivot)一定不能为0.且主元应当尽可能大.所以一般情况下,我们采取部分选主元(partial pivoting).选择主元为所在各列中绝对值最大的元素(或者非0亦可).然后将对应的该行与主元行进行交换,然后消元. function x = gausse

算法学习#03--详解最小二乘法原理和代码

最小二乘法原理 最小二乘法的目标:求误差的最小平方和,对应有两种:线性和非线性.线性最小二乘的解是closed-form(如下文),而非线性最小二乘没有closed-form,通常用迭代法求解(如高斯牛顿迭代法,本文不作介绍). [首先得到线性方程组] 1.概念 最小二乘法(又称最小平方法)是一种数学优化技术.它通过最小化误差的平方和寻找数据的最佳函数匹配. 利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小. 最小二乘法还可用于曲线拟合. 2.原理 函

matlab求解线性方程组

模电题现在看来是不用matlab解方程不可做了orz 绝望,各种绝望,平时不努力到了期末季就焦虑得不行. 左除法就好 x=A/b; 如果有符号变量,用syms声明一下就好. 越来越懒了orz好吧,解线性方程组这种毫无技术含量的东西用matlab倒是没啥.但是求积分可不能依赖matlab了,现在我积分水平暴低,简直药丸orz

《Numerical Methods》-chaper7-解线性方程组的直接方法和最小二乘问题

基于我们在线性代数中学习过的知识,我们知道解线性方程组本质上就是Gauss消元,也就是基于增广矩阵A的矩阵初等变换.关于数学层面的内容这里不做过多的介绍,这里的侧重点是从数值计算的角度来看这些常见的问题. 那么基于Gauss消元的算法,我们将会很好理解如下的Matlab代码: for j = 1:n-1 for i = j+1 : n mult = A(i,j)/A(j,j); A(i,:) = A(i,:) – mult*A(j,:);    %这里改写成A(i , j:n) = A(i,j:

[线代笔记]第一章 线性方程组解法

第一章 线性方程组解法 代数学起源于解方程(代数方程) 一元一次.一元二次.一元三次.一元四次都有求根公式(通过系数进行有限次加.减.乘.除.乘方.开方得到解),一元五次以上方程就不再有求根公式了(近世代数) 二元一次方程组.三元一次方程组.…….n元一次方程组(线性代数研究对象) 高等代数——线性代数+多项式理论 1. 线性方程组的同解变形.线性组合.初等变换.消去法 例1 同解变形:用3种同解变形必可化方程组为阶梯型 交换两个方程位置 用非0的数c乘某个方程两边 用某个方程的k倍加到另一个方