对于繁重的计算,Fortran是否比C更容易优化?


410

我不时地读到,对于繁重的计算,Fortran比C更快,甚至可以更快。是真的吗 我必须承认,我几乎不了解Fortran,但是到目前为止,我所看到的Fortran代码并未表明该语言具有C所没有的功能。

如果是真的,请告诉我原因。请不要告诉我哪种语言或库最适合数字运算,我不打算编写应用程序或库来做到这一点,我很好奇。


53
从以下给出的答案中可以得出主观的看法。正确的标题是“ Fortran编译器可能比C编译器可以产生更好的伪造代码吗?”。
马丁·贝克特

3
我认为,标题问题不是很主观,而是一个误解。更详细的问题不是主观的。
jfm3

1
我认为除了答案是“是”和“否”之外,没有人会从中学到很多,并且答案会因编译器,源代码,CPU,内存布局等而异。
user7116

1
我认为问题或答案不是主观的。但是,如果您认为此标志可以帮助任何人,那么我很好。
quinmars

2
@sixlettervariables尽管您和我已经知道答案了,但对于大多数人来说,这是一个在其职业生涯初期出现的问题,对于理解答案很重要。而不是发表不屑一顾的评论,为什么不找到您同意的答案并给出+1
MarkJ 2012年

Answers:


447

这些语言具有相似的功能集。性能差异源于以下事实: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编译器假定指针/数组在内存中不重叠。

幸运的是,restrict关键字和strict-aliasing已引入C99标准以解决此问题。如今,大多数C ++编译器也都很好地支持它。关键字允许您向编译器提供提示,表明程序员保证指针不会与任何其他指针混叠。严格混叠意味着程序员保证不同类型的指针永远不会重叠,例如a double*将不会与an重叠int*(特定的例外是,char*并且void*可以与任何东西重叠)。

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


26
所有真实有效,杰夫。但是,我认为“假定没有别名”开关是安全的。它可以以微妙的方式破坏从其他项目继承的代码,以至于我不想使用它。由于这个原因,我已经成为
纳粹分子了

3
第二点,您不必使用无别名编译器开关。只需编写代码,以便首先将基于指针的负载分配给自动变量,然后从那里使用自动变量。它看起来会很冗长,但是编译器会对其进行优化。
高大的杰夫

33
一个很好的例子是memcpy()与memmove()的存在。与memcpy()不同,memmove()可以处理重叠区域,因此memcpy()可以比memmove()更快。对于某些人来说,在标准库中包括两个函数而不是一个函数,就足以说明这个问题。
jfs

12
我认为这就是Sebastian的观点-由于C内存处理的复杂性/灵活性,即使像移动内存这样简单的事情也很棘手。
Martin Beckett

3
您的call transform示例没有多大意义。
弗拉基米尔F

163

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

当我开始专业编程时,Fortran的速度优势才刚刚受到挑战。我记得在Dobbs博士那里读过这篇文章,并向年长的程序员讲述了这篇文章-他们笑了。

因此,我对此有两种观点,即理论上的和实践上的。从理论上讲,今天的Fortran对C / C ++甚至任何允许汇编代码的语言都没有固有的优势。实际上,在今天,Fortran仍然享受着围绕数字代码优化而建立的历史和文化遗留的好处。

直到包括Fortran 77在内,语言设计方面的考虑都以优化为主要重点。由于编译器理论和技术的发展,这通常意味着限制功能和特性,以便使编译器在优化代码方面有最佳的表现。一个很好的类比就是将Fortran 77视为牺牲速度的专业赛车。如今,编译器在所有语言中都变得更好,并且使程序员工作效率的功能受到更多重视。但是,在某些地方人们仍然主要关心科学计算的速度。这些人很可能已经从自己是Fortran程序员的人那里继承了代码,培训和文化。

当人们开始讨论代码优化时,有很多问题,对此感到最佳的方式就是潜伏在人们所处的工作领域-快速数字代码。但是请记住,这种非常敏感的代码通常只占整个代码行的一小部分,并且非常专业:许多Fortran代码与其他语言的许多其他代码一样“效率低下”,并且优化甚至不应这种代码的主要问题

