提问



我不时会读到Fortran是或者可以比C更快进行繁重的计算。这是真的吗?我必须承认我几乎不知道Fortran,但到目前为止我看到的Fortran代码并没有表明该语言具有C不具备的功能。


如果是真的,请告诉我原因。请不要告诉我哪些语言或库对数字运算有好处,我不打算写一个app或lib来做那个,我只是好奇。

最佳参考


这些语言具有类似的功能集。性能差异来自于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关键字和严格别名以解决此问题。它在大多数C ++编译器中也得到了很好的支持。关键字允许你给编译器一个提示,即程序员承诺指针不会与任何其他指针混淆。严格别名意味着程序员承诺指针不同类型的东西永远不会重叠,例如double*不会与int*重叠(char*void*可以与任何东西重叠的特殊例外)。


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

其它参考1


是的,1980年;在2008?取决于



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


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


直到并包括Fortran 77,语言设计考虑因素都将优化作为主要关注点。由于编译器理论和技术的状态,这通常意味着限制特性和功能,以便为编译器提供优化代码的最佳机会。一个很好的类比是将Fortran 77视为专业赛车,为速度牺牲功能。如今,编译器在所有语言中都得到了更好的发展,并且程序员的工作效率更高。然而,仍有一些地方人们主要关注科学计算的速度;这些人很可能从他们自己是Fortran程序员的人那里继承了代码,培训和文化。


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


维基百科是一个了解Fortran历史和文化的好地方。 Fortran维基百科条目非常棒,我非常感谢那些花时间和精力为Fortran社区创造价值的人。[17]


(这个答案的缩短版本应该是由 Nils 开始的优秀帖子中的评论,但我没有这样做的业力。实际上,我可能根本不会写任何东西但为此,这个帖子有实际的信息内容和分享,而不是火焰战争和语言偏见,这是我对这个主题的主要体验。我不知所措,不得不分享爱情。)

其它参考2


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


密集矩阵乘法很简单:


matmul(a,b)


向量x的L2范数是:


sqrt(sum(x**2))


此外,诸如FORALLPURE和& ELEMENTAL程序等进一步帮助优化代码。由于这个简单的原因,即使Fortran中的指针也不如C灵活。


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


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

其它参考3


很有趣的是,这里的答案很多,不知道语言。对于已经打开旧FORTRAN 77代码并讨论其弱点的C/C ++程序员来说尤其如此。


我想速度问题主要是C/C ++和Fortran之间的问题。在一个巨大的代码中,它总是取决于程序员。 Fortran的语言功能优于C语言的一些功能。所以,在2011年,没有人能真正说出哪一个更快。


关于语言本身,Fortran现在支持Full OOP功能,并且完全向后兼容。我彻底使用了Fortran 2003,我想说使用它真是令人愉快。在某些方面,Fortran 2003仍然落后于C ++,但让我们看看它的用法.Fortran主要用于数值计算,由于速度原因,没有人使用花哨的C ++ OOP功能。在高性能计算中,C ++几乎没有位置go(看看MPI标准,你会发现C ++已被弃用!)。


如今,您可以使用Fortran和C/C ++进行混合语言编程。 Fortran中甚至还有GTK +接口。有免费的编译器(gfortran,g95)和许多优秀的商业编译器。

其它参考4


Fortran可以更快的原因有几个。然而,它们重要的数量是无关紧要的,或者无论如何都可以解决,这并不重要。现在使用Fortran的主要原因是维护或扩展遗留应用程序。



  • 功能上的PURE和ELEMENTAL关键字。这些功能没有副作用。这允许在某些情况下优化,其中编译器知道将使用相同的值调用相同的函数。 注意:GCC实现纯作为语言的扩展。其他编译器也可以。模块间分析也可以执行此优化,但很难。

  • 处理数组的标准函数集,而不是单个元素。像sin(),log(),sqrt()这样的东西需要数组而不是标量。这样可以更轻松地优化例程。 如果这些函数是内联函数或内置函数,则自动向量化在大多数情况下都会带来相同的好处

  • 内置复合型。从理论上讲,这可能允许编译器在某些情况下重新排序或消除某些指令,但是你可能会在结构{double re,im;}中看到同样的好处;在C中使用的成语。尽管作为运算符,它可以实现更快的开发在fortran的复杂类型上工作。


