我是否正在使用朱莉娅?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我是否正在使用朱莉娅?相关的知识,希望对你有一定的参考价值。
几个月前我开始使用朱莉娅,经过数周的听证会,人们赞美它的各种功能,我决定尝试一下。我对它的了解越多,我就越喜欢它的风格,在高级语言中融合表达概念的易用性,注重速度和可用性。我实现了一个我在Julia中用C ++和R编写的模型,发现Julia版本的运行速度比R版本快得多,但仍然比C ++略慢。即便如此,代码在Julia中比在其他语言中更清晰。这是值得的,特别是当我推广该模型时,为扩大Julia代码范围所做的工作量远远低于其他语言中可比的工作量。
最近,我一直专注于让我的Julia代码运行得更快,因为我需要运行这个模型数万亿次。在这样做的过程中,我一直受到@code_warntype
,@time
,@profile
和ProfileView
以及track-allocation
旗帜的指导。大。这个工具包不像其他语言的分析工具那么好,但它仍然指出了很多瓶颈。
我发现我在我的代码中恰好具有我喜欢的朱莉娅的高级表现力,当我重写那种表达性以避免不必要的分配时,我失去了那种表达能力。作为一个简单的例子,我最近更改了一行代码
sum([x*y for x in some_list, y in similar_list])
循环迭代列表并添加到状态变量。不是火箭科学,我理解为什么不必分配数组更快一点。实际上它的速度要快得多。所以我做了类似的事情,避免使用Dicts或“感觉”正确的问题的复合类型,当我可以只是手动跟踪临时并行数组中的索引,一种编码风格,我厌恶但显然运行一个当我重复创建和简单地使用小数据结构的特定操作时,要快很多次。
一般来说,这很好,因为我已经开始注意编写简短方法的指令,因此组成我自己的较短方法的行为的高级方法不需要“担心”较短的方法如何工作;较短的那些可能是笨重的阅读而不会使我的程序的核心笨重阅读。
但这让我想知道我是否“错过了什么”。如果语言的整个要点(对我来说,作为一个非理论相关的最终用户)部分地将速度与易于开发/思考/阅读/维护等结合起来,即成为可写和可用的技术计算语言,然后这并不意味着我不应该花时间考虑最快的方法来添加一堆数字,不应该重写“易于阅读”或优雅的代码,利用映射,过滤器和将高级功能概念转化为“笨重”的代码,重新发明轮子,以低级别跟踪数组索引的方式表达那些东西? (我的某些部分期望在其设计背后具有如此多智能的语言足够聪明以“弄清楚”当我写sum([x * y])时它实际上不需要分配新数组,并且我太过于愚蠢地找出正确的语言来告诉语言,除了通过字面“手动”告诉整个循环业务。有一次我甚至考虑编写@macros
来“转换”一些快速表达的代码到长但是更快的循环表达式,但我认为如果我本质上试图扩展编译器的函数只是为了解决相当简单的问题,我必须考虑错误的问题,这就是我写这个问题的原因。)
也许答案是“如果你想要真正的高性能代码,无论如何都要付出代价。”或者换句话说,快速代码与令人讨厌的读取循环,数组,跟踪索引等令人不愉快的代码是速度易读性权衡空间的有效前沿。如果是这样,这是完全有效的,因此我不会说我认为朱莉娅更少。我只是想知道这种编程风格是否真的在前沿,或者我的体验是什么,因为我只是没有用语言编写“好”。 (通过类比,请参阅问题What is your most productive shortcut with Vim?,其中接受和优秀的答案基本上是OP没有“得到”它。)我怀疑即使我已经成功地让语言做了大量的事情我想,我只是不“得到”某些东西,但我不太了解要求的东西,因为我害怕我得不到的东西对我来说是未知的。
TL; DR:在Julia的最佳实践中,我花了很多时间将我的高级函数调用“分解”为循环和数组的原始实现,以获得更快的性能,或者是指示性的我没有考虑正确编程/使用该语言?
我认为这个主题与Julia-users组Does Julia really solve the two-language problem?上的讨论非常接近,我想在这里引用一个段落:
@Stefan Karpinski:
每种语言都有不同的编写代码样式和级别。有高度抽象的C ++,并且有低级指针追逐C ++,基本上是C语言。即使在C语言中,编程的void *风格也是有效的动态类型而没有安全性。鉴于这一事实,我不确定从这篇文章提出的角度来看解决这两种语言问题会是什么样子。只执行一种编程风格听起来像是一个问题,而不是解决方案。相反,我认为Julia最大的优势之一是它能够适应各种各样的编程风格和级别。
我自己在Julia编程方面的经验表明,它可以填补现代编程语言的空白框,可以在科学家,工程师和所有计算专家和实用程序员手中带来高级功能,如并行处理,套接字服务器......希望使用一体化编程语言以高效,可维护和可读的方式开展工作。 在我看来,你正在以正确的方式使用Julia,Julia像其他语言一样代表不同情况下的不同编程风格,你可以优化瓶颈以提高速度,并保持其他部分更具可读性。你也可以使用像Devectorize.jl这样的工具来避免重写问题。
这是一个令人满意的难以回答的问题。因此,我会尽量做出简短的贡献,希望不同意见的“底池”可能足够好。所以这里有3个意见:
- 编程语言可以比作具有动量的对象。用户群是它的质量和它们的风格对它施加的力量。初始用户/开发人员可以在某个方向上拉语言,因为它仍然具有较低的质量。即使非常流行(例如C / C ++),语言仍然可以发展,但它更难。朱莉娅的未来仍然是不成文的,但它的承诺是在创作者和早期用户的最初方向。
- 优化最好延迟,直到正确性得到充分测试。 “过早优化是万恶之源”(D. Knuth)。再次记住这一点永远不会伤害。因此,保持代码可读和正确是更好的,直到可能混淆代码的有界区域的优化阶段。
- 表达式
sum([x*y ...])
可能要求编译器过于聪明,简单地定义sumprod(x,y)
可能更好。这将允许sumprod
利用Julia的通用函数多调度框架并保持针对x
和y
进行优化,并且可能稍后甚至针对特定类型的x
和y
进行优化。
就是这样,现在。意见很多。所以让讨论继续下去。
你能写一个为你抽象这些概念的类(即FastDict或FastList或其他)吗?然后,在具有高性能代码时,您将具有相同的易读性(如果多一点黑盒子)。
背景:我是一名R / Rcpp程序员,现在已经使用Julia大约一个月了。我编写的至少一半R代码调用了我编写的C ++代码。
结论:我认为Julia解决了两种编程语言问题,也是可能的。这并不意味着可以编写高性能代码,就好像它是本机R / Python一样,但它大大降低了编写高性能所需的工作量,这些工作可以被其他人轻松使用。
进一步的讨论:首先,我认为,如果不考虑C / C ++类型问题,即无法编写高性能代码,即声明类型,考虑高效的数据结构而不是可读的数据结构等等,我认为根本不可能编写高性能代码。所以它是我的观点是,如果一个人希望他们有一个高性能语言,而不需要关心数据结构,那么他们就不走运了。当然,我是统计学家而不是CS人,所以我承认我在这里错了。
但是,我有点惊讶于使用Julia,我的工作时间似乎被削减了多少。特别是,我的很多工作都涉及首先为一些计算密集的部分编写一些C ++代码。一旦启动并运行,我基本上是在本机R中编写R包装器和数据处理器来为我的C ++代码准备数据。预处理通常不是计算上昂贵的,并且R有很多很好的工具来实现这一点。如果一切都经过精心策划,理论上这不是一个糟糕的过程。
然而,实际上,实际发生的是我让所有事情都运行起来然后我意识到我想要出于某种原因改变一些C ++代码。这是令人头疼的问题。不幸的是,在这一点上,我经常最终得到我所有数据的两个版本;一个传递给一堆本地R预处理工具的东西,另一个传递给C ++对象的东西。使用某些C ++对象会对所有R对象产生很多影响。老实说,我浪费了太多时间试图解决所有问题。
到目前为止,我对朱莉娅的经历是,这种头痛已经消失了。我正在使用的数据不再是R版本和C ++版本。只是朱莉娅。这也意味着将其他人的代码引入代码的高性能部分非常容易。就像最近的一个例子,我一直想要使用Matern协方差函数。这是一个非常重要的功能,我不想自己实现它。我可以找到很多拥有R软件包的人在本机R中实现了很好的,记录良好的调用。但是,在我的情况下,我真的很想从C ++中调用它而不需要所有本机R开销。这意味着要么(a)我需要搜索每个人,不一定有很好的文档记录,也不一定是用户友好的C ++代码在他们的R包中或(b)重新发明轮子。另一方面,如果我使用的是Julia,应该是如果有人为世界编写了一个很好的Matern协方差函数,我应该能够直接使用它而不是在他们的代码中挖掘我真正想要的调用使用。
当我开始构建更复杂的Julia项目时,我可能会发现一些类似的麻烦,我还没有意识到。但到目前为止,它似乎真正改进了将易于使用的工具(即R,类似Python的调用)与高性能代码相结合的过程。
以上是关于我是否正在使用朱莉娅?的主要内容,如果未能解决你的问题,请参考以下文章