维基百科是开始学习Fortran历史和文化的绝佳去处。Fortran Wikipedia条目非常棒,我非常感谢那些花时间和精力使它对Fortran社区有价值的人。

(此答案的缩写版应该是Nils发起的优秀线程中的注释,但我没有因果关系。实际上,我可能什么都不会写,但因为该线程具有实际意义信息内容和共享,而不是火焰战争和语言偏执,这是我在这方面的主要经验。我不知所措,不得不分享爱。)


1
链接:web.archive.org/web/20090401205830/http//ubiety.uwaterloo.ca/…不再起作用。有替代链接吗?
nathanielng 2015年

64

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

密集矩阵乘法很简单:

matmul(a,b)

向量x的L2范数是:

sqrt(sum(x**2))

此外FORALL,,PUREELEMENTAL程序等语句还有助于优化代码。由于这个简单的原因,即使是Fortran中的指针也没有C一样灵活。

即将到来的Fortran标准(2008)具有协同数组,使您可以轻松编写并行代码。CRAY的G95(开源)和编译器已经支持它。

因此,是的,Fortran可以快速实现,仅仅是因为编译器比C / C ++更好地优化/并行化它。但是,就像生活中的其他一切一样,有好的编译器和坏的编译器。



1
forall不建议使用该构造,因为编译器无法很好地优化代码。替换为do concurrent。而且,代码sqrt(sum(x**2))看起来效率很低,因为编译器可能会构造整个vector x**2。我猜想循环会更好,但是无疑最好调用内在norm2函数。
A. Hennink '17

39

有趣的是,这里的许多答案来自于不懂语言。对于已打开并使用旧的FORTRAN 77代码并讨论其缺点的C / C ++程序员,尤其如此。

我想速度问题主要是C / C ++和Fortran之间的问题。在巨大的代码中,它始终取决于程序员。该语言的某些功能胜过Fortran,C则具有某些功能。因此,在2011年,没有人能真正说出哪个更快。

关于语言本身,Fortran现在支持完整的OOP功能,并且完全向后兼容。我已经彻底使用了Fortran 2003,我会说使用它很令人愉快。在某些方面,Fortran 2003仍然落后于C ++,但让我们看一下用法。Fortran主要用于数值计算,由于速度原因,没有人使用精美的C ++ OOP功能。在高性能计算中,C ++几乎无处可去(看看MPI标准,您会发现C ++已被弃用!)。

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


8
您能否添加一个来源,特定经验或科学研究所/高性能计算机构,该机构要么不再使用C ++进行将来的项目,要么将c ++项目重写为另一种语言。我之所以这么问是因为我知道至少有两个科研机构Sandia和CERN大量使用c ++进行高性能建模。此外,Sandia将其建模软件(LAMMPS)之一从fortran转换为c ++,从而增加了许多令人敬畏的增强功能。
Zachary Kraus 2015年

7
LAMMPS用极其简单的C ++编写,没有利用该语言的大多数现代功能。它代表了解C的Fortran程序员在学习C ++ 98之后编写的C ++。这并不是说LAMMPS编写得不好,只是它不是您在HPC中提倡C ++时要引用的示例。
杰夫

30

Fortran可能更快的原因有很多。但是,它们所影响的数量无关紧要,或者无论如何都可以解决,这无关紧要。如今使用Fortran的主要原因是维护或扩展旧版应用程序。

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

  • 处理数组而不是单个元素的标准函数集。像sin(),log(),sqrt()之类的东西采用数组而不是标量。这样可以更轻松地优化例程。如果这些函数是内联函数或内置函数,则自动矢量化在大多数情况下具有相同的优势

  • 内置复杂类型。从理论上讲,这可以使编译器在某些情况下可以重新排序或消除某些指令,但是使用struct {double re,im; }; C中使用的惯用语。尽管操作员在fortran中处理复杂类型,但它可以加快开发速度。


1
“但是您可能会发现{ double re, im; };C语言中使用的struct 习惯用法具有相同的好处”。C编译器最有可能以sret形式返回该结构,并通过调用方堆栈分配空间,将指针传递给被填充的被调用方。这比在Fortran编译器中在寄存器中返回多个值要慢几倍。请注意,在复杂的特殊情况下,C99修复了此问题。
乔恩·哈罗普

