Fortran与Julia的问题

小僧多年前最早使用之语言即是Fortran,至今仍对其非常怀念。当时渴望出现一款类似于Fortran同时具备modern package manager和 data visualization toolbox的compiled language, 就可以避免使用异常笨重的Matlab。随着Julia的出现,这一渴望部分得到了met.

我有三个问题,第一,Julia现在还有多大的优化空间?是否未来能够真正达到Fortran的速度,我个人做finite difference的时候手写的Fortran还是很快。我没有用过Julia的static array之类的包。

第二,鉴于论坛Fortran用户很多,我相问为什么Fortran没能向C++一样进化出一套很好用的standard library.

第三,我听说只要肯砸钱优化,很慢的语言也可以达到非常的速度,比如google对javascript的改造。如果这样的话,是不是意味着Matlab,R,和Python也能优化到Julia的速度。

我现在是用着fortran,学习Julia语言并注视其发展。

我不是Fortran用户,但调过一些简单的Fortran库,比如L-BFGS-B, 能看懂一点Fortran。 个人感觉Fortran77还是比较原始的,甚至要按照一定的格式写,语言的特性也不是很现代(经常要用goto跳转?),这种语言执行效率很高,但如果要作为workhorse language,开发上的效率是个挺大的问题。

第一,Julia现在还有多大的优化空间?是否未来能够真正达到Fortran的速度

代码执行上的效率还是很难达到的,目前Julia的BLAS库还是调的Fortran代码,虽然现在社区里也有人正在研究用纯Julia实现BLAS,但感觉一时半会还是赶不上Fortran优化多年的成熟库,对这块感兴趣可以关注一下官方slack的#linear-algebra频道。 如果考虑开发效率,Julia有着显著的优势,在实际开发中,对于效率要求很高的部分,可以用Fortran实现,然后从Julia调Fortran。由于Julia调Fortran的FFI非常简洁,所以这里产生的two language problem不是那么的明显。

第三,我听说只要肯砸钱优化,很慢的语言也可以达到非常的速度,比如google对javascript的改造。如果这样的话,是不是意味着Matlab,R,和Python也能优化到Julia的速度。

理论上是能发生的,但实际上未必可行。Matlab,R,和Python语言面向的用户在设计之初都有自己的考虑,高性能数值计算可能并不是当时设计的主要目标。经过多年的发展,一些历史兼容性问题可能会导致需要砸非常多的人力物力来实现优化,可能还不如回炉重做。而Julia作为新语言,把高性能科学计算放在设计首位,目标用户就是我们这些群体。

1 个赞

关于Python砸钱优化其实是真的有人做的。这件事情要从Pyston的失败说起:

http://blog.kevmod.com/2017/02/personal-thoughts-about-pystons-outcome/644/

Kristoffer Carlsson的观点是这样的

The thing I wish people understood about Python performance is that the difficulties come from Python’s extremely rich object model, not from anything about its dynamic scopes or dynamic types. The problem is that every operation in Python will typically have multiple points at which the user can override the behavior, and these features are used, often very extensively. Some examples are inspecting the locals of a frame after the frame has exited, mutating functions in-place, or even something as banal as overriding isinstance. "

Sure you can make Python fast in some cases where you use a small subset of the language. However, Python as a whole is extremely difficult to make fast because of the incredible freedom you have. The “compiler” can assume very little, so it is difficult to generate efficient code. Just consider the incredible amount of time and money that has been spent on trying to make it faster and the relatively mediocre success it has had (Pyston, Numba, PyPy etc).

简单来说正式Python的简单和动态造成了Python速度之慢。所以PyPy到现在依然不能完整编译所有的Python库(比如numpy你需要用他们自己改的版本)。Numba是自己实现了一套类型系统。

Numba和Julia的编译过程区别如下

