在英特尔Fortran中编译单个与多个源文件

时间:2015-08-10 00:34:14

标签: performance fortran intel-fortran

我一直在使用不同文件中的模块和子程序编译项目。每个子程序都写在单独的文件中。模块也一样。然后,我测试了将这些文件单独编译为目标文件(-c),然后与优化标志链接,并使用cat合并整个源代码并将相同的过程应用于此单个源文件。我发现,编译单个文件生成的可执行文件比多个文件生成的可执行文件快40%,尽管两者使用完全相同的标记。 我想知道是否有人知道它为什么会发生,以及英特尔Fortran编译器上是否有任何标志编译多个文件,因为它们是单个文件。

1 个答案:

答案 0 :(得分:5)

正如@ chw21所要求的,我创建了一个显示问题的小程序:

program main
    use operators
    implicit none

    integer :: n
    real(8), dimension(:,:), allocatable :: a, b, c
    integer :: i,j,k

    n = 1000

    allocate(a(n,n), b(n,n), c(n,n))

    call random_number(a)
    call random_number(b)

    do j = 1, n
        do i = 1, n
            do k = 1, n
                !c(i,j) = c(i,j) + a(k,i) * b(k,j)
                c(i,j) = add(c(i,j), mul(a(k,i), b(k,j)))
            enddo
        enddo
    enddo

    write(*,*) sum(c)

end program

with module:

module operators

contains

    function add(a,b) result (c)
        real(8), intent(in) :: a, b
        real(8) :: c

        c = a + b
    end function

    function mul(a,b) result (c)
        real(8), intent(in) :: a, b
        real(8) :: c

        c = a * b
    end function
end module

这个想法是,如果编译器知道它们非常小,那么这些函数通常应该被内联。我用-O2进行了三次测试:

  1. 单个文件中的完整源代码
  2. 拆分为两个文件
  3. 使用-ipo(或-flto
  4. 拆分为两个文件

    ifort 13.0.0gfortran 5.2.0在不同计算机上的结果为:

    Test     |   1.  |   2.  |   3.  
    ---------+-------+-------+-------
    ifort    |  1.3s | 15.7s |  1.9s
    gfortran |  1.1s |  3.7s |  1.1s
    

    不幸的是,我不知道为什么第一次和第三次使用ifort测试之间仍然存在差异...我想,看看生成的代码会对这个问题有所了解。

    更新:时间是通过执行time ./a.out来衡量的,这导致了稳定的时间。由于使用ifort -O2进行标准编译,最大指令集应为SSE2(因此,无FMA),处理器最多支持SSE4a(Opteron 6128)。对最近的英特尔处理器(最高AVX)的额外测试显示了类似的结果。

    一个重要的事情似乎是缺乏内部循环的内联和矢量化,这在IPO和单文件编译期间应用(参见--opt-report)。此外,IPO和单文件编译之间的矢量化似乎存在一些差异。