我不确定我是否同意你的主要原因。我个人喜欢将fortran用于数学繁重的代码,其中数组和数学函数是代码中最重要的部分。但是我知道,在许多政府机构和银行中,他们继续使用fortran来维护或扩展旧代码。我个人使用fortran在我的博士学位上扩展了教授的代码。委员会写道。
Zachary Kraus 2015年

您的陈述“当今使用Fortran的主要原因是维护或扩展旧版应用程序”,这是完全错误的。我还没有看到任何其他编程语言,甚至在距离Fortran提供的功能很近的地方,尤其是对于数学应用程序。您已经命名了其中的一些,例如出色的数组支持,内置的复杂算术,纯函数或基本函数-我也可以命名。仅此一项就足以证明您的上述说法是错误的。
巴氏

28

我认为支持Fortran的关键点是它是一种稍微适合于表达基于矢量和基于数组的数学的语言。上面指出的指针分析问题在实践中是真实存在的,因为可移植代码无法真正假设您可以告诉编译器某些信息。以更接近域外观的方式表达计算总是有一个优势。如果仔细观察,C根本没有数组,只是某种类似的行为。Fortran具有真正的优势。这使得更容易针对某些类型的算法进行编译,尤其是对于并行机。

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


25

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

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

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

  • 在某些人发誓永远不使用编译器的那一天,Fortran不得不与Assembly竞争,因此它是为提高速度而设计的。C被设计为灵活的。
  • Fortran的利基市场一直是数字紧缩。在此域中,代码永远不会足够快。因此,保持语言高效始终存在着很大的压力。
  • 编译器优化的大多数研究都是由对加速Fortran数字处理代码感兴趣的人员完成的,因此,与优化其他任何编译语言相比,优化Fortran代码是一个众所周知的问题,并且新的创新首先出现在Fortran编译器中。
  • Biggie:与Fortran相比,C鼓励使用更多的指针。这极大地增加了C程序中任何数据项的潜在范围,这使它们难以优化。请注意,在这个领域,Ada也比C更好,并且比常见的Fortran77更现代的OO语言。如果您想要一种可以比C生成更快代码的OO语言,那么这是您的一个选择。
  • 再次由于其数量紧缺的利基,Fortran编译器的客户比C编译器的客户更关心优化。

但是,没有什么可以阻止某人花费大量精力进行C编译器的优化,并使其生成比其平台的Fortran编译器更好的代码。实际上,C编译器产生的较大销售额使此方案相当可行


4
我同意。而且我想补充一点,就是在50年代末60年代初引入Fortran时(这是第一门高级语言),许多人对此表示怀疑。因此,它的开发人员必须证明Fortran可能是高效且有用的,并着手“优化到死”以证明自己的观点。C来得很晚(大约70年代中期),没有什么可以证明的。但是到了此时,已经编写了许多Fortran代码,因此科学界坚持并仍然这样做。我没有编写Fortran程序,但是我学会了从C ++链接到调用Fortran子例程。
奥米利德(Olumide)

3
关于编译器优化的研究比您想像的还要多样化。例如,LISP实现的历史比以Fortran(仍然是要挑战的默认竞争者)更快地进行号码处理。同样,编译器优化的很大一部分都针对编译器的中间表示形式,这意味着,除了语义上的差异(如别名)外,它们还适用于给定类的任何编程语言。

2
这个想法被重复了很多,但是说编程语言设计所固有的效率没有任何影响是有点不屑一顾的。一些编程语言功能必然会导致效率低下,因为它们限制了编译时可用的信息。
Praxeolitic

@Praxeolitic-完全正确(这就是为什么我很高兴没有说这样的话)。
TED

@TED老实说,几个月后回到这里,我不知道为什么我在您的回答中留下评论。也许我打算把它留在别的地方?XP
Praxeolitic

22

