-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Description
A common "trick" to deal with heterogeneous data that is looped over is to introduce a function barrier that acts as an "inference point" so that dynamic dispatch is only done once per element. When working on the element, the type is known and if the work is significant enough, the cost of dynamic dispatch is negligible. While this usually works well, it is pretty annoying to have to split out the new function, pass all the arguments to the new function etc. Therefore, I wonder if it is possible to introduce a syntax / feature whereby you could achieve this "outlining" without having to manually do it. The result should be the equivalent of moving the body of, for example a for loop, into it's own function.
The code below shows three different implementation of summing over elements of an array that contain 3 vectors with different element types.
function f1(vs)
z = 0.0
for v in vs
for x in v
z += x
end
end
return z
end
function f2(vs)
z = 0.0
for v in vs
(v -> begin
for x in v
z += x
end
end)(v)
end
return z
end
function f3(vs)
z = 0.0
for v in vs
z += _f3(v)
end
return z
end
function _f3(v)
_z = 0.0
for x in v
_z += x
end
return _z
end
using BenchmarkTools
vs = Any[rand(10^5), rand(Int, 10^5), rand(Float32, 10^5)];
@btime f1(vs);
@btime f2(vs);
@btime f3(vs);with the result:
julia> @btime f1(vs);
53.785 ms (1198470 allocations: 22.86 MiB)
julia> @btime f2(vs);
10.569 ms (600004 allocations: 9.16 MiB)
julia> @btime f3(vs);
254.428 μs (6 allocations: 96 bytes)Using a closure seems faster than the normal loop but is clearly much slower than explicitly outlined version.
I realize this possible ties closely into closure lowering so if this is considered a dup of #15276, please close.