可以看到 numba 因为需要重新从Bytecode读取Python的程序,基本上无法使用Python的原生语法。这就表现为numba只能支持Python的部分语法和类型。不是说不可能,但是目前看来想要实现PyPy这样的工程可能还不如来一个新的语言简单。再一个就是Python本身就是当胶水用的,大家本身也不是很在乎Python层面的性能(对于仅仅调用别的库的使用者来说),真正会感到痛苦的是开发Python库的人。

MATLAB 2018的for loop实际上已经很快了。如果真的去比性能可能真的不见得现在Julia会比MATLAB快,而且实际上从Julia的benchmark里看也并不是最快的。但是问却在作为一个起初不是general purpose的语言,为了能能够保持一定的向前兼容,不得不在新的feature上妥协,不容易像本身为工程化设计的语言一样写大工程。

然后Fortran和C++本身有动态语言相对脚本语言开发效率上的问题。但是这个很正常。按道理来说可以通过和一个动态语言结合(比如很多游戏采用Lua + C++,很多Python的库使用 Python + C++或者 Python + Fortran 95),这其实是目前很多科学计算的库的主要方案。再或者也有用Cython这样的相对Python来说low level一些语言去写的。但是这些大家都感受到了维护起来的麻烦。而且实际上有很多部分是重复的,甚至还会导致在上层动态语言里使用困难。比如tensorflow在Python底下又实现了一个XLA,和一些JIT设施,你在Python里调用tensorflow实际上是在Python里面写另外一个语言。这些东西实际上本来可以通过一个新语言,把很多工作交给编译器来完成。

Fortran其实也在发展,并不是很原始。说Fortran老有 goto 其实不是很正确。Fortran的问题是历史遗留的,Fortran2003之后也有面向对象,甚至2018都是支持函数式编程的。其实像C++ 11之后,新的Fortran也可以说有现代化改进。问题是Fortran的主要用户依然停留在Fortran 95(这个结论我没有仔细考证过,只是个人感受,也有可能不对),有一个很大的原因是只有Fortran 95才能被C调用(这个是GNU的工作,在C里面所有Fortran 95的函数都可以用 xxx_ 来直接调用),这也是为什么我们能在Python里面使用Fortran的一个很大的原因,而Fortran 2003之后,有了mod(类似于C++的模板),别的语言调用起来就很麻烦。我原来在科大的时候有一个用Fortran 2003写的库,本身很强大,甚至上过太湖。当时当你想用脚本语言去调用Fortran的时候基本上非Fortran 95不可。Fortran 2003之后的版本用的人少,没有像C++的pybind11这样好用的东西。

Julia理论上依然可以优化很多,因为Julia在设计语言的时候尽量保证不丢失类型信息(这也是实现多重派发所必须的)。实际上Julia0.7相比0.6就多了很多优化。这里仅仅举一个例子,你可以在NEWS.md和issue里面找到相关的工作

R我不是非常了解,据说也很慢,但是我就不多说了。C++的std也很少有人说好用吧(当然可能比Fortran强)?我们之前也主要用C++,其实我还改造过PyTorch (这个PR是C写的,完整的版本比较老,在私有repo里面,等PyTorch 1.0以后我应该还会继续努力让它支持复数):

你可以看到在PyTorch的工程里面其实boost是完全不用的,标准库里面也仅仅用了一些必要的但是不是性能敏感的地方(当然 shared_ptr 之类的很好用),但是这个代码量因为各种原因很大,实际上也不会需要这么大,比如MXNet的就会少很多。此外对于科学计算所需的多维数组C++以前的支持一直不怎么好(Eigen的tensor是最近两年才有的),然后标准库也没有这个东西。我觉得有一个问题不是标准库,而是到现在还是没有比较标准的官方的包管理器(当然现在可以间接通过pip来实现…)以至于标准库里支持了很多东西,然后还有一个超级集合boost,其实很多时候为了用一个小功能装一个boost也怪难受的,不装的话复制过来不一定能够跟上跟新,就得自己维护。这其实是一个刚需,大而全的标准库不见得是一件好事。

以至于甚至现在还有人喜欢用一个工具把整个C++库打包到一个文件里面去…

