比C++更快的语言

25

据说Blitz++提供了接近Fortran的性能。

实际上,Fortran在执行相同任务时是否确实比普通的C++更快?

那其他运行时性能卓越的高级语言呢?我听说有一些语言在某些任务上超过了C++,比如Objective Caml、Java和D等。

我猜垃圾回收可以使很多代码更快,因为它消除了在堆栈中频繁复制数据的必要性(假设代码不是为了性能而编写)。

我只是出于好奇询问——我一直以为除非经过专家级的汇编编程,否则C++几乎无法被击败。


1
这里是各种语言在各种任务和各种硬件上的不同实现的比较:http://shootout.alioth.debian.org/ - Mooing Duck
遗憾的是,最快的语言是汇编语言,没有编译器能够击败理解它的人类程序员。 - Peter
16个回答

58

对于纯数值代码,Fortran比C++更快且几乎总是更好。 Fortran之所以更快有很多原因。它是最古老的编译语言(有很多关于优化编译器的知识)。 它仍然是数值计算的语言,因此许多编译器供应商靠销售优化编译器谋生。 还有其他更技术性的原因。 Fortran(至少Fortran77)没有指针,因此在该领域不会遇到C / C ++语言的别名问题。 许多高性能库仍然使用Fortran编写,并有着悠久的历史(> 30年)。 C或C ++都没有好的数组构造(C太低级,C ++具有与地球上编译器数量相同的数组库,这些库彼此不兼容,从而阻止了一堆经过充分测试和快速代码的池子)。


1
仅为完整起见,f90具有指针,但它们与C和相关语言中的指针完全不同(感谢上帝)。除此之外,您提出了一些很好的观点。+1 - Rook
5
我没有说Fortran比C更快(这种说法本身也没有意义),我说的是针对数值代码,特别是依赖于数组的代码,Fortran具有更快、更好的语法。顺便说一句,Shoutout是一个相对较差的基准测试。 - David Cournapeau
1
射击页面上的Fortran源代码很糟糕。对于数值计算而言,Fortran比C/C++更快、更易读、更可移植、更易维护。 - user7116
1
@sixlettervariables:代码比赛页面已提交。如果您认为代码很糟糕,请随时提交更快的代码。如果您查看细节,Fortran在提交的每个任务中都等同于C++,除了k-nucleotide,那里只有一个提交,而且很糟糕。如果您可以为该任务编写快速版本,则应该可以解决比较问题。 - Mooing Duck
显示剩余5条评论

22

关于Fortran是否比C++更快这个问题存在争议。有些人说是,有些人说否;我不会深入讨论这个问题。它取决于编译器、你运行它的架构、算法的实现等等。

Fortran相对于C具有很大的优势,那就是它所需的算法实现时间较短。因此,它非常适合进行任何类型的数值计算。我将仅列举一些与C相比明显的优势:

  • 基于1的数组索引(在实现较大的模型时非常有帮助,而且你不必去想,只需“FORmula TRANslate”)
  • 有一个幂运算符(**)(天哪,谁想到使用幂函数?而不是用一个运算符?!)
  • 我认为Fortran是当前市场上支持多维数组的最佳语言(而且看起来短期内不会有改变),使用方式与数学中的表示方法类似于 A(1,2)
  • 避免循环 - A=B*C 就可以完成数组乘法运算(几乎像Matlab语法,但速度更快)
  • 它具有内置的并行特性(请查看新标准)
  • 非常容易与其他语言(如C、Python)连接,因此您可以在Fortran中进行重型计算,同时使用您选择的其他语言进行其他操作
  • 完全向后兼容(因为整个F77是F90的子集),因此你可以使用一个世纪之久的编码技能
  • 非常容易移植(这可能对于某些编译器扩展无法工作,但通常都很好用)
  • 面向问题解决社区(由于Fortran用户通常不是计算机科学家,而是数学、物理、工程等领域的人员......他们的问题解决经验对你的问题的了解可能非常有帮助)

