F#在科学计算中的表现

Any*_*orn 71 c++ parallel-processing performance f# scientific-computing

我很好奇F#性能与C++性能的对比情况如何?我问了一个关于Java的类似问题,我得到的印象是Java不适合重编码.

我已经读过F#应该具有更高的可扩展性和更高的性能,但这种真实性能与C++相比如何呢?关于当前实施的具体问题是:

  • 浮点数有多好?
  • 它是否允许矢量指令
  • 对优化编译器有多友好?
  • 它有多大的记忆足迹?它是否允许对内存位置进行细粒度控制?
  • 它是否具有分布式内存处理器的容量,例如Cray?
  • 在涉及大量处理的计算科学中,它可能具有哪些特征?
  • 是否有使用它的实际科学计算实现?

谢谢

Jon*_*rop 62

我很好奇F#性能与C++性能的对比情况如何?

根据应用的不同而变化很大.如果您在多线程程序中广泛使用复杂的数据结构,那么F#可能是一个巨大的胜利.如果你的大部分时间花在紧密的数字循环变异数组上,那么C++可能会快2-3倍.

案例分析:射线追踪我的标杆这里使用树状分层扑杀和数字射线球路口代码来生成输出图像.这个基准测试已有几年的历史了,多年来C++代码已经被改进了几十次,并被成千上万的人阅读.Microsoft的Don Syme设法编写了一个F#实现,当使用MSVC编译并使用OpenMP进行并行化时,该实现比最快的C++代码略.

我已经读过F#应该具有更高的可扩展性和更高的性能,但这种真实性能与C++相比如何呢?

使用F#比使用C++更容易,更快地开发代码,这适用于优化和维护.因此,当您开始优化程序时,如果使用F#而不是C++,相同的工作量将产生更大的性能提升.但是,F#是一种更高级别的语言,因此对性能的上限较低.因此,如果您有无限的时间来进行优化,理论上,您应该始终能够在C++中生成更快的代码.

当然,这与C++对Fortran和Fortran在手写汇编程序上的优势完全相同.

案例研究:QR分解这是LAPACK等图书馆提供的线性代数的基本数值方法.参考LAPACK实现是2,077行Fortran.我在80行代码中编写了一个F#实现,可以达到相同的性能水平.但参考实现并不快:像英特尔数学核心库(MKL)这样的供应商调优实现通常要快10倍.值得注意的是,我设法优化了我的F#代码,远远超出了在英特尔硬件上运行的英特尔实现的性能,同时保持我的代码在150行代码和完全通用(它可以处理单精度和双精度,以及复杂甚至符号矩阵!):对于高薄矩阵,我的F#代码比英特尔MKL快3倍.

请注意,本案例研究的道德并不是您应该期望您的F#比供应商调整的库更快,而是即使像英特尔这样的专家如果只使用较低级别的语言也会错过高效的高级优化.我怀疑英特尔的数值优化专家未能充分利用并行性,因为他们的工具使得它非常麻烦,而F#使它毫不费力.

浮点数有多好?

性能类似于ANSI C,但.NET不提供某些功能(例如舍入模式).

它是否允许矢量指令

没有.

对优化编译器有多友好?

这个问题没有意义:F#是Microsoft的专有.NET语言,只有一个编译器.

它有多大的记忆足迹?

一个空的应用程序在这里使用1.3Mb.

它是否允许对内存位置进行细粒度控制?

比大多数内存安全语言更好,但不如C语言好.例如,您可以通过将它们表示为"结构"来取消F#中的任意数据结构.

它是否具有分布式内存处理器的容量,例如Cray?

取决于"容量"的含义.如果您可以在Cray上运行.NET,那么您可以使用F#中的消息传递(就像下一种语言一样),但F#主要用于桌面多核x86计算机.

在涉及大量处理的计算科学中,它可能具有哪些特征?

内存安全意味着您不会遇到分段错误和访问冲突..NET 4中对并行性的支持很好.通过Visual Studio 2010中的F#交互式会话即时执行代码的能力对于交互式技术计算非常有用.

是否有使用它的实际科学计算实现?

我们在F#中用于科学计算的商业产品已经有数百个用户.

