朱莉娅快速吗?

2021-06-20 23:14:44

朱莉娅表现的概述了你可以且不能期待的。 围栏缝合指南思考是否使用朱莉亚进行高性能计算。 似乎很难相信动态语言可以快速,但朱莉娅在某种程度上是真正的性能,我认为人们有很难缠绕的头部。 我在我的Accu 2021会议谈话中详细解释了这一点:朱莉娅 - 埃里克·埃尔赫姆之旅 但这约为1.5小时,所以这是快速的破旧。 我在朱莉娅使用无意义的函数只是为了演示高度动态的代码在朱莉娅中可以优化。 功能foo(xs ...)ys = map(xs)do x t = typeof(x)k =转换(t,2)c =转换(t,3)k * x + c * x结束和(ys) 结尾 理解它确实的确切是重要的。 在此代码中想要突出显示的是许多事实: 任何地方都没有说明了任何示意信息。 很多人朱莉娅表现来自类型的注释。 不对。

优化应该很难考虑到它具有可变数量的参数XS ......编译器如何知道如何优化,当args的数量仅在运行时已知?

代码非常动态。数组XSI中的每个元素X的类型抬头查看(x)。你不能原则上的东西在编译时知道。然后将整数常量2和3转换为x的任何类型。

地图函数通过了内核或匿名函数,这是此代码块:

do x t = typeof(x)k =转换(t,2)c =转换(t,3)k * x + c * x结束

这往往很难优化。使用Python的人应该习惯这一点。如果将某些自定义Python代码内核传递给具有C ++代码的模块,则会很难优化。同样,如果将函数指针传递给另一个C函数,则编译器不能优化它,因为它无法提前知道哪些功能将被传递为参数。

考虑到这一点。尝试想象在Julia命令行在julia命令行中运行以下表达式的机器代码会产生多少机器代码的球场:

下面可以看到机器代码这变成了。现在你可能不知道x86汇编,所以让我稍微散步。 ADDQ指令是简单的添加,leaq是另外的添加和移位(乘以数量的数字为2),并且RETQ返回结果。

换句话说,高度动态和复杂的代码被朱莉娅JIT编译器进入了基本上没有。编写为通用和动态的代码,因为即使在C或Fortran中也是不可能转换为此有效的机器代码。美丽是看看方法调用变为什么机器代码是多么容易。以下是我在Julia命令行中发现的方式:

您可以简单地将宏@code_native放在您要查看哪种机器代码julia的表达式中。

在SC19,2019年超级履历国际会议,朱莉娅创造者Alan Edelman叙述了Massachusetts理工学院(麻省理工学院)的一群人在朱莉娅重新装修他们的福特兰气候模型。他们提前确定他们会容忍他们的代码的3倍减速。这是一个可接受的权衡,以获得高级别的语言,在他们的观点中获得更高的生产力。相反,他们通过去朱莉娅来获得3倍的速度增强。

对于真正苛刻的任务,我们将在超级计算机上运行它们。直到Julia出现在世界上,只有三个Langauges在世界上取得了Petaflops性能:C,C ++和Fortran。

朱莉娅是世界上第若要的语言,这已经在超级计算机上运行,​​以实现Petaflops性能。这就是为什么它正在使用。对于下一代气候模型,由例如: Clima以及像Celeste这样的天文项目。

Climatemachine.jl - Github上的Clima Julia源代码。您可以看到自己如何使用朱莉娅而不是Fortran建造下一代气候模型。由CALTECH,MITA和NAS JPL科学家建造。

Celeste.jl - 通过处理在1.54 petaflops的650 000核心上处理178岁的数据,在天文图像中找到和描述天文图像中的星星和星系。

目前,我们正在了解朱莉娅版的时间荣誉卓越的图书馆,如Blas,已经在Fortran上进行了优化数十年。然而,Julia实现的早期考验表明它们是表现优于福特兰人。鉴于Fortran是数字代码的低级编程语言,这是一个壮举。

然而,这不是科学家越来越多地切换到朱莉娅的关键原因,以实现高性能。今天的关键挑战是异因计算。我们越来越多地通过使用多核,GPU,SIMD指令,多台计算机,专用矢量处理单元等来挤压性能。这会产生很多复杂性。您如何快速开发,测试和迭代所有这种硬件。像C / C ++和FORTRAN等静态类型的编译语言成为主要的瓶颈。

这是朱莉娅在朱莉娅有多容易做的例子。假设您称机器学习培训函数(我们在此示例中使用的磁通库):