暂时想不到其他的了,就这些吧。


12
基于1的数组索引既是一种福音,也是一种诅咒。无论我使用哪种语言,采用哪种约定,似乎相反的方法更适合解决手头的问题... - kquinn
10
是的,以1作为基础并不比以0作为基础更好。我看不出它对于任何模型有什么帮助 - 根据领域的不同,索引可以从0或1(或其他数字)开始。在信号处理中,从0开始索引非常常见。 - David Cournapeau
2
在“传统”的工程领域(机械、地质、海洋、航空等),使用以1为起始索引是常见的,没有任何困惑。数学家也使用以1为起始索引。我认为以1为起始索引更加合理,如果数组长度为1,则其中仅有一个元素;如果你正在访问第五个元素,则索引为5……就是这种感觉。 - Rook
2
由于这些领域中的所有材料(书籍、文章……等等)都使用该索引编写,所以一直想着索引翻译可能非常(极其)令人疲劳。 - Rook
10
C语言缺少指数运算符是因为大多数CPU没有指数指令。据我了解,在C语言中,运算符保留给大多数硬件可以在常数时间内执行的函数,最多只需要几条指令即可完成。 - rpetrich
显示剩余7条评论

9
Blitz++所竞争的并不是Fortran语言,而是用于Fortran数学库的人力。在某种程度上,语言有所帮助:老语言已经拥有了更多时间来获得优化编译器(而且,让我们面对现实吧,C ++是最复杂的语言之一)。另一方面,高级C ++库(如Blitz ++uBLAS)允许您比相对低级别的Fortran代码更清晰地表达意图,并允许进行全新类别的编译时优化。

然而,始终有效地使用任何库都要求开发人员熟悉语言、库数学。通过改善其中任何一个方面,通常可以获得更快的代码...


7

由于语言实现数组的方式不同,FORTRAN在数组处理方面通常比C ++更快 - FORTRAN不允许数组元素的别名,而C ++则允许。这使得FORTRAN编译器的工作更加容易。此外,FORTRAN拥有许多非常成熟的数学库,这些库已经存在了近50年 - C ++还没有存在那么长时间!


Fortran的EQUIVALENCE语句可以为数组元素创建别名。 - Pete Kirkham
是的,但编译器现在知道关于该别名的信息了。对于C++(和C),可能有许多编译器无法推断出来的别名。 - anon

3
C++的特点是它非常接近硬件层面。实际上,你可以通过汇编模块在硬件层面进行编程。一般来说,c++编译器在优化方面做得很好(为了获得巨大的速度提升,请启用“链接时间代码生成”,以允许函数在不同cpp文件之间内联),但如果你熟悉硬件并且具有相应的技能,你可以编写一些汇编函数,这些函数甚至可以更快地工作(虽然有时候你真的无法打败编译器)。
你还可以实现自己的内存管理器(这是许多其他高级语言所不允许的),因此你可以为自己的特定任务定制它们(也许大多数分配都是32字节或更少,那么你只需要拥有一个巨大的32字节缓冲区列表,可以在O(1)时间内进行分配/释放)。我相信只要你完全理解编译器和你正在使用的硬件,C++就能够击败任何其他语言。总体而言,最重要的是你使用的算法,而不是其他任何东西。

1
事实上,你可以在硬件层面上进行编程(通过汇编块)。而那段代码是……汇编语言,而不是C++。老实说,如果你把C++搞得面目全非,注入其他技术,那么你对这门语言并不十分诚实。 - MrMesees

2
这将在很大程度上取决于编译器、程序员,以及是否具有垃圾回收功能,差异可能会很大。如果直接编译成机器代码,则通常比解释性语言具有更好的性能,但是在达到汇编语言速度之前,存在有限的优化可能性。如果有人说Fortran略微更快,你会用它来编写新项目吗?