其它参考5


我认为支持Fortran的关键点在于它是一种稍微适合表达基于矢量和数组的数学的语言。上面指出的指针分析问题在实践中是真实的,因为可移植代码不能真正假设您可以告诉编译器一些东西。以更接近域的外观的方式表达计算总是有利的。如果仔细观察,C根本就没有数组,只是像它那样的行为。 Fortran有真正的箭头。这使得编译某些类型的算法变得更容易,特别是对于并行机器。


在运行时系统和调用约定之类的内容中,C和现代Fortran非常相似,很难看出会产生什么影响。请注意,这里的C实际上是基本C:C ++是一个完全不同的问题,具有非常不同的性能特征。

其它参考6


没有一种语言比另一种语言更快,所以正确的答案是


您真正需要问的是使用Fortran编译器X编译的代码比使用C编译器Y编译的等效代码快吗?这个问题的答案当然取决于你选择哪两个编译器。


人们可能会问的另一个问题是考虑到在编译器中进行优化所需的相同工作量,哪个编译器会产生更快的代码?
对此的答案实际上是 Fortran 。 Fortran编译器具有certian优势:



  • 当有些人发誓永远不会使用编译器时,Fortran不得不与大会竞争,所以它是专为速度而设计的。 C的设计灵活。

  • Fortran的利基已被数字运算。在这个域名代码永远不会足够快。因此,保持语言效率始终存在很大的压力。

  • 编译器优化的大多数研究都是由对加速Fortran数字运算代码感兴趣的人完成的,因此优化Fortran代码是一个比优化任何其他编译语言更为人熟知的问题,并且新的创新首先出现在Fortran编译器中。

  • Biggie :C鼓励使用比Fortran更多的指针。这极大地增加了C程序中任何数据项的潜在范围,这使得它们更难以优化。请注意,在这个领域,Ada也比C更好,并且是比常见的Fortran77更现代的OO语言。如果你想要一个可以生成比C更快的代码的OO语言,那么这是一个选项。

  • 再次由于它的数字运算领域,Fortran编译器的客户往往更关心优化而不是C编译器的客户。



然而,没有什么能阻止某人为他们的C编译器的优化投入大量精力,并使其生成比他们的平台的Fortran编译器更好的代码。事实上,C编译器产生的较大销售额使这种情况非常可行

其它参考7


还有另一个项目,其中Fortran与C不同 - 并且可能更快。 Fortran有比C更好的优化规则。在Fortran中,没有定义表达式的评估顺序,这允许编译器对其进行优化 - 如果想要强制某个顺序,则必须使用括号。在C中,顺序更加严格,但是使用-fast选项,它们会更放松,(...)也会被忽略。我认为Fortran有一种很好的中间位置。 (好吧,IEEE使生活变得更加困难,因为某些评估顺序的变化要求不会发生溢出,要么必须忽略,要么妨碍评估)。


智慧规则的另一个领域是复数。不仅仅是C到C 99还有它们,在Fortran中管理它们的规则也更好;由于gfortran的Fortran库部分用C语言编写,但实现了Fortran语义,因此GCC获得了选项(也可以与普通C程序一起使用):



??-fcx Fortran的规则
??复数乘法和除法遵循Fortran规则。范围缩减是作为复杂除法的一部分完成的,但是没有检查复数乘法或除法的结果是否是NaN + I * NaN,试图在这种情况下挽救情况。



上面提到的别名规则是另一个好处,并且 - 至少在原则上 - 全数组操作,如果编译器的优化器正确考虑,可以导致更快的代码。另一方面,某些操作需要更多时间,例如如果对可分配数组进行赋值,则需要进行大量检查(重新分配?[[Fortran 2003特性]],数组步长等),这使得简单操作在幕后变得更加复杂 - 因此速度较慢,但??是使语言更强大。另一方面,具有灵活边界和跨度的数组操作使编写代码更容易 - 编译器通常比用户更好地优化代码。


总的来说,我认为C和Fortran的速度差不多;选择应该是更多的语言更多或者使用Fortran的整个数组操作及其更好的可移植性是否更有用 - 或者更好地连接到C中的系统和图形用户界面库。

其它参考8


