找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5846|回复: 0
打印 上一主题 下一主题
收起左侧

高斯消去法(LU分解)SSE并行化研究报告 带源代码

[复制链接]
跳转到指定楼层
楼主
ID:186175 发表于 2017-4-5 08:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
高斯消去法SSE并行化研究报告
一、         问题描述
题目:高斯消去法(LU分解)串行算法如下面伪代码所示,计算模式如图1所示(第k步时第k行的除法运算,和后续行减去第k行的运算)。设计实现SSE算法,加速计算过程。提交研究报告(问题描述、SSE算法设计与实现、实验及结果分析)和源码(只将程序文件和工程文件提交,不要将编译出的目标文件和可执行文件也打包提交)。
1.procedure LU (A)
2. begin
3.    for k := 1 to n do
4.           for j := k+1 to n do
5.                  A[k, j] := A[k, j]/A[k, k];
6            A[k, k] := 1.0;
7.           endfor;
8.           for i := k + 1 to n do
9.                  for j := k + 1 to n do
10.                       A[i, j] := A[i, j] - A[i,k] × A[k, j ];
11.         endfor;
12.         A[i, k] := 0;
13.  endfor;
14.endfor;
15. end LU
综合以上分析一下,作业的目的就是找到上面的算法可以并行执行的部分,将这部分用SSE实现,并且测试所用时间,再改变问题规模,观察随着问题规模的变化,所用时间与串行时间比例的变化。最后分析一下判断并行算法的性能是否足够好。
二、         SSE算法设计和实现
算法设计:
分析此算法,首先外层循环无法并行化,因为在不同的循环中,相同位置的元素都会改变。内部的将对角线元素变为1和下面元素变为0都是可以并发执行的。由此获得解题思路。但是在实际操作的工程中发现并行运行时间有时候要比串行运行时间多,所以又进行了部分并行(只对置零操作进行并行),发现有时候要比全部并行的效果好。
实现:
1)          基本串行算法:
voidbasic_change() {//基本的串行算法
     for (int k =0; k < MAX; k++)
     {
         for (int j =k; j < MAX; j++)
              A[k][j] /= A[k][k];
         A[k][k] = 1;
         for (int i =k + 1; i < MAX; i++)
          {
              for (int j =k + 1; j < MAX; j++)
                   A[ i][j] = A[ i][j] - A[ i][k] *A[k][j];
              A[ i][k] = 0;
         }
     }
}
2)          并行算法:
voidpara_change_impr() {//并行算法
     __m128 t1,t2, t3;
     for (int k =0; k < MAX; k++)
     {
//此处需要并行处理
         int off= (MAX - k - 1) % 4;
         for (int j =k + 1; j < k + 1 + off; j++)
              A[k][j] /= A[k][k];
         t2=_mm_loadu_ps(A[k] + k);
         for (int j =k + 1 + off; j < MAX; j += 4)
         {
              t1 =_mm_loadu_ps(A[k] + j);
              t1 =_mm_div_ps(t1,t2);
              _mm_store_ss(A[k] + j, t1);
         }
         A[k][k] = 1;
         for (int i =k + 1; i < MAX; i++)
         {
              //此处不再以1位单位而是以4为单位进行循环
              for (int j =k + 1; j < k + 1 + off; j++)
                   A[ i][j] = A[ i][j] - A[ i][k] *A[k][j];
              for (int j =k + 1 + off; j < MAX; j += 4)
              {
                   t2 =_mm_loadu_ps(A[ i] + k);
                   t3 =_mm_loadu_ps(A[k] + j);
                   t1 =_mm_loadu_ps(A[ i] + j);
                   t2 =_mm_mul_ps(t2, t3);
                   t1 =_mm_sub_ps(t1, t2);
                   _mm_store_ss(A[ i] + j, t1);
              }
              A[ i][k] = 0;
         }
     }
}
3)          部分并行:
voidpara_change() {//并行算法
     __m128 t1,t2, t3;
     for (int k =0; k < MAX; k++)
     {
         for (int j =k + 1; j < MAX; j++)
              A[k][j] /= A[k][k];
         A[k][k] = 1;
         //此处需要并行处理
         for (int i =k + 1; i < MAX; i++)
         {
              //此处不再以1位单位而是以4为单位进行循环
              int off= (MAX - k - 1) % 4;
              for (int j =k + 1; j < k + 1 + off; j++)
                   A[ i][j] = A[ i][j] - A[ i][k] *A[k][j];
              for (int j =k + 1 + off; j < MAX; j += 4)
              {
                   t2 =_mm_loadu_ps(A[ i] + k);
                   t3 =_mm_loadu_ps(A[k] + j);
                   t1 =_mm_loadu_ps(A[ i] + j);
                   t2 =_mm_mul_ps(t2, t3);
                   t1 =_mm_sub_ps(t1, t2);
                   _mm_store_ss(A[ i] + j, t1);
              }
              A[ i][k] = 0;
         }
     }
}
三、         实验及结果分析
  