还有另一个项目,其中Fortran与C不同-并且可能更快。Fortran比C具有更好的优化规则。在Fortran中,未定义表达式的求值顺序,这使编译器可以对其进行优化-如果要强制执行某个顺序,则必须使用括号。在C语言中,顺序要严格得多,但是使用“ -fast”选项时,它们会更宽松,并且“(...)”也将被忽略。我认为Fortran的中间位置很好。(好吧,由于某些评估顺序的更改要求没有溢出发生,因此IEEE会使工作变得更加困难,这必须被忽略或妨碍评估)。

更智能的规则的另一个领域是复数。直到C 99才有了C,并且在Fortran中控制它们的规则也更好。由于gfortran的Fortran库部分用C编写,但是实现了Fortran语义,因此GCC获得了该选项(也可以与“常规” C程序一起使用):

-fcx-fortran-rules复杂的乘法和除法遵循Fortran规则。范围缩小是复数除法的一部分,但是没有检查复数乘法或除法的结果是否为“ NaN + I * NaN”,从而试图挽救这种情况。

上面提到的别名规则是另一个好处,而且-至少在原则上-整个数组操作,如果编译器的优化程序将其适当考虑在内,则可以导致更快的代码。相反,某些操作会花费更多时间,例如,如果将一个操作分配给可分配的数组,则需要进行大量检查(重新分配?[Fortran 2003功能],是否具有数组步长,等等),这使得简单的操作在幕后变得更加复杂-从而速度较慢,但​​使语言更强大。另一方面,具有灵活边界和步幅的数组操作使编写代码更加容易-而且编译器通常比用户更能优化代码。

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


在Nan + Inan案中,要进行有意义的“救援”是什么?使无限性不同于NaN的原因是无限符号是签名的。涉及会产生混乱符号的非复数无穷运算的运算会产生NaN,我看不出复数应有其他理由。如果将(DBL_MAX,DBL_MAX)乘以(2,2),则对结果求平方,然后对结果求平方,如果没有溢出,结果的符号是什么?乘以(1.001,DBL_MAX)的倍数是多少?我认为(NaN,NaN)是正确的答案,而无穷大和NaN的任何组合都是荒谬的。
超级猫

14

对于特定的目的,Fortran和C 语言并没有什么比另一种更快。关于每种语言的特定编译器,有些事情比某些任务对某些任务的帮助更大。

多年以来,Fortran编译器就可以对您的数字例程产生魔力,从而使许多重要的计算速度异常之快。当代的C编译器也做不到。结果,Fortran中增加了许多出色的代码库。如果要使用这些经过良好测试的,成熟的,出色的库,可以使用Fortran编译器。

我的非正式观察表明,这些天人们用任何旧的语言编写繁重的计算内容,如果花了一些时间,他们会花一些时间在廉价的计算集群上。摩尔定律使我们所有人都变得愚蠢。


11
几乎改变了这一点。问题在于,Fortran 确实具有某些固有的优势。但是,您很清楚要看的重要内容是编译器,而不是语言。
TED

14

我将Fortran,C和C ++的速度与netlib的经典Levine-Callahan-Dongarra基准进行了比较。带有OpenMP的多语言版本为 http://sites.google.com/site/tprincesite/levine-callahan-dongarra-vectors C语言较为丑陋,因为它以自动翻译开始,并且为某些语言插入了限制和注释编译器。在适用的情况下,C ++只是带有STL模板的C语言。在我看来,STL能否提高可维护性是一个参差不齐的问题。

自动内联函数只有很少的练习,以了解它在多大程度上改善了优化效果,因为这些示例基于传统的Fortran惯例,因此很少依赖内联函数。

迄今为止使用最广泛的C / C ++编译器缺少自动矢量化功能,这些基准测试在很大程度上依赖于此。

回顾一下之前的文章:有两个示例,其中在Fortran中使用括号指示更快或更准确的求值顺序。已知的C编译器在不禁用更重要的优化的情况下没有观察括号的选项。


为了克服混叠问题,需要进行丑陋的翻译。您必须给编译器模拟变量,以告诉它作为指针实现的byref变量可以进行寄存器优化。
大卫

12

我是一个业余程序员,在两种语言中我都“平均”。我发现编写快速的Fortran代码比C(或C ++)代码容易。Fortran和C都是“历史性”语言(按今天的标准),已被大量使用,并且得到了自由和商业编译器的良好支持。

