Julia: mapslices performance

Created on 20 Apr 2018  Â·  4Comments  Â·  Source: JuliaLang/julia

Consider the following piece of code:

n=10^6;
X = randn(1,n);
V(x) = 0.5 * dot(x,x);
f(V, X) = [ V((@view X[:,n])) for n = 1:size(X,2) ]

Timing on this reveals:

julia> @time mapslices(V, X, 1);
  1.177690 seconds (12.00 M allocations: 267.024 MiB, 6.91% gc time)
julia> @time f(V,X);
  0.047745 seconds (1.00 M allocations: 53.406 MiB, 5.58% gc time)

which is substantially different.

Note that in this simple example, my data could be a column vector; however, this is a surrogate for problems where I have time series data and X is d x n with 1< d << n.

arrays performance

Most helpful comment

Updated timings on latest nightly:

julia> @btime mapslices($V, $X, dims=1);
  377.917 ms (10998504 allocations: 251.75 MiB)

julia> @btime f($V,$X);
  14.712 ms (2 allocations: 7.63 MiB)

julia> @btime map(V, Slices($X, 1));
  14.832 ms (6 allocations: 7.63 MiB)

mapslices is still struggling, but eachslice has improved ~5x since v1.5.2, and is now tied with hand-written & julienned versions:

julia> @btime map(V, eachslice($X, dims=2));
  76.877 ms (4000009 allocations: 129.70 MiB) # v1.5.2
julia> @btime map(V, eachslice($X, dims=2));
  14.937 ms (7 allocations: 7.63 MiB) # v1.6.0-DEV.1208

All 4 comments

Better on 0.7, but not parity:

julia> @time mapslices(V, X, 1);
  0.202644 seconds (5.00 M allocations: 114.428 MiB, 5.10% gc time)

julia> @time f(V,X);
  0.032617 seconds (1.00 M allocations: 53.406 MiB, 16.69% gc time)

Edit:

Both idx and ridx at:

https://github.com/JuliaLang/julia/blob/8f46450f61c27de38e26f13c5fe20c2a4b2e6108/base/abstractarray.jl#L1940-L1958

are Vector{Any} and seems to be used in quite tight loops.

JuliennedArrays might help in this case:

julia> @benchmark mapslices(V, X, 1)
BenchmarkTools.Trial: 
  memory estimate:  267.02 MiB
  allocs estimate:  11999527
  --------------
  minimum time:     750.878 ms (2.31% GC)
  median time:      782.824 ms (2.33% GC)
  mean time:        803.105 ms (3.38% GC)
  maximum time:     905.073 ms (2.32% GC)
  --------------
  samples:          7
  evals/sample:     1

julia> @benchmark f(V, X)
BenchmarkTools.Trial: 
  memory estimate:  53.41 MiB
  allocs estimate:  1000006
  --------------
  minimum time:     23.018 ms (5.64% GC)
  median time:      25.374 ms (5.97% GC)
  mean time:        37.715 ms (32.41% GC)
  maximum time:     101.140 ms (67.24% GC)
  --------------
  samples:          133
  evals/sample:     1

julia> using JuliennedArrays
julia> @benchmark map(V, julienne(X, (:,*)))
BenchmarkTools.Trial: 
  memory estimate:  53.41 MiB
  allocs estimate:  1000006
  --------------
  minimum time:     26.012 ms (5.17% GC)
  median time:      28.425 ms (5.71% GC)
  mean time:        41.413 ms (30.04% GC)
  maximum time:     109.614 ms (65.14% GC)
  --------------
  samples:          121
  evals/sample:     1

There are plans to migrate it into Base: https://github.com/JuliaLang/julia/issues/23645#issuecomment-328265939

Updated timings on latest nightly:

julia> @btime mapslices($V, $X, dims=1);
  377.917 ms (10998504 allocations: 251.75 MiB)

julia> @btime f($V,$X);
  14.712 ms (2 allocations: 7.63 MiB)

julia> @btime map(V, Slices($X, 1));
  14.832 ms (6 allocations: 7.63 MiB)

mapslices is still struggling, but eachslice has improved ~5x since v1.5.2, and is now tied with hand-written & julienned versions:

julia> @btime map(V, eachslice($X, dims=2));
  76.877 ms (4000009 allocations: 129.70 MiB) # v1.5.2
julia> @btime map(V, eachslice($X, dims=2));
  14.937 ms (7 allocations: 7.63 MiB) # v1.6.0-DEV.1208

...and just for fun,

using LoopVectorization, Tullio
g(X) = @tullio y[j] := 0.5*X[i, j]^2
julia> @btime g($X)
  754.101 μs (172 allocations: 7.64 MiB)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

StefanKarpinski picture StefanKarpinski  Â·  3Comments

StefanKarpinski picture StefanKarpinski  Â·  3Comments

omus picture omus  Â·  3Comments

omus picture omus  Â·  3Comments

ararslan picture ararslan  Â·  3Comments