当然不是 :) 我更好奇的是可能会使它更快的因素 - 也许它表达得更少,因此可以做出更多的假设/优化,那样的事情。我不懂Fortran。 - Iraimbilanja

2

你可能在加载此页面时使用了一些奇怪的托管XML解析器。 :)

我们不断地针对代码进行性能分析,而且收益一直很稳定(这不是幼稚的C++,只是带有boost库的现代C++)。它比任何CLR实现都至少快2倍,经常快5倍甚至更多。比Java时代好多了,那时候快20倍,但你仍然可以找到优秀的实例,并消除所有的System.Object膨胀,将其打得毫无还手之力。

托管开发人员不明白的一件事是,硬件架构不支持VM和对象根方法的任何扩展。你必须亲眼看到才会相信,等等,启动一个浏览器并转到像Silverlight这样的“轻量级”VM。你会惊讶地发现它有多慢,需要大量CPU资源。

第二点,开发任何性能应用程序时,请使用本机数据库而非托管数据库。


1
通常情况下,算法而非编程语言决定了程序的性能表现。
在这个范畴内,优化编译器通常可以比大多数汇编程序员生成更好的代码。 过早优化是万恶之源
这可能是每个人都会重复的“常识”,但我认为这可能是因为它是正确的。我期待有具体证据来反驳这一点。

1

C#比C++快得多 - 在C#中,我可以在十分之一的时间内编写XML解析器和数据处理器,而在C++中则需要更长的时间。

哦,你是指执行速度吗?

即使考虑从编写第一行代码到第一次执行代码结束所需的时间,C#仍然可能比C++更快。

这是一篇非常有趣的文章,讲述了将C++程序转换为C#并使C++比C#更快所需的努力。

因此,如果考虑开发速度,几乎任何东西都能击败C++。

好的,针对OP的运行时性能要求: 不是语言本身,而是语言的实现决定了运行时性能。我可以编写一个生成最慢代码的C++编译器,但它仍然是C++。理论上也可以编写一个针对IA32指令而不是Java VM字节码的Java编译器,从而提高运行时速度。

您的代码性能将取决于语言的优势与代码的要求之间的匹配。例如,一个进行大量内存分配/释放的程序在一个天真的C++程序中(即使用默认内存分配器)中表现不佳,因为C++的内存分配策略过于泛化,而C#的基于GC的分配器可以更好地执行(如上面的链接所示)。字符串操作在C++中很慢,但在像php、perl等语言中很快。

3
我已经足够熟悉C++,可以以与使用C#或python3相同的速度编写代码。这只需要10年的经验。 - Zendel
这意味着你说的话在整整10年里都不是真的 :) - user519179

1

在实际应用中,D有时比C++更快,这在很大程度上是因为垃圾回收的存在帮助避免了使用智能指针时RAII和引用计数的开销。对于分配大量具有非平凡生命周期的小对象的程序,垃圾回收可能比C++风格的内存管理更快。此外,D的内置数组允许编译器在某些情况下执行更好的优化,而C++的STL向量则不被编译器所理解。此外,D2支持不可变数据和纯函数注释,最近版本的DMD2基于此进行了优化。D的创造者Walter Bright在D和C++中都编写了JavaScript解释器,据他说,D版本更快。


垃圾回收逻辑不应该适用于其他像Java和C#这样的垃圾回收语言吗? - Nikhil
是的,这些语言有时也比C++更快,但D更常见,因为它在其他地方的开销较小。 - dsimcha
BLADE呢?它是否曾被与blitz或fortran进行基准测试比较过? - Ellery Newcomer
这是一个利用D语言的编译期编程特性,生成据称接近最优的X86浮点代码的库。我不知道它现在的状态如何,但在几年前引起了很大关注。 - Ellery Newcomer
今天,LDC编译的代码应该比BLADE表现出色得多,因为LDC可以矢量化并使用SSE/AVX与典型的LLVM优化。 - Quonux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接