没有任何关于语言 Fortran和C的内容,它们比其他特定目的更快。对于这些语言中的每一种语言都有一些特定的编译器,它们比某些语言更有利于某些任务。


多年来,Fortran编译器已经存在,可以为你的数字例程做黑魔法,使得许多重要的计算速度非常快。当代的C编译器也不能这样做。因此,Fortran中增加了许多优秀的代码库。如果你想使用这些经过良好测试,成熟,精彩的库,你就可以打破Fortran编译器。


我的非正式观察表明,现在人们用任何旧语言编写繁重的计算资料,如果需要一段时间,他们会在一些廉价的计算集群上找到时间。摩尔定律使我们所有人都变得愚蠢。

其它参考9


我将Fortran,C和C ++的速度与netlib的经典Levine-Callahan-Dongarra基准进行比较。使用OpenMP的多语言版本是
http://sites.google.com/site/tprincesite/levine-callahan-dongarra-vectors
C更加丑陋,因为它始于自动翻译,并为某些编译器插入限制和编译指示。
在适用的情况下,C ++只是带有STL模板的C.在我看来,STL是否能提高可维护性。[18]


只需极少量的自动函数内嵌运算即可了解它在多大程度上改进了优化,因为这些示例基于传统的Fortran实践,其中很少依赖于内衬。


到目前为止,最广泛使用的C/C ++编译器缺乏自动向量化,这些基准测试依赖于自动向量化。


重新发布在此之前的帖子:有几个例子,其中在Fortran中使用括号来指示更快或更准确的评估顺序。已知的C编译器没有选项来观察括号而不会禁用更重要的优化。

其它参考10


我用FORTRAN和C做了几年广泛的数学研究。根据我自己的经验,我可以说FORTRAN有时候确实比C更好但不是因为它的速度(可以通过使用适当的编码风格使C表现得像FORTRAN一样快),而是因为非常优化的库如LAPACK,并且因为很好的并行化。在我看来,FORTRAN真的很难处理,它的优点还不足以取消这个缺点,所以现在我使用C + GSL进行计算。

其它参考11


我是一个业余爱好者的程序员,而且我对这两种语言都很平均。
我发现编写快速Fortran代码比编写C(或C ++)代码更容易。 Fortran和C都是历史语言(按今天标准),使用频繁,并且支持免费和商业编译器。


我不知道这是否是一个历史事实,但Fortran觉得它的构建是并行/分布/矢量化/无论多少核心化。而今天它几乎是我们的标准指标 谈论速度:它会扩大吗?


对于纯粹的cpu运算,我喜欢Fortran。对于与IO相关的任何事情,我发现使用C更容易(无论如何都很困难)。


当然,对于并行数学密集型代码,您可能希望使用GPU。 C和Fortran都有很多或多或少集成的CUDA/OpenCL接口(现在是OpenACC)。


我温和客观的答案是:如果你同时知道两种语言同样好/那么我认为Fortran更快,因为我发现在Fortran中编写并行/分布式代码比在C中更容易。(一旦你明白你可以编写自由形式fortran和不只是严格的F77代码)


这是第二个答案,因为他们不喜欢第一个答案:两种语言都具有编写高性能代码所需的功能。所以它依赖于你实现的算法(cpu密集型? io密集型?内存密集型?),硬件(单CPU?多核?分配超级计算机?GPGPU?FPGA?),你的技能,最终是编译器本身.C和Fortran都有很棒的编译器。(我很惊讶的是Fortran编译器的先进程度如何,但C编译器也是如此。


PS:我很高兴你特意排除了libs,因为我对Fortran GUI库有很多不好的东西。:)

其它参考12


我没有听说过Fortan比C快得多,但可以想象在某些情况下它会更快。而关键不在于存在的语言特征,而在于那些(通常)不存在的语言特征。


一个例子是C指针。 C指针几乎无处不在,但指针的问题在于编译器通常无法判断它们是否指向同一数组的不同部分。


例如,如果您编写了一个如下所示的strcpy例程:


strcpy(char *d, const char* s)
{
  while(*d++ = *s++);
}


编译器必须在假设d和s可能是重叠数组的情况下工作。因此,当数组重叠时,它无法执行会产生不同结果的优化。正如您所期望的那样,这极大地限制了可以执行的优化类型。


[[我应该注意到C99有一个restrict关键字,它明确地告诉编译器指针不重叠。另请注意,Fortran也有指针,语义与C语言不同,但指针并不是普遍存在的。在C.]]


但回到C vs. Fortran问题,可以想象Fortran编译器能够执行一些(直接编写的)C程序可能无法实现的优化。所以我不会对这个说法感到太惊讶。不过,我确实认为性能差异不会那么大。 [[?5-10%]]

其它参考13


Fortran和C之间的任何速度差异将更多地取决于编译器优化和特定编译器使用的基础数学库。 Fortran没有什么内在的东西能让它比C更快。


无论如何,一个优秀的程序员可以用任何语言编写Fortran。

其它参考14


快速简单:
两者同样快,但Fortran更简单。
最终真的更快取决于算法,但无论如何都没有相当大的速度差异。这就是我学到的东西n 2015年在德国Stuttgard高性能计算中心举办的Fortran研讨会。我与Fortran和C共同工作并分享了这一观点。


说明:


C旨在编写操作系统。因此,它具有比编写高性能代码所需的更多自由度。一般情况下这没有问题,但如果没有仔细编程,可以轻松减慢代码速度。


Fortran专为科学编程而设计。出于这个原因,它支持在语法方面编写快速代码,因为这是Fortran的主要目的。与公众舆论相反,Fortran不是一种过时的编程语言。它的最新标准是2010年,并且定期发布新的编译器,因为大多数高性能代码都是在Fortran中编写的。 Fortran进一步支持现代功能作为编译器指令(在C编译指示中)。[19]


示例:
我们想要一个大型结构作为函数的输入参数(fortran:subroutine)。在函数内,参数不会改变。


C支持通过引用调用和按值调用,这是一个方便的功能。在我们的例子中,程序员可能会偶然使用按值调用。这会大大减慢速度,因为结构需要先在内存中复制。


Fortran只能通过引用调用,它强制程序员手动复制结构,如果他真的想要通过值操作调用。在我们的例子中,fortran将自动与C版本一样快,并通过引用调用。

其它参考15


通常FORTRAN比C慢.C可以使用硬件级指针,允许程序员手动优化。 FORTRAN(在大多数情况下)不能访问硬件内存寻址黑客。(VAX FORTRAN是另一个故事。)自从70以来我一直使用FORTRAN。 (真。)


然而,从90年代开始的FORTRAN已经发展到包括特定的语言结构,可以优化为本质上并行的算法,可以真正在多核处理器上尖叫。例如,自动矢量化允许多个处理器同时处理数据向量中的每个元素.16个处理器 - 16个元素向量 - 处理需要1/16的时间。


在C中,您必须管理自己的线程并仔细设计算法以进行多处理,然后使用一堆API调用来确保并行性正确发生。


在FORTRAN中,您只需仔细设计算法以进行多处理。编译器和运行时可以为您处理其余的事情。


您可以阅读一些关于高性能Fortran的内容,但是您会发现很多死链接。你最好不要阅读并行编程(如OpenMP.org)以及FORTRAN如何支持它。[20] [21]

其它参考16


更快的代码并不是真正取决于语言,是编译器所以你可以看到ms-vb编译器生成膨胀,较慢和冗余的目标代码,它们在.exe中绑定在一起,但是powerBasic生成方式太多了更好的代码。
由C和C ++编译器生成的目标代码在某些阶段(至少2个)生成,但是通过设计,大多数Fortran编译器至少有5个阶段,包括高级优化,因此通过设计,Fortran将始终能够生成高度优化的代码。
所以最后编译器不是你应该要求的语言,我所知道的最好的编译器是英特尔Fortran编译器,因为你可以在LINUX和Windows上获得它,你可以使用VS作为IDE,如果你正在寻找一个便宜的Tigh编译器,你可以随时在OpenWatcom上转发。


关于这个的更多信息:
http://ed-thelen.org/1401Project/1401-IBM-Systems-Journal-FORTRAN.html[22]

其它参考17


大多数帖子已经提出了令人信服的论据,所以我只会在另一个方面加上众所周知的2美分。


