24小时热门版块排行榜    

CyRhmU.jpeg
查看: 2524  |  回复: 9
本帖产生 1 个 程序强帖 ,点击这里进行查看
当前只显示满足指定条件的回帖,点击这里查看本话题的所有回帖

coolrainbow

木虫 (著名写手)

未来国家冻凉

[交流] 【转帖】intel Fortran编译器的一个“危险”优化已有9人参与

源地址:http://hi.baidu.com/coolrainbow/ ... d6c40c5aaf535e.html

今天无意中发现了intel编译器优化的一个问题。我有一个程序,大致是这样

program main
    integer, parameter :: n = 1000
    real(kind = 8) value(n)
    integer i
   
    call computation(value)

    do i = 1, n
         write (*,*) value(n)
    enddo
end

其中computation是一个计算量极大的subroutine。利用intel编译编译,分别令n = 1000和n = 5000,不优化和优化执行的时间

n           1000              5000
O0        12min             60min
O2          7min             36min

后来,我无意中将输出函数的代码取消了,也即:

program main
    integer, parameter :: n = 1000
    real(kind = 8) value(n)
    integer i
   
    call computation(value)
end

再次运行,惊现!

n           1000              5000
O0        11min30s          59min
O2         0.003s            0.003s

看到这种结果,我目瞪口呆,可是当我发现n=1000和5000是执行时间相同,我就猜测computation这个子过程根本就没有执行。那么为什么没执行呢?我猜测:intel编译器在O2过程中,发现后续代码没有用到value这个数组,也没有牵扯到computation函数内部的任何内容,因此干脆将其优化掉了

这个猜测对吗?决定看一下。在n=1000时候,我将两段代码编译成汇编语言:
ifort -O0 -o pO0.s -S   foo.f90
ifort -O2 -o pO2.s -S   foo.f90

首先观察pO0.s,发现:

# -- Begin MAIN__
.........
   call      foo_mp_computation_                #369.10
........
# -- End MAIN__

果然,main中调用了computation函数。再看pO2.s,我们发现:

# -- Begin MAIN__
........
# -- End MAIN__

确确实实没有发现computation函数调用的汇编代码,哈哈,看来我的推测是对的。

下面这段比较小的代码,大家可以自己用编译器编译一下,我用ifort编译了一下,和上面是一样的,通过汇编语言可以发现,开启O2时,汇编代码的MAIN中没有出现调用perform函数的内容。当然,如果我说的不对,希望大家指教,呵呵。

subroutine perform(value, n)
   integer n
   real(kind = 8) value(n)

   integer i

   do i = 1, n
       value(i) = 2.0*i
   enddo
return
end subroutine


program main

   integer, parameter :: n = 10
   real(kind = 8) value(n)

   call perform(value,n)

end

事实上,这个例子表明,编译器的优化选项确实有一定的危险性,尽管在这个例子中,并没有什么问题,但是在投产级别的软件中启动优化选项时的确要慎重,一般不要启用O3这种激进的优化,即使启用也一定要试验确定代码无误后才行
回复此楼

» 猜你喜欢

» 本主题相关价值贴推荐,对您同样有帮助:

技术博客:http://hi.baidu.com/coolrainbow/blog
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

weiwei43

至尊木虫 (正式写手)


小木虫(金币+0.5):给个红包,谢谢回帖交流
原来发现编译时debug和release结果不一样,是不是也是优化的结果不同?
7楼2010-09-26 19:05:38
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
查看全部 10 个回答

hakekill

木虫 (小有名气)


小木虫(金币+0.5):给个红包,谢谢回帖交流
这个确实是第一次听说,不知道gfortran是不是这样
2楼2010-09-12 19:06:22
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

ifmc1234

木虫 (著名写手)


小木虫(金币+0.5):给个红包,谢谢回帖交流
引用回帖:
Originally posted by coolrainbow at 2010-09-12 18:21:45:
源地址:http://hi.baidu.com/coolrainbow/ ... d6c40c5aaf535e.html

今天无意中发现了intel编译器优化的一个问题。我有一个程序,大致是这样

program main
    integer, param ...

楼主正解。很多软件都说了这个问题。
所以有些软件(需要自己编译的)告诉使用者要把编译结果和他们给的例子进行比较。
3楼2010-09-12 19:21:14
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖

coolrainbow

木虫 (著名写手)

未来国家冻凉

引用回帖:
Originally posted by hakekill at 2010-09-12 19:06:22:
这个确实是第一次听说,不知道gfortran是不是这样

gfortran似乎没有这样,比如刚才那段代码

f95 -O0
CODE:
.LCFI4:
         movl    $options.5.935, %esi
         movl    $7, %edi
         call    _gfortran_set_options
         leaq    -80(%rbp), %rdi
         movl    $.LC0, %esi
         movl    $0, %eax
         call    perform_
         leave
         ret
.LFE3:

f95 -O2
CODE:
.LCFI0:
        movl    $options.5.929, %esi
        movl    $7, %edi
        call    _gfortran_set_options
        movq    %rsp, %rdi
        movl    $.LC0, %esi
        xorl    %eax, %eax
        call    perform_
        addq    $88, %rsp
        ret
.LFE3:

技术博客:http://hi.baidu.com/coolrainbow/blog
4楼2010-09-12 21:00:35
已阅   回复此楼   关注TA 给TA发消息 送TA红花 TA的回帖
普通表情 高级回复(可上传附件)
信息提示
请填处理意见