但是,您的质疑线表明您将科学计算视为高性能计算(例如Cray)而非交互式技术计算(例如MATLAB,Mathematica).F#适用于后者.

  • @ZXX:我把它卖掉了. (14认同)
  • 你还没有完全发布那个据称胜过MATLAB的F#实现:-) (2认同)
  • 这篇文章充满了未经证实的断言.F#轻松让您创建比C++更高效的代码的想法尤其值得怀疑.我已经非常深入地参与了F#,包括许多PR来加速高阶数组函数,我可以向你保证,通常情况并非如此.F#的创建者可以在F#中创建比在C++中更快的东西,这可能会更多地说明你在每种语言中的相对天赋,而不是任何先天属性. (2认同)

Tom*_*cek 43

除了其他人所说的,还有一个关于F#的重要观点,那就是并行性.普通F#代码的性能由CLR决定,尽管您可以使用F#中的LAPACK,或者您可以使用C++/CLI作为项目的一部分进行本机调用.

但是,精心设计的功能程序往往更容易并行化,这意味着您可以通过使用多核CPU轻松获得性能,如果您正在进行一些科学计算,这些CPU绝对可用.以下是几个相关链接:

关于分布式计算,您可以使用可用于.NET平台的任何分布式计算框架.有一个MPI.NET项目,它适用于F#,但您也可以使用DryadLINQ,这是一个MSR项目.


Joh*_*Joh 40

  • F#执行浮点计算的速度与.NET CLR允许的速度一样快.与C#或其他.NET语言没有太大区别.
  • F#本身不允许向量指令,但如果你的CLR有这些的API,F#应该没有问题使用它.例如,见Mono.
  • 据我所知,目前只有一个F#编译器,所以问题应该是"在优化时F#编译器有多好?".答案在任何情况下都"可能与C#编译器一样好,目前可能稍差一些".请注意,F#与C#的不同之处在于它在编译时支持内联,这可能允许更高效的代码依赖于泛型.
  • F#程序的内存脚印与其他.NET语言类似.您对分配和垃圾回收的控制量与其他.NET语言相同.
  • 我不知道对分布式内存的支持.
  • F#具有非常好的原语用于处理平面数据结构,例如数组和列表.在Array模块的内容中寻找例子:map,map2,mapi,iter,fold,zip ...数组在科学计算中很受欢迎,我想由于它们本身具有良好的内存局部性.
  • 对于使用F#的科学计算包,您可能想看看Jon Harrop在做什么.

  • 我只想指出问题是F#vs**C++**,这个答案是F#vs**C#**,C++和C#是不同的语言. (7认同)

Rob*_*vey 16

与所有语言/性能比较一样,您的里程在很大程度上取决于您的编码能力.

F#是OCaml的衍生物.我很惊讶地发现OCaml在金融世界中被广泛使用,其中数字运算性能非常重要.我更惊讶地发现OCaml是速度更快的语言之一,其性能与最快的C和C++编译器相当.

F#建立在CLR之上.在CLR中,代码以字节码的形式表示,称为公共中间语言.因此,如果代码写得很好,它可以从JIT的优化功能中受益,并且具有与C#(但不一定是C++)相当的性能.

通过使用本机映像生成器(NGEN),可以在运行时之前的单独步骤中将CIL代码编译为本机代码.由于不再需要CIL到本机编译,这加速了软件的所有后续运行.

需要考虑的一件事是像F#这样的函数式语言受益于更具说明性的编程风格.从某种意义上说,您过度使用C++等命令式语言来指定解决方案,这限制了编译器的优化能力.从理论上讲,更具说明性的编程风格可为编译器提供额外的算法优化机会.

  • 是的,所以*如果*你使用内联函数和*只*使用无副作用的操作(即没有.NET互操作),那么它可以重新排序.不幸的是,正如可以用反射器验证的那样,普通的F#函数*被编译成.NET方法.MS本身在关于内联函数的MSDN页面上说"你应该避免使用内联函数进行优化,除非你已经尝试了所有其他优化技术".但即使你这样做,F#的优化将使C++中的类似代码(静态内联)无法实现?在手动帮助下,我确信F#是朝着正确方向迈出的一步 - 但它不是Haskell. (2认同)

