Performance of variants of findall

Here is a small session:

julia> using BenchmarkTools

julia> A = rand(100, 100)
100×100 Array{Float64,2}  [...]

julia> @btime findall(A .> 0.5)
  39.951 μs (7 allocations: 85.06 KiB)
5077-element Array{CartesianIndex{2},1}  [...]

julia> @btime findall(x -> x > 0.5, A)
  208.314 μs (17 allocations: 256.80 KiB)
5077-element Array{CartesianIndex{2},1} [...]

Why these timing differences between evaluations of two expressions that look so close and sensible ?

They are not the same (you can explore this with @edit, or the debugger). The first creates a temporary array for A .> 0, and then collects the true indexes. Both of these operations are very fast.

The second one goes through the generic iterator path. Perhaps it could optimized more, I am sure PRs doing this would be welcome.

Thanks for your answer. Perhaps some warning in the documentation (https://docs.julialang.org/en/v1/base/arrays/#Base.findall-Tuple{Function,Any}), about the case where the second argument is an array, would be useful.

Try to see if there is any effect of interpolating A into the expression with $

I don’t think there is an inherent reason for the performance difference here (which would of course warrant documentation), it is just waiting for someone to optimize it.

See also the similar topic Comprehension vs map and filter unexpected speeds

1 Like