矩阵规模
  
10
100
1000
512
1024
串行运行时间
0.0030ms
1.8973ms
1794.62ms
343.542ms
2707.7ms
部分并行
0.0316ms
1.5394ms
1581.11ms
  
291.542ms
1505ms
并行
0.8534ms
2.5583ms
1831.7ms
156.443ms
1471.66ms
串行/部分并行
0.094937
1.232493
1.135038
1.178362
0.179914
串行/
  
并行
0.003515
0.741625
0.979757
2.195956
1.839895
注:实验结果为每次运行5次程序取平均值
根据实验数据绘制以下图表:
从图表中可以明显看出来,在运算的数据较少的时候,并行算法和串行算法的速率几乎没有区别,串行算法甚至比并行算法快。但是随着数据量的增长,可以明显看到并行速度要比串行的速度快很多。注意其中的数据量为512和1024的位置,要比之前快的还要明显。尤其是数据量为1000和1024的对比。说明当数据量为4的整数倍的时候,SSE并行算法发挥的用更大一些。
这张图中看的更明显一些。在数据量为512的时候,速率比要比在1000的时候高。当数据量为1024的时候,只是比1000多了24个数据,但是速率明显的提升了。
从图中可以看出,在数据量为1000左右的时候,部分并行是要快于全部并行的。
总结:
此并行算法对串行算法进行了性能上的优化。在数据量越来越多的时候,优化的效果也越来越好。并且当数据量为4的整数倍的时候,优化效果尤其明显。
附加:
在做完实验之后,我在想并行算法中,如果先处理大部分数据,之后处理小于4个的数据,效率会不会有变化,所以添加了以下实验:
  
矩阵规模
  
10
100
1000
512
1024
先算4的倍数个数据
0.0315734ms
1.53941ms
1581.11ms
291.542ms
1505ms
后算4的倍数个数据
0.00384ms
1.59957ms
1288.09ms
247.643ms
1383.1ms
前者/后者
8.222
0.962
1.223
1.177
1.090
观察可以看到,除了在数据过小的时候结果有一些偏差以外,其他情况两种并行算法的方式都是差不多的。但同时可以看出来先处理大部分数据再处理小部分数据要快一些。
在全部完成后,使用codeblock重复以上实验步骤,使用了-O2加速(因为-O3本身采取的就是SSE方式,所以采用了-O2加速)。
得到如下实验结果:
  
矩阵规模
  
10
100
1000
512
1024
串行运行时间
0.00298666ms
2.39232ms
1230.66ms
212.315ms
1349.82ms
部分并行
0.00341333ms
0.707839ms
391.611ms
  
66.3569ms
462.897ms
并行
0.0136533ms
1.05472ms
471.08ms
64.1954ms
359.968ms
串行/部分并行
0.874999
3.379752
3.142557
3.199592
2.916027
串行/
  
并行
0.21875
2.268204
2.612423
3.307324
3.749833
得到以下图表:
  
从表格和图表中可以看出,在数据较小的时候,由于并行本身的花销,串行算法要优于并行算法。随着数据量的增加,串行算法的运行时间线性增加,但并行算法的固定开销却是稳定在一定范围内的,甚至在数据量达到一定规模的时候,这个开销可以忽略。所以时间比越来越大,最后甚至大于三倍。再看部分并行和全部并行。在数据量处于中间范围的时候,可以看出部分并行要比全部并行的加速比大,推测还是并行开销的问题。当数据量逐渐增加的时候,在图中可以看出在数据量大于1000的时候,全部并行的加速比要大于部分并行的加速比。以后可以根据数据规模选择并行程度。
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表