Yin*_*Zhu 9

这取决于你正在做什么样的科学计算.

如果您正在进行traditional heavy computing,例如线性代数,各种优化,那么您不应该将您的代码放在.Net框架中,至少不适合F#.因为这是在算法级别,所以大多数算法必须以命令式语言编码,以便在运行时和内存使用方面具有良好的性能.其他人提到并行,我必须说当你做一些像SVD实现并行的低级别的东西时它可能是无用的.因为当你知道如何并行SVD时,你根本就不会使用高级语言,Fortran,C或者修改过的C(例如cilk)都是你的朋友.

然而,今天的许多科学计算都不属于这种类型,这是某种高级应用,例如统计计算和数据挖掘.在这些任务中,除了一些线性代数或优化之外,还有很多数据流,IO,预处理,做图形等.对于这些任务,F#非常强大,因为它简洁,功能,安全,易于平行等

正如其他人所提到的,.Net很好地支持平台调用,实际上MS内部的很多项目都使用.Net和P/Invoke来提高瓶颈性能.

  • 这些算法的运行时间是用触发器测量的,高级语言很难衡量.内存使用情况也难以预测,在C和Fortran中,您可以精确计算您将使用的字节数. (2认同)
  • "通过检查以命令式语言来表现性能更容易"与"只有命令式语言提供良好性能"非常不同.而且也错了.诸如高速缓存一致性之类的二阶效应在现代处理器上非常重要,FLOP中的测量算法毫无价值.在FLOP优化算法和需要10倍FLOP的位置优化算法之间,地点优化算法将获胜.在我之后重复:FPU不再是瓶颈. (2认同)

kvb*_*kvb 7

不幸的是,我认为你不会找到很多可靠的信息.F#仍然是一种非常新的语言,所以即使它非常适合性能繁重的工作负载,仍然不会有那么多具有丰富经验的人报告.此外,性能很难准确测量,微基准测试难以概括.即使在C++中,您也可以看到编译器之间的巨大差异 - 您是否想知道F#是否与任何 C++编译器或假设的"最佳"C++可执行文件竞争?

至于针对C++的具体基准,这里有一些可能相关的链接:O'Caml vs. F#:QR分解 ; F#vs非托管C++用于并行数字.请注意,作为F#相关材料的作者和作为F#工具的供应商,作者对F#的成功有着既定的兴趣,因此请谨慎对待这些说法.

我认为可以说有一些应用程序,其中F#在执行时间具有竞争力,而其他一些应用程序则不具备竞争力.在大多数情况下,F#可能需要更多内存.当然,最终的表现也将高度依赖于程序员的技能 - 我认为F#几乎可以肯定是一个更有效率的语言,可以为一个适度称职的程序员编程.此外,我认为目前,对于大多数任务而言,Windows上的CLR在大多数操作系统上的性能优于Mono,这可能也会影响您的决策.当然,由于F#可能比C++更容易并行化,因此它还取决于您计划运行的硬件类型.

最后,我认为真正回答这个问题的唯一方法是编写F#和C++代码,代表您要执行的计算类型并进行比较.

  • @RuneFS - 在O'Caml中实现良好的性能通常是以不使用其更高级别结构为代价的(例如,参见http://www.janestreetcapital.com/minsky_weeks-jfp_18.pdf的第3.3节).在谈论现实世界中的F#性能时,唯一当前的F#实现在.NET(CLR或Mono)上运行的事实也意味着某些优化可能不可用.我是一个巨大的F#粉丝,并且在未来进一步优化可能会提供更快的速度,但目前我怀疑有许多应用程序,其中"最佳"C++代码将胜过"最佳"F#代码. (8认同)
  • f#_compiler_可能是新的(并且由F#编译器生成的代码的性能未知)但F#的功能导向部分远非新的.它可以没有变化(这只适用于以特定方式写入的F#)被编译为已经存在了几个世纪的OCaml.如果F#中的优化器与OCaml优化器相同,则OCaml可证明是一种非常优化的语言(由于其不可变性),那么重数字运算非常适合F# (3认同)