回 帖 发 新 帖 刷新版面

主题:请教matmul效率, 跟Blas比较.

请问有人把矩阵操作和向量操作运算跟BLAS的比较过吗? 如果有可不可以谈谈经验?

回复列表 (共56个回复)

31 楼

哈. 如果你一定要打破砂锅问到底, 搞清楚这中间的关系, 也是可以的. 

编译器都有控制"描写"的选项, 比如gfortran的 -p选项, 大致过程如下: 编译的时候加上这个选项, 编译器会在程序中插入小段代码, 这些代码将做相关统计, 你把程序运行一遍, 统计结果会写到一个文件中, 察看该文件就可以知道程序中每个子过程的运行时间. 有这种技术作基础, 你就能弄清楚上面的疑问.

除此之外, intel给出了更好的方法, intel处理器内部有相关硬件设施用于计数, 由软件开关控制. intel提供了专门的软件vtune 用于统计这些计数, intel称vtune是一种观察工具, 观察的对象是他所说的"代码与cpu的相互作用”. 不仅仅是统计各子程序的时间, 可观察的还有cpu分支预测错误、缓存缺失等大量信息,帮助程序员改善程序。

以这种技术为基础, 统计各个子程序的时间易如反掌, 事实上可以做得更多, 由于调试选项是在程序中插入信息, 表示某段代码与源程序中的某行是相关的, 所以把vtune观察工具与调试选项联用, 可以精确知道每一行源程序的运行时间.

掌握这些绝活很让人上瘾,但是还是上面那句话,优化不能走上极端,投入精力过多的话还不如购买更强的计算机。把自己的精力花在刀刃上。

32 楼

我也觉得有一点陷入"优化门"了. 那些工具还是有时间要学学.
既然这个问题不是那么简单那么还是抓紧时间算东西要紧. 以后毕业了什么都好说.
谢谢各位给的中肯的意见.

33 楼

大家说的非常有道理,把时间用到刀刃上,等以后时间好好研究。我以前想在编程技巧上做功夫,浪费许多时间。换台电脑很多问题都解决。采用最简单的办法,能把计算速度相对提高就行,做到最高,太难了。

34 楼

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 楼

而使用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 楼

[quote][quote]编译好的库的效率都没直接使用源代码来的快

直接使用blas源代码,就是编译时间长一些。
编译开关为 ifort /O3 /fast /QxHost
测试结果为
 使用matmul : 4.140625s
 直接使用blas源代码里的dgemm: 0.03125s[/quote]
请问blas源代码是指lapack里面带的原始代码吗?[/quote]
我用的是在netlib里下载的Blas源码,在一堆文件中,您只需要用到三个文件:
dgemm
lsame
xerbla

37 楼

我确实忽略了小规模矩阵这一块. 跟我要算的东西矩阵都是上百上千阶有关.
cgl_lgs 兄说起的并行, GOTOBlas2在编译过程中默认是开了并行开关的. 我也应用到我的程序里面, 可惜看到的效果并不明显. 程序整体速度是有提升但是所有线程使用的cpu_time比串行的多出不少.
如果是小规模的矩阵相乘这里使用并行我觉得会得不偿失. 还是在更高层的地方考虑并行算法好些.
让我想起一个问题, 不知道Blas本身是否thread-save线程安全的呢?

38 楼


为什么动态数组的计算时间比静态数组多呢?
我的数组都是动态的。

39 楼

[quote]
为什么动态数组的计算时间比静态数组多呢?
我的数组都是动态的。[/quote]
动态的取数组中数据是在堆上使用相对寻址取,而局部的是在栈上取。

40 楼

[quote]我确实忽略了小规模矩阵这一块. 跟我要算的东西矩阵都是上百上千阶有关.
cgl_lgs 兄说起的并行, GOTOBlas2在编译过程中默认是开了并行开关的. 我也应用到我的程序里面, 可惜看到的效果并不明显. 程序整体速度是有提升但是所有线程使用的cpu_time比串行的多出不少.
如果是小规模的矩阵相乘这里使用并行我觉得会得不偿失. 还是在更高层的地方考虑并行算法好些.
让我想起一个问题, 不知道Blas本身是否thread-save线程安全的呢?[/quote]
俺在使用F编程时,尽量不去按用C/C++时的思想做,所以从不手工开线程:)能自动优化的东西留给编译器做去,俺就做模型上的优化(这个才往往是卓有成效的):)
yeg001兄还有这样的矩阵啊,总是满阵计算确实很头痛啊,如果能改改数学模型减少计算量就好了:)

我来回复

您尚未登录,请登录后再回复。点此登录或注册