我不知道这是否是一个历史事实,但是Fortran感觉它是并行/分布式/矢量化/多核化的。今天,当我们谈论速度时,它几乎已成为“标准指标”:“它可扩展吗?”

对于纯cpu运算,我喜欢Fortran。对于任何与IO相关的问题,我发现使用C会更容易(无论如何,这都是困难的)。

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

我的客观回答是:如果您对两种语言的了解都很好/很差,那么我认为Fortran会更快,因为我发现用Fortran编写并行/分布式代码比使用C更为容易。不只是严格的F77代码)

对于那些因为我不喜欢第一个答案而愿意拒绝我的人,这是第二个答案:两种语言都有编写高性能代码所需的功能。因此,它取决于您要实现的算法(CPU密集型还是io密集型还是内存密集型),硬件(单cpu,多核,分布式超级计算机,GPGPU,FPGA),您的技能以及最终的编译器本身。C和Fortran都有出色的编译器。(我对Fortran编译器的先进程度感到非常惊讶,但C编译器也是如此)。

PS:很高兴您特别排除了库,因为关于Fortran GUI库,我有很多不好的话要说。:)


11

我在FORTRAN和C上做了几年广泛的数学研究。根据我自己的经验,我可以说出FORTRAN有时确实比C更好,但不是因为它的速度(通过使用适当的编码样式就可以使C的性能与FORTRAN一样快),而是因为LAPACK这样的优化库非常好,并且由于高度并行化。我认为,FORTRAN的使用确实很笨拙,并且其优点还不足以消除该缺点,因此现在我使用C + GSL进行计算。


10

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

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


@斯科特·克劳森:你得-1,我不知道为什么。+1可以解决这个问题。但是,需要考虑的一点是,Fortran的存在时间比我们许多父母的生存时间更长。优化编译器输出时花费了大量时间:D
user7116

我同意。我刚刚并行发布了一个非常相似的答案。
高杰夫

其他人提出了C语言中的指针别名问题,但是程序员可以在现代编译器上使用多种方法来解决该问题,所以我仍然同意。
高杰夫

1
@Kluge:“ Fortran没有内在的东西可以使它比C更快”。指针混叠,返回寄存器中的复合值,内置更高级的数字结构...
Jon Harrop 2012年

9

我还没有听说过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%]


9

快速而简单: 两者同样快,但是Fortran更简单。 最终真正更快的速度取决于算法,但是无论如何速度差异不大。这就是我2015年在德国斯图加德高性能计算中心的Fortran研讨会上所学到的。我与Fortran和C一起工作,并分享了这一观点。

说明:

C被设计为编写操作系统。因此,它比编写高性能代码所需的自由更大。通常,这没有问题,但是如果不仔细编程,则很容易降低代码速度。

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

示例: 我们想给函数提供一个大的结构作为输入参数(fortran:子例程)。在函数中,参数不会更改。

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

Fortran仅与按引用调用一起使用,如果程序员确实想要按值调用,它将迫使程序员手动复制该结构。在我们的情况下,通过引用调用,fortran将自动与C版本一样快。


您可以用C编写本机并行应用程序(意思是不调用任何库吗?)。否。可以在Fortran中编写本机并行应用程序吗?是的,以几种不同的方式。如此,Fortran变得“更快”。公平地说,在2010年,当您发表评论时,对Fortran并行功能和共数组功能的支持可能不像现在那样广泛。
马里·雷莫克

@MaliRemorker他在2016年而不是2010
Kowalski

在我看来,创建并行进程的开销并不是将编程语言称为“快速”的最相关因素。更为相关的是实际考虑,例如代码表现不佳。因此,如果您一次节省时间(在创建并行进程时)并在以后将其浪费在多个内核上,则无济于事。术语“快速”还应考虑非并行代码。由于这个原因,我看不出有任何反对意见。也许您的评论是作为独立答案提出的?
Markus Dutschke

8

通常,FORTRAN比C慢。C可以使用硬件级别的指针,从而允许程序员进行手动优化。FORTRAN(在大多数情况下)无权访问硬件内存来解决黑客问题。(VAX FORTRAN是另一个故事。)自70年代以来,我一直在使用FORTRAN。(真。)

但是,从90年代开始,FORTRAN已发展为包括特定的语言结构,这些结构可以优化为固有的并行算法,这些算法实际上可以在多核处理器上大放异彩。例如,自动向量化允许多个处理器同时处理数据向量中的每个元素。16个处理器-16个元素向量-处理需要1/16的时间。

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

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

您可以阅读有关高性能Fortran的一些文章,但是会发现很多死链接。您最好阅读有关并行编程(例如OpenMP.org)以及FORTRAN如何支持它的知识。


6
@ S.Lott:我无法想象要像在这里为大多数代码编写Fortran一样,要完成如此糟糕的C代码,而我是C程序员。通过Fortran中的简单代码,您将获得更好的性能。不是您或我找不到反例。:D
user7116

2
@格雷格·罗杰斯(Greg Rogers):您必须与Fortran Vectorization人员(而不是我)一起解决问题。我只是在报告我读到的东西。 polyhedron.com/absoftlinux
S.Lott

2
-1 //“通常FORTRAN比C慢。这几乎适用于所有情况。” 为什么?//基于在Fortran vs C中易于使用多线程的观点并没有说明性能。
steabert

4
@ S.Lott:“仅存在多线程以提高性能”。嗯不
乔恩·哈罗普

4
@ S.Lott:“ C几乎在硬件级别使用指针,使C比Fortran更快”。Err,no
Jon Harrop'1

5

较快的代码并不能完全由语言决定,而是编译器,因此您可以看到ms-vb“ compiler”生成ated肿,较慢且冗余的目标代码,这些目标代码在“ .exe”内捆绑在一起,但powerBasic生成的方式也是如此更好的代码。由C和C ++编译器生成的目标代码是在某些阶段(至少2个阶段)生成的,但是根据设计,大多数Fortran编译器至少有5个阶段(包括高级优化),因此根据设计,Fortran将始终具有生成高度优化的代码的能力。因此,最后是编译器而不是您应该使用的语言,我所知道的最好的编译器是Intel Fortran编译器,因为您可以在LINUX和Windows上获得它,并且可以将VS用作IDE,如果您正在寻找一个便宜的编译器,您可以随时在OpenWatcom上转播。

有关此的更多信息:http : //ed-thelen.org/1401Project/1401-IBM-Systems-Journal-FORTRAN.html


3

Fortran具有更好的I / O例程,例如,隐含的do工具提供了C标准库无法匹敌的灵活性。

Fortran编译器直接处理所涉及的更复杂的语法,并且由于无法轻松地将这种语法简化为参数传递形式,因此C无法有效地实现它。


1
您是否有基准测试表明Fortran在I / O方面胜过C?
杰夫

3

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

这里的一些人建议FORTRAN更快,因为编译器不需要担心别名(因此可以在优化过程中做出更多假设)。但是,自C99(我认为)标准以来,这已在C中处理,其中包含了strict关键字。基本上告诉编译器,在给定范围内,指针没有别名。此外,C支持正确的指针算术,在这种情况下,如混叠之类的事情在性能和资源分配方面非常有用。尽管我认为最新版本的FORTRAN允许使用“适当”的指针。

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

http://benchmarksgame.alioth.debian.org/u64q/fortran.html

编辑:

对此的合理批评似乎是基准测试可能有偏差。这是另一个结果(相对于C),将结果放在更多上下文中:

http://julialang.org/benchmarks/

您可以看到C在大多数情况下通常都胜过Fortran(再次参见下面的批评也适用于此)。正如其他人指出的那样,基准测试是一门不精确的科学,可以轻松地进行加载以使一种语言优于另一种语言。但这确实说明了Fortran和C如何具有相似的性能。


3
如果从假设Fortran仍然是FORTRAN的帖子中相信任何有关Fortran的信息,那将是一个傻瓜。这种情况在25年前改变了。这些测试无法比较语言,因为尽管Intel和GCC都使用了C和Fortran的编译器,但它们使用的是来自不同供应商的编译器。因此,这些比较毫无价值。
弗拉基米尔F

