-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Closed
Closed
Copy link
Description
Here are two almost-identical functions:
function getindex1!(dest::AbstractArray, src::AbstractArray, I::Union{Real, AbstractArray}...)
@inbounds for (i, j) in zip(eachindex(dest), Iterators.product(I...))
dest[i] = src[j...]
end
return dest
endfunction getindex2!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray}, N}) where N
@inbounds for (i, j) in zip(eachindex(dest), Iterators.product(I...))
dest[i] = src[j...]
end
return dest
endAnd now a benchmark:
julia> a = zeros(300, 300); b = rand(500, 500);
julia> @benchmark getindex1!($a, $b, 201:500, 201:500)
BenchmarkTools.Trial:
memory estimate: 20.59 MiB
allocs estimate: 629500
--------------
minimum time: 17.831 ms (0.00% GC)
median time: 20.793 ms (0.00% GC)
mean time: 20.941 ms (5.62% GC)
maximum time: 31.831 ms (8.14% GC)
--------------
samples: 239
evals/sample: 1
julia> @benchmark getindex2!($a, $b, 201:500, 201:500)
BenchmarkTools.Trial:
memory estimate: 352 bytes
allocs estimate: 6
--------------
minimum time: 77.827 μs (0.00% GC)
median time: 77.973 μs (0.00% GC)
mean time: 87.117 μs (0.00% GC)
maximum time: 514.022 μs (0.00% GC)
--------------
samples: 10000
evals/sample: 1
The code_lowered and code_typed are identical.
For a function containing a call to this function, the code_typed is different:
julia> foo1(a, b) = getindex1!(a, b, 201:500, 201:500)
foo1 (generic function with 1 method)
julia> foo2(a, b) = getindex2!(a, b, 201:500, 201:500)
foo2 (generic function with 1 method)
julia> @code_typed foo1(a, b)
CodeInfo(
1 ─ %1 = invoke Main.getindex1!(_2::Array{Float64,2}, _3::Array{Float64,2}, $(QuoteNode(201:500))::UnitRange{Int64}, $(QuoteNode(201:500))::Vararg{UnitRange{Int64},N} where N)::Array{Float64,2}
└── return %1
) => Array{Float64,2}
julia> @code_typed foo2(a, b)
CodeInfo(
1 ─ %1 = invoke Main.getindex2!(_2::Array{Float64,2}, _3::Array{Float64,2}, $(QuoteNode(201:500))::UnitRange{Int64}, $(QuoteNode(201:500))::UnitRange{Int64})::Array{Float64,2}
└── return %1
) => Array{Float64,2}
The reason for this difference in performance/compilation is not clear. The function signatures describe identical methods. If you define both as methods for the same function, there is still only one method in the function. I think this is a bug?
nickrobinson251, atthom, blegat and rschwarz
Metadata
Metadata
Assignees
Labels
No labels