Why do I care again? Array operations vs loops.

I use vectorized operations in (NumPy/R/Matlab/...) for speed! I don't need to write loops.

The message in Julia is not that you shouldn't write vectorized code. You can write vectorized code when it is natural, but you don't have to write vectorized code just for the sake of speed. Sometimes it's more natural to write a loop. For example:

  • cumulative operations
  • moving window operations
  • conditional operations on a vector
  • iterative algorithms

And occationally, you might want to write loops for optimization...

Using Array operations


In [0]:
# two 200 x 200 matricies
n = 200
A = rand(n, n)
B = rand(n, n);

In [1]:
f(A, B) = 2A + 3B + 4A.*A


Out[1]:
f (generic function with 1 method)

In [2]:
using TimeIt

In [2]:
@timeit f(A, B);


1000 loops, best of 3: 925.69 µs per loop

This is easy to read, but allocates many temporary arrays.

Explicit loops


In [3]:
function f2(A, B)
    length(A) == length(B) || error("array length mismatch")
    C = similar(A, promote_type(eltype(A),eltype(B)))
    for i=1:length(C)
        @inbounds a = A[i]
        @inbounds C[i] = 2a + 3B[i] + 4a*a
    end
    return C
end


Out[3]:
f2 (generic function with 1 method)

In [4]:
@timeit f2(A, B)


1000 loops, best of 3: 154.49 µs per loop

Pre-allocate output


In [7]:
function f3!(A, B, C)
    length(A) == length(B) == length(C) || error("array length mismatch")
    for i=1:length(C)
        a = A[i]
        C[i] = 2a + 3B[i] + 4a*a
    end
end


Out[7]:
f3! (generic function with 1 method)

In [8]:
C = similar(A, promote_type(eltype(A),eltype(B)))
@timeit f3!(A, B, C)


10000 loops, best of 3: 60.97 µs per loop

In [ ]: