在某些情况下,有各种各样的论点,例如,在涉及别名时,Fortran可能比C快,而且我经常听说它比C做得更好的自动矢量化(有关更好的讨论,请参见here)。

但是,对于简单的计算斐波那契数和Mandelbrot的复杂函数,并提供简单明了的解决方案,而没有任何技巧和编译器额外的提示/关键字,我希望它们确实能达到相同的效果。

C实现:

int fib(int n) {
    return n < 2 ? n : fib(n-1) + fib(n-2);
}

int mandel(double complex z) {
    int maxiter = 80;
    double complex c = z;
    for (int n=0; n<maxiter; ++n) {
        if (cabs(z) > 2.0) {
            return n;
        }
        z = z*z+c;
    }
    return maxiter;
}

Fortran实施:
integer, parameter :: dp=kind(0.d0)          ! double precision

integer recursive function fib(n) result(r)
integer, intent(in) :: n
if (n < 2) then
    r = n
else
    r = fib(n-1) + fib(n-2)
end if
end function

integer function mandel(z0) result(r)
complex(dp), intent(in) :: z0
complex(dp) :: c, z
integer :: n, maxiter
maxiter = 80
z = z0
c = z0
do n = 1, maxiter
    if (abs(z) > 2) then
        r = n-1
        return
    end if
    z = z**2 + c
end do
r = maxiter
end function

Julia的实现:
fib(n) = n < 2 ? n : fib(n-1) + fib(n-2)

function mandel(z)
    c = z
    maxiter = 80
    for n = 1:maxiter
        if abs(z) > 2
            return n-1
        end
        z = z^2 + c
    end
    return maxiter
end

(包括其他基准功能的完整代码可以在here中找到。)

根据Julia homepage,Julia和Fortran(带有-O3)在这两个函数上的性能要优于C(带有-O3)。

怎么可能?

最佳答案

老实说,我不会太重视这些差异。不同的C编译器也会给出不同的结果。尝试使用GCC和Clang运行C微基准测试,您将获得与C vs. Fortran几乎一样的差异。为什么GCC有时比Clang更快,有时却不?他们只是以不同的方式进行不同的优化和代码生成。相对性能在不同的硬件上也有所不同,因为它可能取决于寄存器的确切数量,缓存大小,超标量吞吐量的程度,各种指令的相对速度等。

奇怪的是,Fortran能够更快地达到fib基准,因此,如果有人指出一个答案并在此处发布答案,我会很乐意赞成,但是在mandel和其他基准上相差≤15%并不是全部那太了不起了。对于这些基准,对我而言,最神秘的是,为什么Fortran在整数解析方面如此之慢。我怀疑这是因为该代码在做一些愚蠢的事情,但我不是Fortran编码器,所以我不确定应该改进什么。如果有人读这是Fortran专业人士,并且想看看this code,将不胜感激。我怀疑Fortran比C慢5倍是错误的。

要注意的一件事是,在整理这些基准测试结果时,我们拒绝了零时间,以避免计算编译器仅对整个计算进行恒定折叠的情况。在某些优化级别上,这恰恰是C和Fortran编译器所做的,并且很难迫使他们不要这样做,除非使用较低的优化级别。如果有人想弄清楚如何迫使编译器在仍然完全优化基准代码的同时不不断折叠这些结果,那将是一个值得欢迎的贡献。 (一种可能的方法是使用完全优化将基准功能编译为共享库,然后在关闭链接时优化的情况下将其链接到主程序中。这很棘手,但可能会起作用。)

最终,过于担心确切的微基准数字会错过更大的前景。这些基准测试的重点是某些语言具有可靠的快速标准实现-例如C,Fortran,Julia和Go-而其他语言则没有。在慢速语言中,有时您必须求助于使用其他语言来获得所需的性能,而在可靠的快速语言中,则不必这样做。这就是所有这些。快速语言的确切相对性能是一场军备竞赛:一种语言有时可能领先,但另一种语言总是紧随其后–关键是它们完全在竞争中。

关于c - 简单数学函数的基准:为什么Fortran和Julia比C更快,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20001680/

10-09 21:03
查看更多