2

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

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


1
而且Fortran是否更快,还取决于:您使用的编译器(这很重要!),对于计算作业,是否对代码应用适当的并行化以及代码的编写方式。

1

这在某种程度上是主观的,因为它影响到编译器的质量,而比其他任何事情都重要。但是,从语言/编译器的角度来讲,要更直接地回答您的问题,关于C语言的Fortran并没有使它本质上比C更快或更好的方法。如果您要执行大量的数学运算,它将归结为编译器的质量,每种语言的程序员的技能以及内在的数学支持库,这些库支持这些操作,以最终确定对于给定的实现哪种方法更快。

编辑:@Nils之类的其他人提出了关于C中使用指针的区别以及别名的可能性的好处,这可能会使C中最幼稚的实现变慢。但是,在C99中有很多方法可以解决,通过编译器优化标志和/或C的实际编写方式。@Nils答案以及其答案中的后续注释对此进行了详细介绍。


听起来像是算法的基准测试。FORTRAN或C,哪个时间花费更少?听起来对我不是很主观。也许我想念一些东西。
S.Lott

1
不同意。您正在比较的是编译器,而不是语言。我认为最初的问题是有关LANGUAGE的内容是否有任何本质上的改进。这里的其他答案正在引起一些细微的可疑差异,但我认为我们最同意它们正在喧嚣中。
高杰夫

这不是算法的O(n)分析。这是性能。没有看到性能如何成为假设的与实现无关的概念。猜猜我缺少什么。
S.Lott

1
-1:“ Fortran over C并没有使它本质上比C更快或更好的东西”。嗯不
乔恩·哈罗普

0

大多数帖子已经提出了令人信服的论点,因此我将在另一方面加上众所周知的2美分。

最终,在处理能力方面更快或更慢的fortran可能具有其重要性,但是如果在Fortran中开发某些东西要花费5倍的时间,原因是:

  • 它缺乏用于处理纯数字运算以外的其他任何好的库
  • 它缺少用于文档和单元测试的任何不错的工具
  • 这是一种表达能力很低的语言,使代码行数猛增。
  • 它对字符串的处理非常差
  • 在不同的编译器和体系结构中,它存在着无数疯狂的问题,使您发疯。
  • 它的IO策略非常差(对顺序文件进行读/写操作。是的,存在随机访问文件,但您见过使用它们吗?)
  • 它不鼓励良好的开发实践,模块化。
  • 有效缺乏完全标准,完全兼容的开源编译器(gfortran和g95都不支持所有功能)
  • 与C的互操作性非常差(调整:一个下划线,两个下划线,没有下划线,通常一个下划线,但如果有另一个下划线则两个下划线。只是不要钻研COMMON块...)

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


3
拒绝投票的原因是,尽管您提出了一些有趣的观点,这增加了与其他语言相比的fortrans好处/缺点的讨论(我并不完全同意),但这并不是问题的真正答案……
steabert 2011年

@steabert:其实,我说I will just add the proverbial 2 cents to a different aspect
斯蒂法诺博里尼

1
从我+1那里得到一些不明确的答案。如您所说,Fortran在某些罕见的任务中可能会更快(个人没有见过)。但是,您浪费在维护不可维护的语言上的时间浪费了任何可能的优势。
安德烈·贝格纳(AndréBergner)2012年

10
-1。您似乎在考虑F77的Fortran。被F90,F95,F03 F08 所取代。
凯尔·卡诺斯

4
由于它只讨论权衡的一面,因此予以否决。开发速度对于大多数通用编程而言可能很重要,但这并不是唯一有效的折衷方案。Fortran程序员经常是科学家/工程师,他们非常重视语言的简单性(FORMULA TRANslation非常易于学习和掌握,而C / C ++则不然),出色的库(通常用于其他语言)和速度(例如天气模拟)在Fortran中需要花费几天的时间,但如果完全用其他语言编写则需要花费数月的时间)。
BraveNewCurrency 2013年

-3

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


最近的gcc更新使用Openmp和fast-math组合解决了该问题。
2016年

这个答案实际上是关于用户不了解其编译器的默认标志,而不是语言本身的。
杰夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.