黑马程序员____矩阵相乘常规法和Strassen方法算法分析
2012-09-17 12:43
531 查看
----------------------android培训、java培训、期待与您交流!
----------------------
矩阵相乘是计算机编程领域的常见问题。按照常规方法解决问题的算法复杂度为,在矩阵规模超过一定规模后,复杂度增长使得计算时间过长,无法令人满意。显然,矩阵相乘的下界在,但这个想法过于理想。目前得到的最优方案为,由于最优方案的实现过于复杂,没有在计算机上完美实现。Strassen方法通过分治递归的思想,将算法的复杂度降到了左右,并且实现较为简单。本实验的目的就是在程序实现矩阵相乘常规法和Strassen方法的基础上,比较两者在不同数据规模下的速度。
一、
算法分析
1.
矩阵相乘常规法
伪码实现如下:
MATRIX-MULTIPLY(A, B)
n ← rows[A]
let C be an n × n matrix
for i ← 1 to n
do for j ← 1 to n
do cij ← 0
for k ← 1 to n
do cij ← cij + aik× bkj
return C
通过伪代码循环嵌套的分析,可以直观地看出算法复杂度为。
2.
矩阵相乘Strassen法
将一个 n × n的矩阵乘法分割为 2 × 2个(n/2) × (n/2)大小的子矩阵相乘。
P1=a
⋅(f−h)
P2= (a+
b)⋅h
P3= (c+
d)⋅e
P4=d
⋅(g−e)
P5= (a+
d)⋅(e+h)
P6= (b−d)⋅(g+h)
P7= (a−c)⋅(e+f
)
r =P5+
P4−P2+P6
s =P1+
P2
t =P3+
P4
u =P5+
P1−P3−P7
这样在子矩阵的加乘法中,一共涉及到7次乘法,由于在大规模矩阵的情况下,矩阵相乘的复杂度远大于加减矩阵的复杂度,所以Strassen算法比常规法有所改进(Strassen方法的正确性在此略过)。
算
b81c
法复杂度得到一定的改进。
程序在实现的过程中。有时会碰到分割出的矩阵的n不为偶数的情形,此时应对矩阵加一条零边,使分割顺利进行,而不影响计算结果。
分割出的矩阵使用动态二维矩阵存储,节约存储空间。在矩阵使用完以后及时回收,以免堆内存溢出。
The Source matrix is displayed below:
1 7 4 0 9
4 8 8 2 4
5 5 1 7 1
1 5 2 7 6
1 4 2 3 2
The Target matrix is displayed below:
2 1 6 8 5
7 6 1 8 9
2 7 9 5 4
3 1 2 3 3
4 1 1 3 8
常规法所得结论:
The Result matrix is displayed below:
95 80 58 111 156
102 114 112 154 162
72 50 59 109 103
86 58 49 97 127
51 44 36 65 74
Strassen法所得结论:
The Result matrix is displayed below:
95 80 58 111 156
102 114 112 154 162
72 50 59 109 103
86 58 49 97 127
51 44 36 65 74
根据手动计算结果,均正确。
压力测试(不同数据规模下运行速度):(单位为秒)
图表1
表格1
数据取600位上界,即超过10分钟跳出。可以看到使用Strassen算法时,耗时不但没有减少,反而剧烈增多,在n=700时计算时间就无法忍受。仔细研究后发现,采用Strassen算法作递归运算,需要创建大量的动态二维数组,其中分配堆内存空间将占用大量计算时间,从而掩盖了Strassen算法的优势。于是对Strassen算法做出改进,设定一个界限。当n<界限时,使用普通法计算矩阵,而不继续分治递归。
改进后算法优势明显,就算时间大幅下降。之后,针对不同大小的界限进行试验。在初步试验中发现,当数据规模小于1000时,下界S法的差别不大,规模大于1000以后,n取值越大,消耗时间下降。最优的界限值在32~128之间。
因为计算机每次运算时的系统环境不同(CPU占用、内存占用等),所以计算出的时间会有一定浮动。虽然这样,试验结果已经能得出结论Strassen算法比常规法优势明显。使用下界法改进后,在分治效率和动态分配内存间取舍,针对不同的数据规模稍加试验可以得到一个最优的界限。
四、 实验小结
本次实验成功实现了矩阵相乘的常规法和Strassen算法,发现了Strassen算法在使用动态内存分配时的缺陷,并进行改进。实验中还发现Strassen算法消耗内存明显,在使用空间换取时间时要进行适当取舍。
---------------------- android培训、java培训、期待与您交流!
----------------------
详细请查看:http://edu.csdn.net/heima
----------------------
矩阵相乘是计算机编程领域的常见问题。按照常规方法解决问题的算法复杂度为,在矩阵规模超过一定规模后,复杂度增长使得计算时间过长,无法令人满意。显然,矩阵相乘的下界在,但这个想法过于理想。目前得到的最优方案为,由于最优方案的实现过于复杂,没有在计算机上完美实现。Strassen方法通过分治递归的思想,将算法的复杂度降到了左右,并且实现较为简单。本实验的目的就是在程序实现矩阵相乘常规法和Strassen方法的基础上,比较两者在不同数据规模下的速度。
一、
算法分析
1.
矩阵相乘常规法
伪码实现如下:
MATRIX-MULTIPLY(A, B)
n ← rows[A]
let C be an n × n matrix
for i ← 1 to n
do for j ← 1 to n
do cij ← 0
for k ← 1 to n
do cij ← cij + aik× bkj
return C
通过伪代码循环嵌套的分析,可以直观地看出算法复杂度为。
2.
矩阵相乘Strassen法
将一个 n × n的矩阵乘法分割为 2 × 2个(n/2) × (n/2)大小的子矩阵相乘。
P1=a
⋅(f−h)
P2= (a+
b)⋅h
P3= (c+
d)⋅e
P4=d
⋅(g−e)
P5= (a+
d)⋅(e+h)
P6= (b−d)⋅(g+h)
P7= (a−c)⋅(e+f
)
r =P5+
P4−P2+P6
s =P1+
P2
t =P3+
P4
u =P5+
P1−P3−P7
这样在子矩阵的加乘法中,一共涉及到7次乘法,由于在大规模矩阵的情况下,矩阵相乘的复杂度远大于加减矩阵的复杂度,所以Strassen算法比常规法有所改进(Strassen方法的正确性在此略过)。
算
b81c
法复杂度得到一定的改进。
二、程序实现
关键步骤说明程序在实现的过程中。有时会碰到分割出的矩阵的n不为偶数的情形,此时应对矩阵加一条零边,使分割顺利进行,而不影响计算结果。
分割出的矩阵使用动态二维矩阵存储,节约存储空间。在矩阵使用完以后及时回收,以免堆内存溢出。
三、测试程序
范例测试(正确性测试)The Source matrix is displayed below:
1 7 4 0 9
4 8 8 2 4
5 5 1 7 1
1 5 2 7 6
1 4 2 3 2
The Target matrix is displayed below:
2 1 6 8 5
7 6 1 8 9
2 7 9 5 4
3 1 2 3 3
4 1 1 3 8
常规法所得结论:
The Result matrix is displayed below:
95 80 58 111 156
102 114 112 154 162
72 50 59 109 103
86 58 49 97 127
51 44 36 65 74
Strassen法所得结论:
The Result matrix is displayed below:
95 80 58 111 156
102 114 112 154 162
72 50 59 109 103
86 58 49 97 127
51 44 36 65 74
根据手动计算结果,均正确。
压力测试(不同数据规模下运行速度):(单位为秒)
图表1
表格1
数据取600位上界,即超过10分钟跳出。可以看到使用Strassen算法时,耗时不但没有减少,反而剧烈增多,在n=700时计算时间就无法忍受。仔细研究后发现,采用Strassen算法作递归运算,需要创建大量的动态二维数组,其中分配堆内存空间将占用大量计算时间,从而掩盖了Strassen算法的优势。于是对Strassen算法做出改进,设定一个界限。当n<界限时,使用普通法计算矩阵,而不继续分治递归。
改进后算法优势明显,就算时间大幅下降。之后,针对不同大小的界限进行试验。在初步试验中发现,当数据规模小于1000时,下界S法的差别不大,规模大于1000以后,n取值越大,消耗时间下降。最优的界限值在32~128之间。
因为计算机每次运算时的系统环境不同(CPU占用、内存占用等),所以计算出的时间会有一定浮动。虽然这样,试验结果已经能得出结论Strassen算法比常规法优势明显。使用下界法改进后,在分治效率和动态分配内存间取舍,针对不同的数据规模稍加试验可以得到一个最优的界限。
四、 实验小结
本次实验成功实现了矩阵相乘的常规法和Strassen算法,发现了Strassen算法在使用动态内存分配时的缺陷,并进行改进。实验中还发现Strassen算法消耗内存明显,在使用空间换取时间时要进行适当取舍。
---------------------- android培训、java培训、期待与您交流!
----------------------
详细请查看:http://edu.csdn.net/heima
相关文章推荐
- Strassen 矩阵相乘算法(转)
- Strassen方法完成N*N矩阵的相乘
- Conquer-Divide的经典例子之Strassen算法解决大型矩阵的相乘
- 算法实践篇-2的n次方方正相乘普通方法,递归方法以及strassen方法
- 算法导论 矩阵相乘(Strassen方法)
- 时间复杂度算法分析有方法(摘)
- opencv 矩阵与一个常数相乘的 两种实现方法
- 算法--生成m个指定范围的不重复随机数的三种方法分析(Java实现)
- STL堆算法性能分析与优化方法
- 【算法】算法分析与设计的基本方法
- [算法] 矩阵相乘
- Java遍历集合的几种方法分析(实现原理、算法性能、适用场合)
- STL堆算法性能分析与优化方法(GCC4.4.2 stl_heap.h源代码分析与改进方案)
- 矩阵相乘strassen-c++代码实现及运行实例结果
- strassen方法求任意行列数的矩阵乘法
- 算法设计分析之一(平摊分析,表扩增,势能方法)
- 名企笔试:搜狗2016研发工程师笔试(矩阵元素相乘)2017-03-13 算法爱好者
- 快速矩阵乘法:Strassen 演算法
- Linux下的cryptoloop的使用方法和算法分析
- 两个二维矩阵相乘的算法