Mapslices() warntype?

I’m wondered seeing that mapslices() gives warntype as below:

julia> const mat = randn(3,2)
3×2 Array{Float64,2}:
  1.49498   -1.98461  
 -0.935659  -0.0317199
  0.783414  -0.284129 

julia> mapslices(prod, mat, dims = 1)
1×2 Array{Float64,2}:
 -1.09583  -0.0178864

julia> @code_warntype mapslices(prod, mat, dims = 1)
Body::Any
...
5 ┄ %16 = Base.:(var"#mapslices#109")(dims, @_3, f, A)::Any
└──       return %16

is there any way to avoid the warntype? thanks.

Mapslices can’t be inferred, because Julia has no way of telling what prod applied to a slice mat looks like without trying. Therefore mapslices first figures that out by calling prod on the first slice and then it calls an inner function which then is “typestable”. [source]

See keyword “function barrier” in the [performance tips]. Therefore you do not need to worry much about that warning, are you calling mapslices in highly performance relevant code or inner loops?

1 Like

mapslices just doesn’t behave very well, IMO, and you are much better off building the same thing from other pieces. These are fine:

@code_warntype map(prod, eachcol(mat))
@code_warntype map(prod, eachslice(mat, dims=2)) # same, with keyword

although of course you can write prod(mat, dims=1), but I guess it’s an example. If your function returns arrays, you want something like this:

f(x) = vcat(x, x .^ 2)
mapslices(f, mat, dims=1) == reduce(hcat, map(f, eachcol(mat))) # true
@code_warntype mapslices(f, mat, dims=1)          # Any
@code_warntype reduce(hcat, map(f, eachcol(mat))) # Array{Float64,2}
2 Likes

yes, using in performance sensitive inner loop… so, even with the function barrier inner_mapslices!(), seems like mapslices() is still very slow compared to map( , eachcol() ) as suggested by @mcabbott:

julia> @btime prod($mat, dims = $1);
  57.745 ns (1 allocation: 96 bytes)

julia> @btime map($prod, eachcol($mat));
  76.787 ns (6 allocations: 256 bytes)

julia> @btime map($prod, eachslice($mat, dims = $2));
  585.473 ns (7 allocations: 272 bytes)

julia> @btime mapslices($prod, $mat, dims = $1);
  4.639 μs (54 allocations: 2.56 KiB)

it’s interesting to see that map( , eachslice()) is that much slower than map(, eachcol() ) !

another thing to note is the confusion of dims: 1 is used in prod() and mapslices() but 2 should be used in eachslice() !!!

Yes, see e.g. https://github.com/JuliaLang/julia/issues/34840, https://github.com/JuliaLang/julia/issues/29146, and maybe https://discourse.julialang.org/t/ann-lazystack-slicemap-starslice .

1 Like