至于Fortran为啥没这样的标准库我猜还是用的人相对更少,大家复制一下代码,复制几个文件,当黑箱用用凑合凑合就完事儿了吧。

js不熟悉,不做评论,v8确实很快。

3 个赞

顺便提一句,Pyston的失败某种程度上正是创造Julia的动机(之一)。

Fortran77很原始,但是现在也已经有了f90,f95,f03,f08等现代语法。

我个人感觉Fortran比C++用起来舒服一些(更符合数学思维),尤其是原生的数组支持。Fortran 2008 的OOP和coarray非常好用。不过如你所说,用的人越来越少,即使在linux下包管理都很奇怪,再这么下去确实更加没人改进。

Julia的语法非常简单好用,如果goal是做free Matlab我觉得可以胜任了。不过好像想往Python方向发展,这就有点问题了,至少在data science这个方面Julia做的非常不够,比现有的dplyr和pandas, Linq都要差,做图也非常慢。

作图慢是因为Plots这个包真的慢。。。我推荐用GR这个包,非常快。然后确实如你所说data science的工具还比不上Pandas,但是也并不是完全不如Python。比如为大数据存储设计的HDF5格式的JLD就很好用,而且因为语言本身存储了比较完整的信息,你可以将任何一个Julia object存到JLD里面去。

其实也有人抱怨过Julia的DataFrame好像没Pandas快(这个可能依然需要重新测试),然后1.0开始也原生支持missing data(我相信这个应该是一个比较不错的优点吧)

往Python发展是目标,但是要知道Julia 1.0已经比过去很多语言的1.0耗时要少了(从12年到18年花了6年时间)rust花了8年(10年第一个版本),而要知道R和Python都是上个世纪开始的工程了。所以如果可以给Julia一些时间,我相信这些问题都是可以靠人力解决的(而不是技术上的困难)。

:sweat_smile: 是我接触的太少了

Fortran 2018是可以functional programming的:

http://fortranwiki.org/fortran/show/Fortran+2018

我平时是用GR的backend做图,不过速度还是一般,数据一大就不行。 Gadfly的色彩渲染比较好看,不过慢到吓人。DataFrame的速度和pandas差不多,不过比r的data.table慢几倍以上。JLD的读取速度非常慢,比R的data.table读csv还要慢十倍以上。

我个人认为Julia需要在data science方面提高很多,毕竟data science的用户远远多于做numerical computing的。不过说实话我还是更愿意看到Julia像Matlab一样专注于提高性能,花里胡哨的东西少搞。

首先要分清楚MATLAB是一个商业软件,其实作为商业软件不太容易像Python这些开源的通用语言有一个比较广的社区(当然MATLAB可以很容易地制定目标用户的计划)。而作为开源的通用语言,很难说指导这个社区做什么,对于Julia本身开发者来说他们只能不断地提供更好的编译器和语法支持。至于用来干嘛真的就是各显神通了。

HDF5作为二进制文件应该不会比CSV慢啊?你可以新开一个帖子看一下你的benchmark么?然后也可以试试JLD2.jl

JLD格式不是用来读CSV的哈,如果要读CSV就用专门的CSV包

然后这个十倍以上我觉得很有可能你把编译时间也算进去了,如果只读一次的话,因为现在的JIT不会先解释执行所以第一次运行一定会进行JIT的trace。测试性能用 BenchmarkTools.jl 才比较公平。

使用方法很简单

@benchmark xxx

绘图本身大部分的场景其实不需要JIT(因为可能也就画一次),我觉得这个将来这个包发展优化好以后就能解决这个问题(也就是静态编译Julia的代码)其实这个包起初也是有人觉得绘图程序太慢做的,不过还是不完善。

大数据绘图一般都需要调GPU后端,这个可以期待一下Makie

现在Julia对于只需要运行一次就能完成任务的场景不是很合适,因为这些场景很有可能压根不需要JIT。这个就需要等编译器底层进行一定的修改了,但是并不是不能做的。

我试过把csv的数据用r的data.table::fread读和在Julia里面转成JLD在读,100万行15列左右的data frame在Julia里面读起来非常慢。我一般直接用@time算时间,貌似不包括compilation时间吧。而且读取数据一般都是一次性的,这样的话compilatiion时间也要考虑。

如果用@time是算上了编译时间。如果只是比较速度就不公平。

但是实际上确实对于这种一次性的任务会更慢,只能等待类似于V8的技术用在Julia上面了(如果依然要保持动态性)。不过我不认为这个在技术上未来实现不了,只是不知道要到什么时候了…

如果写好的代码需要部署,可以用AOT编译器把这个overhead编译掉。

如果你用@benchmark 应该可以获得更准确的时间(因为会运行很多次)。

我觉得Fortran本身发展不慢,但是相关的库却好像没怎么发展了。如其他人也提到的那样,Fortran加入的新特性也越来越多。但是,有多少人去用这些特性就是另一回事了。比如我在一个Fortran群Fcode里面请教过大家Coarray的问题,居然没有几个人听说过,更不用说帮忙解答了。
Fortran的用户群体都是和我们一样搞科学计算的,可能多数人没有计算机基础知识,不懂程序编译过程,不使用版本控制,不懂性能优化,甚至都不会调试。我认识的人里面写了一两年Fortran还没用过Module、allocated array的多的是。这也怪不了他们,他们只用把程序跑出来能出论文就行了。开发Fortran的这些包总得有人来做啊,但是谁愿意做呢?水平低的或者有别的活的人不会去做,水平高的人写的东西可能也没人用。
现在有Julia这样的东西在,完全可以试试的。Julia的一些包有时可以达到和Fortran相关包相当的速度,比如DifferentialEquations。此外,Fortran也不总是很快,如果不仔细挑选编译器和函数库,可能计算也快不了。比如gfortran就比ifort慢很多。另一方面,Julia才1.0,在此之前还没有多少统一的标准,所以包的开发也很难一直跟上,编译器的优化也远远不够,这个都是可以期待的。

同意。Fortran的这些库好多都是77风格的,新一点的95用的人还可以,2003以及以后用的人不多。Fortran学起来很容易,原生的向量数组用起来很舒服。据我所知九十年代在美国的金融领域还有一些人使用Fortran, Kenneth French也是用Fortran. 不过现在已经没人用了,美国几个大的金融数据提供商都不再提供Fortran借口了。现在使用Fortran的应该主要在academia, 或者搞HPC的同学。

stackoverflow里面Fortran高手很多,貌似年龄都偏大。

语言的性能主要在算法和对硬件性能的利用率,Fortran这两点都不占优势。我个人觉得Julia还是有一个非常promising的前景的,希望能够在国内积累一些玩家。

我对Julia在国内的adoption的担忧主要在三点。第一,大学老师用的都很少,学生做科研也没有动力学。第二,公司用的更少,不利于就业。第三,网络环境太差(下载慢学习材料少),盗版太容易找到(好多人情愿使用盗版windows也不用linux, 盗版matlab用的人很多)。

1 个赞

个人感觉,Julia的流行是早晚的事情。由于他底层对python、fortran、c、c++的支持,以包的形式扩展进来,可以有效的利用这四种语言提供的库。
以我个人为例,数据常规处理和一些统计计算以及画图,python的效果,而且有着很多的机器学习算法可以直接调用。而一些图形上的几何算法,则可以调用c/c++库,速度不比直接用c/c++慢,更何况可以直接出图。
另外,最重要的,我是做最优化算法的,一些最优化工具Ampl都是收费的,一些算法求解器在其它语言上提供的接口并不是特别友好,而julia居然有针对这些求解器的包可以做统一的模型描述,这让我还是非常惊讶的。
无论是自由的语法表达还是便捷的部署,以及虽然年轻但是很好用的IDE,外加能够包罗万象的包管理,这些都是它能够快速发展的基础。
先不要着急诟病它的缺点以及不是特别靠谱的生产环境,毕竟,它才刚刚1.0

2 个赞