回 帖 发 新 帖 刷新版面

主题:[讨论]比较了一下串行、并行中的重载函数效率

比较了以下三种情况,有些疑问
1. 串行情况下 matmul
2. OpenMP并行下的matmul
3. OpenMP并行下的matmul的重载函数mt

对附件文件进行编译:
ifort /O3 /Qopenmp mtml_inomp.f90 /link /STACK:50000000,50000000

然后运行 mtml_inomp
在我的电脑上效率是  3>2>1,不明白为什么重载函数效率超过原函数好多

PS:电脑是i7 4核8线程 16G内存
!############################################################
[size=5]###实际问题在2楼###[/size]

回复列表 (共21个回复)

沙发

我在工作站上编译运行了一下, linux redhat6.0, ivf12. 双路的Xeon 5690, 不过有人在用,所以我在代码那里加了限制2个线程.
!! --------------------------------------- !!

[***]$ ifort -V
Intel(R) Fortran Intel(R) 64 Compiler XE for applications running on Intel(R) 64, Version 12.0.5.220 Build 20110719
Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.

!! --------------------------------------- !!

[***]$ ifort -O3 -openmp mtml_inomp.f90 
[***]$ ./a.out
 matmul in Serial program:    12.64220      s
 matmul in Parallel program:    50.33674      s
 overloaded matmul in Parallel program:    98.57339      s

!! --------------------------------------- !!

那两个并行有明显的数据冲突啊... 所以我不知道windows上是怎么处理的,系统是否有介入.
顺便说说, 楼主其实不必最求这样去优化矩阵向量关系, 应该用更优秀的矩阵计算库BLAS代替matmul.

板凳

是的,我知道它是有冲突的,因为能运行我也没去管,这里主要是考察重载的matmul和matmul原函数。用过mkl和imsl的矩阵乘法,发现在/O3 下效率matmul效率不比它们差
但是后来发现类似matmul(a(i).b,c(j).d)格式的乘法效率极低,matmul(a(i)%b,c(j)%d)也一样,而重载后效率有很大提高。
我不知道我的机器和编译器编译出的代码是不是普遍现象,yeg001大哥能否也能编译一下这几行代码试试:
!###################################################
PROGRAM matmul_in_derive
implicit none
    integer:: N=1000,i
    type:: mm
        real(8),allocatable:: mat1(:,:),mat2(:,:),mat3(:,:)
    endtype
    type(mm):: mvp(2)
    real:: t1,t2
    !###########################
    interface
        function mt(x,y)
            implicit none
            real(8),allocatable:: x(:,:),y(:,:)
            real(8),allocatable:: mt(:,:)
        end function
    end interface
    !#############################
    allocate(mvp(1).mat1(N,N),mvp(1).mat2(N,N),mvp(1).mat3(N,N))
    allocate(mvp(2).mat1(N,N),mvp(2).mat2(N,N),mvp(2).mat3(N,N))
    call random_number(mvp(1).mat1)
    call random_number(mvp(1).mat2)
    mvp(2).mat1 = mvp(1).mat1
    mvp(2).mat2 = mvp(1).mat2
    !###################################
    t1 = secnds(0.0)
        mvp(1).mat3 = matmul(mvp(1).mat1,mvp(1).mat2)
    t1 = secnds(t1)
    print*, 'matmul in Serial program: ',t1,' s'
    
    t2 = secnds(0.0)
    mvp(2).mat3 = mt(mvp(2).mat1,mvp(2).mat2)
    t2 = secnds(t2)
    print*, 'overloaded matmul in Serial program: ',t2,' s'
    
END PROGRAM

function mt(x,y)
implicit none
    real(8),allocatable:: x(:,:),y(:,:)
    real(8),allocatable:: mt(:,:)
    allocate(mt(size(x,1),size(y,2)))
    mt = matmul(x,y)
end function
!#####################################################
D:\Desktop>ifort /O3 note.f90 /link /STACK:50000000
Intel(R) Visual Fortran Compiler XE for applications running on IA-32, Version 1
2.0.5.221 Build 20110719
Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.

Microsoft (R) Incremental Linker Version 10.00.30319.01
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:note.exe
-subsystem:console
/STACK:50000000
note.obj

D:\Desktop>note
 matmul in Serial program:    7.008594      s
 overloaded matmul in Serial program:   0.4877813      s

结果看出重载过的matmul效率很高,很奇怪……

3 楼

还是上面的机器.

[***]$ ifort -O3 testMatmul_defTYPE.f90 
[***]$ ./a.out
 matmul in Serial program:    2.391108      s
 overloaded matmul in Serial program:    3.051880      s


你的情况确实很奇怪. 你这么一说我有印象好像之前讨论过.
要不试试分开两个程序来计算. 分别来测试两者的计算时间. 我想会不会有缓冲啊什么的还没有清掉就计算第二个然后得到了好处? 也知识猜的, 只是确实没道理间接的比直接的还快.

4 楼

谢谢,上次也是我提出的,不过情况略有不同
我在非至强机器上也是有问题的,我在intel官网上挂了这个问题
http://software.intel.com/en-us/forums/showthread.php?t=104335&p=1#180613

不太明白那个intel工程师说的,If the compiler allocated plain temporary arrays as arguments to matmul, this would be an example where that is a useful transformation.  I guess you didn't set options implying /Qopt-matmul; to implement that, the temporary arrays would be required in both cases (but you would be confused if you used the legacy secnds timer).

both cases 不知指的什么

5 楼

我不知道/Qopt-matmul是什么编译参数. 我没看明白他的意思. intel论坛很久没上了, 今晚申请了一下"忘记密码"等明天邮箱收到密码我也把linux的结果贴上去,问问他们是不是与系统有关系.

6 楼

谢谢yeg001,坐等intel牛人的解答了

7 楼

我以前知识去汇报些bug,之前发的几个贴都是ivf上的openmp遇到的问题. 很少就性能方面在那里发帖.
我看了一下你之前的几个帖子,似乎他们也没有完全解释清楚.
那个:matmul speed test with 4 situation
http://software.intel.com/en-us/forums/showthread.php?t=102213

有没有按照其中某个人说的把situation的顺序换一下测试结果? 好像几个帖子不了了之啊.

8 楼

对,以前的问题后来情况变了,后来老板给我们换电脑后,那四种情况出的结果已经没有问题了,具体原因不明。
现在的情况是把 matmul(a.b,c.d)换成matmul(a(i).b,c(j).d)的形式效率变得很低(其中a(i).b和c(j).d都是allocatable矩阵),这就是这次出现的问题了。实际上现在可以用 重载后的matmul解决,但是就是有一种没弄明白被编译器忽悠的感觉。

9 楼

原生matmul的代码一般来说对于小矩阵效率会较高,而优化的matmul算法则相当于使用了优化的gemm。对于大矩阵效率会高些,但小矩阵则反而会降低。

10 楼

谢谢,不过你可能没有看清楚,这里并不是讨论matmul的效率问题,而是matmul函数在对于类似a(i).b这样的实参数效率低下的问题

我来回复

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