在Julia中,您可以使用来自CUDA.JL包的GPU功能简单地将输入转换为存储在GPU内存中的数据。你可以看到完全相同的火车!函数被称为包裹相同的参数。

这是一个非常重要的事情来实现这一点。火车!尚未为GPU编写。它不知道它正在通过生活在GPU内存中的数据。如果代码在GPU或CPU上运行代码,则没有IF-ELSE语句。相反,Julia利用其杀手功能多次调度。这允许专门用于不同类型的代码。 Julia Jit将简单地生成GPU代码,因为在火车内数学运算符之间的所有交互!涉及GPU类型。这是非常强大的。它允许您在CPU上以交互式方式开发代码。您可以逐步执行代码并测试它。当您快乐的工作时,会恢复最小的更改,以获得在GPU上运行相同的代码。

在跳上朱莉亚火车上的所有退出之前,并将您的Python或C ++代码转换为朱莉娅,还有一些东西可以了解。朱莉娅不是魔法。为Python或C ++精细调整的代码不一定在Julia上使用天真的端口快速运行。您必须正确地学习Julia并了解其性能模型。

在其他语言中,人们将以朱莉娅提供高性能的方式优化。例如。 C / C ++编码器通常可以尝试避免函数调用,尤其是虚拟呼叫。因此,在许多其他语言中,人们经常用于更大的功能以避免开销。在Python函数中,呼叫开销非常高,这一个试图通过将东西推入numpy并避免类似于循环的内容来实现。朱莉娅几乎相反。要在朱莉亚获得最大性能,通常需要执行以下操作:

更喜欢If-statements上的动态调度。您不应该在朱莉亚的具体类型明确地进行代码检查。

朱莉娅也有一些独特的壁炉,你可能不习惯。在Julia型稳定性是alpha-omega。代码应以一种方式编写,使得函数内的值的类型不会变化。您应该尝试在功能稳定中保持值的类型。

我看到人们抱怨在移植到朱莉娅后没有看到速度改善的次数。通常他们做了一个天真的港口,实际上并没有学习如何优化朱莉娅代码。其他经典错误是忘记他们之前的Python代码实际上是主要是C / C ++代码。如果在C / C ++代码中编写的图书馆进行了所有繁重的举重,它已经过分优化,那么年轻的朱莉娅图书馆可能不会更快。朱莉娅是一种年轻语言,而不是每个图书馆都得到了最大潜力。

但朱莉娅社区的经典讨论是一些人发布了朱莉娅跑速势速度较慢的例子。在短时间内,Julia专家已经探讨了它,发现了比竞争更高的绩效代码瓶颈和热潮。那是朱莉娅的美丽。这是“乌龟一路下来”,意思是朱莉娅是Julia代码。你发现一个问题,你通常可以自己解决这个问题。除非您是C / C ++向导,普通Python开发人员无法修复或优化像numpy或tensorflow等大库。在Julia,其用户倾向于为他们自己使用的图书馆贡献更多。

因此,将朱莉娅表现视为强大的潜力而不是保证的东西非常重要。朱莉娅为您提供了语言功能和JIT编译器,使您可以优化Julia代码并将其快速或比C / C ++或Fortran更快。使用像Python这样的语言,您可以更快地达到可能做的最佳状态。

好的,我希望这不会是名字,但让我试着阐明我的意思。我是一个旧的C / C ++开发人员。我不能说我曾经发现它很容易理解C / C ++代码。我可以看到朱莉娅唯一的优势是我倾向于当内存分配和释放以及其布局时更好地掌握。

然而,朱莉娅在我看来更容易理解和处理。您可以编写微小的功能并快速检查他们变成的代码。您可以以各种方式配置个人功能,并且JIT可以警告您对损害性能的编码选择。这种一次专注于一个小功能的能力使我更容易理解我的观点中的性能和优化。使用C ++,您将始终处理整个文件。没有交互式环境,很难快速更改和观察性能变化。在朱莉娅,我可以在我的代码编辑器中进行小的更改,并立即立即基准在REPT中的一个功能。

在C / C ++中,如果您发现性能因使用CPU缓存的使用不好,您可能希望通过例如更改内存布局。 将结构阵列转换为阵列的结构。 在C / C ++中,这将需要重大代码重写。 在Julia中,您可以将数据类型作为类型参数传递给StructArray参数化类型。 所有现有代码都将相同。 事实上,这甚至可以与GPU上的数据相结合。 Julia图书馆与任何其他编程语言不同。