Julia 语言真的像它声称的那样快吗? [英] Is the Julia language really as fast as it claims?

查看:23
本文介绍了Julia 语言真的像它声称的那样快吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这篇文章之后,我决定将 Julia 与 GNU Octave 进行基准测试,结果与julialang.org 中说明的加速.

Following this post I decided to benchmark Julia against GNU Octave and the results were inconsistent with the speed-ups illustrated in julialang.org.

我用 CXXFLAGS='-std=c++11 -O3' 编译了 Julia 和 GNU Octave,得到的结果:

I compiled both Julia and GNU Octave with CXXFLAGS='-std=c++11 -O3', the results I got:

a=0.9999;

tic;y=a.^(1:10000);toc
Elapsed time is 0.000159025 seconds.

tic;y=a.^(1:10000);toc
Elapsed time is 0.000162125 seconds.

tic;y=a.^(1:10000);toc
Elapsed time is 0.000159979 seconds.

--

tic;y=cumprod(ones(1,10000)*a);toc
Elapsed time is 0.000280142 seconds.

tic;y=cumprod(ones(1,10000)*a);toc
Elapsed time is 0.000280142 seconds.

tic;y=cumprod(ones(1,10000)*a);toc
Elapsed time is 0.000277996 seconds.

朱莉娅

tic();y=a.^(1:10000);toc()
elapsed time: 0.003486508 seconds

tic();y=a.^(1:10000);toc()
elapsed time: 0.003909662 seconds

tic();y=a.^(1:10000);toc()
elapsed time: 0.003465313 seconds

--

tic();y=cumprod(ones(1,10000)*a);toc()
elapsed time: 0.001692931 seconds

tic();y=cumprod(ones(1,10000)*a);toc()
elapsed time: 0.001690245 seconds

tic();y=cumprod(ones(1,10000)*a);toc()
elapsed time: 0.001689241 seconds

有人能解释一下为什么 Julia 在这些基本操作上比 GNU Octave 慢吗?加热后,它应该调用 LAPACK/BLAS 没有开销,对吧?

Could someone explain why Julia is slower than GNU Octave with these basic operations? After warmed, it should call LAPACK/BLAS without overhead, right?

正如评论和答案中所解释的,上面的代码不是一个好的基准,也不能说明在实际应用程序中使用该语言的好处.我曾经认为 Julia 是一个更快的Octave/MATLAB",但它远不止于此.这是朝着高效、高性能、科学计算迈出的一大步.通过使用 Julia,我能够 1) 在我的研究领域中胜过用 Fortran 和 C++ 编写的软件,以及 2) 为用户提供更好的 API.

As explained in the comments and answers, the code above is not a good benchmark nor it illustrates the benefits of using the language in a real application. I used to think of Julia as a faster "Octave/MATLAB", but it is much more than that. It is a huge step towards productive, high-performance, scientific computing. By using Julia, I was able to 1) outperform software in my research field written in Fortran and C++, and 2) provide users with a much nicer API.

推荐答案

.^ 这样的向量化操作正是 Octave 擅长的,因为它们实际上完全用专门的 C 语言实现代码.在构建 Octave 时编译的代码中的某处,有一个 C 函数计算 .^ 为一个双精度和一个双精度数组 - 这就是你在这里真正计时的地方,而且速度很快,因为它是用 C 编写的.另一方面,Julia 的 .^ 运算符是用 Julia 编写的:

Vectorized operations like .^ are exactly the kind of thing that Octave is good at because they're actually entirely implemented in specialized C code. Somewhere in the code that is compiled when Octave is built, there is a C function that computes .^ for a double and an array of doubles – that's what you're really timing here, and it's fast because it's written in C. Julia's .^ operator, on the other hand, is written in Julia:

julia> a = 0.9999;

julia> @which a.^(1:10000)
.^(x::Number,r::Ranges{T}) at range.jl:327

该定义包含以下内容:

.^(x::Number, r::Ranges) = [ x^y for y=r ]

它使用一维数组推导将 x 提升到 r 范围内的每个值 y,并将结果作为向量返回.

It uses a one-dimensional array comprehension to raise x to each value y in the range r, returning the result as a vector.

Edward Garson 非常正确,不应该使用全局变量来实现 Julia 的最佳性能.原因是编译器不能很好地推断全局变量的类型,因为它们可以在执行离开当前范围的任何时候发生变化.离开当前范围听起来并不经常发生,但在 Julia 中,即使是索引到数组或添加两个整数之类的基本操作实际上也是方法调用,因此会离开当前范围.然而,在这个问题的代码中,所有的时间都花在 .^ 函数中,所以 a 是一个全局的事实实际上并不重要:

Edward Garson is quite right that one shouldn't use globals for optimal performance in Julia. The reason is that the compiler can't reason very well about the types of globals because they can change at any point where execution leaves the current scope. Leaving the current scope doesn't sound like it happens that often, but in Julia, even basic things like indexing into an array or adding two integers are actually method calls and thus leave the current scope. In the code in this question, however, all the time is spent inside the .^ function, so the fact that a is a global doesn't actually matter:

julia> @elapsed a.^(1:10000)
0.000809698

julia> let a = 0.9999;
         @elapsed a.^(1:10000)
       end
0.000804208

最终,如果您所做的只是在浮点数组上调用矢量化操作,那么 Octave 就可以了.然而,即使在高级动态语言中,这实际上也不是大部分时间花费的地方.如果你发现自己想用 for 循环遍历数组,用标量算法对每个元素进行操作,你会发现 Octave 在这种事情上相当慢——通常比 C 或 Julia 代码慢数千倍一样的东西.另一方面,在 Julia 中编写 for 循环是一件非常合理的事情——事实上,我们所有的排序代码都是用 Julia 编写的,并且在性能上与 C 相当.还有许多其他与性能无关的原因使用 Julia.作为 Matlab 的克隆,Octave 继承了 Matlab 的许多设计问题,并且作为通用编程语言表现不佳.例如,您不会想用 Octave 或 Matlab 编写 Web 服务,但它是 在 Julia 中非常容易.

Ultimately, if all you're ever doing is calling vectorized operations on floating point arrays, Octave is just fine. However, this is often not actually where most of the time is spent even in high-level dynamic languages. If you ever find yourself wanting to iterate over an array with a for loop, operating on each element with scalar arithmetic, you'll find that Octave is quite slow at that sort of thing – often thousands of times slower than C or Julia code doing the same thing. Writing for loops in Julia, on the other hand, is a perfectly reasonable thing to do – in fact, all our sorting code is written in Julia and is comparable to C in performance. There are also many other reasons to use Julia that don't have to do with performance. As a Matlab clone, Octave inherits many of Matlab's design problems, and doesn't fare very well as a general purpose programming language. You wouldn't, for example, want to write a web service in Octave or Matlab, but it's quite easy to do so in Julia.

这篇关于Julia 语言真的像它声称的那样快吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