至少在处理能力方面更快或更慢的Fortran可能有其重要性,但如果在Fortran中开发内容需要5倍的时间,因为:



  • 它缺少任何与纯数字运算不同的任务的好库

  • 它没有任何适当的文档和单元测试工具

  • 这是一种表达能力非常低的语言,代码行数突然增加。

  • 对字符串的处理非常糟糕

  • 它在不同的编译器和架构之间存在大量问题,让你发疯。

  • 它有一个非常差的IO策略(顺序文件的READ/WRITE。是的,存在随机访问文件,但你有没有看到它们被使用过?)

  • 它不鼓励良好的开发实践,模块化。

  • 有效缺乏完全标准的,完全兼容的开源编译器(gfortran和g95都不支持所有内容)

  • 与C的互操作性非常差(错误:一个下划线,两个下划线,没有下划线,一般一个下划线,但如果有另一个下划线则为两个。并且不要钻研COMMON块...)



那么这个问题就无关紧要了。如果某些事情很慢,大多数时候你无法超越给定的限制。如果您想要更快的速度,请更改算法。最后,电脑时间便宜。人类的时间不是。重视减少人类时间的选择。如果它增加了计算机时间,那么无论如何它都具有成本效益。

其它参考18


Fortran具有更好的I/O例程,例如暗示的设施提供了C的标准库不能匹配的灵活性。


Fortran编译器直接处理更复杂的问题
涉及的语法,因此不容易减少语法
对于参数传递形式,C无法有效地实现它。

其它参考19


使用现代标准和编译器,不!


这里的一些人建议FORTRAN更快,因为编译器不需要担心别名(因此可以在优化期间做出更多的假设)。但是,自从C99(我认为)标准以来,这已经在C中处理过了。包含restrict关键字。这基本上告诉编译器,在给定范围内,指针没有别名。此外,C启用正确的指针算法,其中像别名这样的东西在性能和资源分配方面非常有用。我认为更新版本的FORTRAN可以使用正确的指针。


对于现代实现,C general优于FORTRAN(尽管它也非常快)。


http://benchmarksgame.alioth.debian.org/u64q/fortran.html[23]


编辑:


对此的公平批评似乎是基准测试可能存在偏见。这是另一个源(相对于C),它将结果放在更多上下文中:


http://julialang.org/benchmarks/[24]


在大多数情况下,您可以看到C通常优于Fortran(同样请参见下面的批评也适用于此);正如其他人所说,基准测试是一种不精确的科学,可以很容易地加载到一种语言而不是其他语言。但它确实说明了Fortran和C在性能上是如何相似的。

其它参考20


这在某种程度上是主观的,因为它进入了编译器的质量,而不是其他任何东西。然而,为了更直接地回答你的问题,从语言/编译器的角度来讲,没有任何关于Fortran over C会使它本身比C更快或更好。如果你正在进行繁重的数学运算,它将归结为编译器的质量,每种语言的程序员的技能以及支持这些操作的内在数学支持库,以最终确定哪一个对于给定的实现更快。


编辑:其他人如@Nils已经提出了关于C中指针使用差异的好处以及混淆的可能性,这可能会使C中最天真的实现更慢。但是,有很多方法可以在C99中处理它,通过编译器优化标志和/或实际写入C的方式。 @Nils答案以及随后的答案中都有详细介绍。

其它参考21


Fortran可以非常方便地处理数组,尤其是多维数组。在Fortran中切片多维数组元素比在C/C ++中更容易。 C ++现在有了库可以完成这项工作,比如Boost或Eigen,但它们毕竟是外部库。在Fortran中,这些功能是固有的。


Fortran是否更快或更便于开发主要取决于您需要完成的工作。作为地球物理学的科学计算人员,我在Fortran中完成了大部分计算(我的意思是现代Fortran,>=F90)。

其它参考22


Fortran传统上没有设置诸如-fp:strict之类的选项(ifort需要启用USE IEEE_arithmetic中的一些功能,这是f2003标准的一部分。)英特尔C ++也没有设置-fp:strict作为默认值,但是例如,这是ERRNO处理所必需的,而其他C ++编译器不能方便关闭ERRNO或获得降低simd等优化.gcc和g ++要求我设置Makefile以避免使用危险的组合-O3 -ffast-math -fopenmp -march=native。
除了这些问题之外,关于相对性能的这个问题变得更加挑剔并且依赖于关于编译器和选项的选择的本地规则。