主题:请教matmul效率, 跟Blas比较.
yeg001
[专家分:14390] 发布于 2010-04-22 00:44:00
请问有人把矩阵操作和向量操作运算跟BLAS的比较过吗? 如果有可不可以谈谈经验?
回复列表 (共56个回复)
31 楼
f2003 [专家分:7960] 发布于 2010-06-29 20:10:00
哈. 如果你一定要打破砂锅问到底, 搞清楚这中间的关系, 也是可以的.
编译器都有控制"描写"的选项, 比如gfortran的 -p选项, 大致过程如下: 编译的时候加上这个选项, 编译器会在程序中插入小段代码, 这些代码将做相关统计, 你把程序运行一遍, 统计结果会写到一个文件中, 察看该文件就可以知道程序中每个子过程的运行时间. 有这种技术作基础, 你就能弄清楚上面的疑问.
除此之外, intel给出了更好的方法, intel处理器内部有相关硬件设施用于计数, 由软件开关控制. intel提供了专门的软件vtune 用于统计这些计数, intel称vtune是一种观察工具, 观察的对象是他所说的"代码与cpu的相互作用”. 不仅仅是统计各子程序的时间, 可观察的还有cpu分支预测错误、缓存缺失等大量信息,帮助程序员改善程序。
以这种技术为基础, 统计各个子程序的时间易如反掌, 事实上可以做得更多, 由于调试选项是在程序中插入信息, 表示某段代码与源程序中的某行是相关的, 所以把vtune观察工具与调试选项联用, 可以精确知道每一行源程序的运行时间.
掌握这些绝活很让人上瘾,但是还是上面那句话,优化不能走上极端,投入精力过多的话还不如购买更强的计算机。把自己的精力花在刀刃上。
32 楼
yeg001 [专家分:14390] 发布于 2010-06-29 23:03:00
我也觉得有一点陷入"优化门"了. 那些工具还是有时间要学学.
既然这个问题不是那么简单那么还是抓紧时间算东西要紧. 以后毕业了什么都好说.
谢谢各位给的中肯的意见.
33 楼
vehicle [专家分:310] 发布于 2010-06-30 11:25:00
大家说的非常有道理,把时间用到刀刃上,等以后时间好好研究。我以前想在编程技巧上做功夫,浪费许多时间。换台电脑很多问题都解决。采用最简单的办法,能把计算速度相对提高就行,做到最高,太难了。
34 楼
cgl_lgs [专家分:21040] 发布于 2010-07-04 08:44:00
yeg001兄使用的是静态分配数组,俺试了一下动态分配的。噢,买嘎~~~~
结果:
!动态部分结果:
consumed CPU_time(s): 3.2604209000
consumed CPU_time(s): 0.2340015000
!静态部分结果:
consumed CPU_time(s): 2.1684139000
consumed CPU_time(s): 0.1716011000
当然,俺滴测试程序稍有不同:
! 测试BLAS与MatMul效率的程序:)
! 好小爱新 参考 pfan.yeg001兄写于 2010年7月3日
Program test1
Implicit None
Integer,Parameter:: matsize_r=12,matsize_c=1,times=2D7 ! 3D梁单元使用的矩阵大小 及 计算量
!Integer,Parameter:: matsize_r=2000,matsize_c=2000,times=1 ! yeg001兄使用的矩阵大小 及 计算量
Integer i
Real*8,Allocatable:: A(:,:), B(:,:)
Real*8,Allocatable:: C(:,:), D(:,:) ! 动态滴
Real*8 AS(matsize_r,matsize_r), BS(matsize_r,matsize_c)
Real*8 CS(matsize_r,matsize_c), DS(matsize_r,matsize_c) ! 静态滴
Real*8 time_begin, time_end
! 给需要动态分配内存的数组分配空间:)
Allocate(A(matsize_r,matsize_r),B(matsize_r,matsize_c),C(matsize_r,matsize_c),D(matsize_r,matsize_c))
! 初始化
Call RANDOM(A)
Call RANDOM(B)
! 为公平起见,AS与BS直接使用A和B的值:)
AS=A;BS=B
! -----------俺-----是-----分-----隔-----线---------------------------动态部分
Call CPU_TIME(time_begin)
Do i=1,times
C=MatMul(A, B)
B=C
End Do
Call CPU_TIME(time_end)
Write(*,'(A,F16.10)')"consumed CPU_time(s):", time_end - time_begin
Call CPU_TIME(time_begin)
Do i=1,times
Call dgemm('N', 'N', matsize_r, matsize_c, matsize_c, 1.0_8, A, matsize_r, B, matsize_c, 0.0_8, D, matsize_r)
B=D
End Do
Call CPU_TIME(time_end)
Write(*,'(A,F16.10)')"consumed CPU_time(s):", time_end - time_begin
! -----------俺-----是-----分-----隔-----线---------------------------静态部分
Call CPU_TIME(time_begin)
Do i=1,times
CS=MatMul(AS, BS)
BS=CS
End Do
Call CPU_TIME(time_end)
Write(*,'(A,F16.10)')"consumed CPU_time(s):", time_end - time_begin
Call CPU_TIME(time_begin)
Do i=1,times
Call dgemm('N', 'N', matsize_r, matsize_c, matsize_c, 1.0_8, AS, matsize_r, BS, matsize_c, 0.0_8, DS, matsize_r)
BS=DS
End Do
Call CPU_TIME(time_end)
Write(*,'(A,F16.10)')"consumed CPU_time(s):", time_end - time_begin
Deallocate(A,B,C,D)
End Program test1
35 楼
cgl_lgs [专家分:21040] 发布于 2010-07-04 08:53:00
而使用yeg001兄滴矩阵大小及计算量则:
!动态部分
consumed CPU_time(s): 6.2556401000
consumed CPU_time(s): 0.0624004000
!静态部分
consumed CPU_time(s): 3.4788223000
consumed CPU_time(s): 0.0468003000
由此可以看出:
其实咱常用的矩阵大小只有在一定运算次数下才会有性能上的提升,否则对于一个计算需要数分钟的非线性有限元程序来说,提升了几秒几乎可以忽略不计。
但是我们如果在解方程这部分狠下努力,提升其可并行性,减少其计算量,那效率将是成N倍的提升:)
36 楼
cgl_lgs [专家分:21040] 发布于 2010-07-04 09:05:00
[quote][quote]编译好的库的效率都没直接使用源代码来的快
直接使用blas源代码,就是编译时间长一些。
编译开关为 ifort /O3 /fast /QxHost
测试结果为
使用matmul : 4.140625s
直接使用blas源代码里的dgemm: 0.03125s[/quote]
请问blas源代码是指lapack里面带的原始代码吗?[/quote]
我用的是在netlib里下载的Blas源码,在一堆文件中,您只需要用到三个文件:
dgemm
lsame
xerbla
37 楼
yeg001 [专家分:14390] 发布于 2010-07-04 10:46:00
我确实忽略了小规模矩阵这一块. 跟我要算的东西矩阵都是上百上千阶有关.
cgl_lgs 兄说起的并行, GOTOBlas2在编译过程中默认是开了并行开关的. 我也应用到我的程序里面, 可惜看到的效果并不明显. 程序整体速度是有提升但是所有线程使用的cpu_time比串行的多出不少.
如果是小规模的矩阵相乘这里使用并行我觉得会得不偿失. 还是在更高层的地方考虑并行算法好些.
让我想起一个问题, 不知道Blas本身是否thread-save线程安全的呢?
38 楼
vehicle [专家分:310] 发布于 2010-07-04 18:11:00
为什么动态数组的计算时间比静态数组多呢?
我的数组都是动态的。
39 楼
cgl_lgs [专家分:21040] 发布于 2010-07-05 10:44:00
[quote]
为什么动态数组的计算时间比静态数组多呢?
我的数组都是动态的。[/quote]
动态的取数组中数据是在堆上使用相对寻址取,而局部的是在栈上取。
40 楼
cgl_lgs [专家分:21040] 发布于 2010-07-05 11:09:00
[quote]我确实忽略了小规模矩阵这一块. 跟我要算的东西矩阵都是上百上千阶有关.
cgl_lgs 兄说起的并行, GOTOBlas2在编译过程中默认是开了并行开关的. 我也应用到我的程序里面, 可惜看到的效果并不明显. 程序整体速度是有提升但是所有线程使用的cpu_time比串行的多出不少.
如果是小规模的矩阵相乘这里使用并行我觉得会得不偿失. 还是在更高层的地方考虑并行算法好些.
让我想起一个问题, 不知道Blas本身是否thread-save线程安全的呢?[/quote]
俺在使用F编程时,尽量不去按用C/C++时的思想做,所以从不手工开线程:)能自动优化的东西留给编译器做去,俺就做模型上的优化(这个才往往是卓有成效的):)
yeg001兄还有这样的矩阵啊,总是满阵计算确实很头痛啊,如果能改改数学模型减少计算量就好了:)
我来回复