Is the Julia language really as fast as it claims?

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

That definition consists of this:

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

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 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

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.

Leave a Comment