Fortran在进行大量计算时比C更容易优化?

我不时读到Fortran是或可能比C更快,因为计算繁重。 这是真的吗? 我必须承认,我几乎不了解Fortran,但迄今为止我看到的Fortran代码并未显示该语言具有C没有的功能。

如果确实如此,请告诉我为什么。 请不要告诉我哪种语言或库适合数字处理,我不打算写一个应用程序或库来做到这一点,我只是好奇。


这些语言具有相似的功能集。 性能差异来自Fortran说不允许使用别名,除非使用EQUIVALENCE语句。 任何具有别名的代码都不是Fortran的有效代码,但是由程序员而不是编译器来检测这些错误。 因此,Fortran编译器会忽略内存指针的可能别名,并允许它们生成更高效的代码。 看看C中的这个小例子:

void transform (float *output, float const * input, float const * matrix, int *n)
{
    int i;
    for (i=0; i<*n; i++)
    {
        float x = input[i*2+0];
        float y = input[i*2+1];
        output[i*2+0] = matrix[0] * x + matrix[1] * y;
        output[i*2+1] = matrix[2] * x + matrix[3] * y;
    }
}

优化之后,此函数的运行速度将比Fortran对手慢。 为什么这样? 如果将值写入输出数组中,则可以更改矩阵的值。 毕竟,这些指针可能会重叠并指向同一块内存(包括int指针!)。 C编译器被迫从所有计算的内存中重新加载四个矩阵值。

在Fortran中,编译器可以加载一次矩阵值并将它们存储在寄存器中。 它可以这样做,因为Fortran编译器假定指针/数组在内存中不重叠。

幸运的是,C99标准中引入了restrict关键字和strict-aliasing来解决这个问题。 现在大多数C ++编译器都支持它。 关键字允许您给编译器一个提示,即程序员承诺指针不会与别的指针混淆。 严格别名意味着程序员承诺不同类型的指针永远不会重叠,例如double*不会与int*重叠(具体例外是char*void*可以与任何东西重叠)。

如果你使用它们,你将从C和Fortran获得相同的速度。 但是,仅将性能关键函数用于restrict关键字的能力意味着C(和C ++)程序更安全,更易于编写。 例如,考虑无效的Fortran代码: CALL TRANSFORM(A(1, 30), A(2, 31), A(3, 32), 30) ,大多数Fortran编译器都会在没有任何警告的情况下愉快编译,但会引入一个错误仅在某些编译器上,某些硬件上以及某些优化选项才会显示。


是的,在1980年; 在2008? 依靠

当我开始专业编程时,Fortran的速度优势正受到挑战。 我记得在Dobbs医生那里读过关​​于它的文章,并告诉了年长的程序员这篇文章 - 他们笑了。

所以我对此有两个看法,理论和实践。 理论上,Fortran今天对C / C ++甚至任何允许汇编代码的语言都没有内在优势。 在实践中,Fortran今天仍然享有围绕数字代码优化而建立的历史和文化遗产的益处。

直到包括Fortran 77在内,语言设计考虑因素都被优化为主要焦点。 由于编译器理论和技术的状态,这通常意味着限制特性和功能,以便为编译器提供优化代码的最佳选择。 一个很好的比喻是将Fortran 77认为是一款牺牲速度特性的专业赛车。 现在编译器在所有语言中都变得更好,程序员生产力的功能更受重视。 但是,人们仍然主要关心科学计算的速度, 这些人很可能继承了自己是Fortran程序员的人的代码,培训和文化。

当开始讨论代码优化时,会遇到很多问题,最好的办法就是让潜伏在哪里的人的工作就是拥有快速的数字代码。 但请记住,这些敏感代码通常只是整个代码行的一小部分,而且非常专业化:许多Fortran代码与其他语言中的许多其他代码一样“低效”,优化甚至不应该这种代码的主要关注点。

开始学习Fortran历史和文化的好地方就是维基百科。 Fortran维基百科条目非常好,我非常感谢那些花时间和精力为Fortran社区创造价值的人。

(这个答案的简短版本应该是Nils开始的优秀线程中的一个评论,但我没有业力去做这件事实际上,我可能根本不会写任何东西,但是为了这个线程有实际的意义信息内容和分享,而不是火焰战争和语言偏见,这是我对这个主题的主要经历,我不知所措,不得不分享爱情。)


在某种程度上,Fortran的设计始终考虑到编译器优化。 该语言支持整个数组操作,其中编译器可以利用并行性(特别是在多核处理器上)。 例如,

密集矩阵乘法很简单:

matmul(a,b)

向量x的L2范数是:

sqrt(sum(x**2))

此外,诸如FORALLPUREELEMENTAL程序等语句还有助于优化代码。 由于这个简单的原因,即使是Fortran中的指针也不像C那样灵活。

即将推出的Fortran标准(2008)具有联合数组,可让您轻松编写并行代码。 来自CRAY的G95(开源)和编译器已经支持它。

所以是的Fortran可以快速,因为编译器可以比C / C ++更好地优化/并行化它。 但是,再次像生活中的其他事物一样,有好的编译器和糟糕的编译器。

链接地址: http://www.djcxy.com/p/85711.html

上一篇: Is Fortran easier to optimize than C for heavy calculations?

下一篇: How to raise double to array powers in Eigen