unt*_*gam 3 performance benchmarking julia
我正在挖掘源代码,Base.IteratorsMD我确信Base.nextindfor CartesianIndex(in julia/base/multidimensional.jl,请参见此处https://github.com/JuliaLang/julia/blob/55e36cc308b66d3472990a06b2797f9f9154ea0a/base/multidimensional.jl#L142-L150 ) 的实现效率极低:
function Base.nextind(a::AbstractArray{<:Any,N}, i::CartesianIndex{N}) where {N}
iter = CartesianIndices(axes(a))
return CartesianIndex(inc(i.I, first(iter).I, last(iter).I))
end
Run Code Online (Sandbox Code Playgroud)
我认为CartesianIndices(...)在每次调用中创建一个新实例必须非常昂贵,因为在我的机器上CartesianIndices(...)通过 REPL调用似乎创建了所有索引。因此,我为替代实现编写了以下基准脚本mynextind:
using Base.IteratorsMD
function mynextind(a::AbstractArray{<:Any,N}, i::CartesianIndex{N}) where {N}
dims = (x.stop for x in axes(a))
return CartesianIndex(Base.IteratorsMD.inc(i.I, CartesianIndex(ones(Int64, length(dims))...).I, CartesianIndex(dims...).I))
end
function f(func, M)
c = CartesianIndex(1,1)
while true
(c = func(M, c)) == CartesianIndex(size(M)...) && break
end
end
A = rand(100,100)
@btime f(Base.nextind, A)
@btime f(mynextind, A)
Run Code Online (Sandbox Code Playgroud)
Base.nextind比 快几个数量级(7?s vs 12ms)mynextind。此外,Base.nextind似乎没有进行任何内存分配。现在我试图理解为什么会这样。CartesianIndices实际上是否创建了所有索引?
我认为在每次调用中创建 CartesianIndices(...) 的新实例必须非常昂贵,因为在我的机器上通过 REPL 调用 CartesianIndices(...) 似乎创建了所有索引。
这是无效的。
CartesianIndices(...)在 REPL 中打印时,将打印所有元素。但这并不意味着它将创建所有索引。
正如您在CartesianIndices此处结构的源代码中所见:https :
//github.com/JuliaLang/julia/blob/64d8ca49122609d1c10c72a96d1711b95346980a/base/multidimensional.jl#L248
当您创建类似 的实例时CartesianIndices(axes(A)),只会存储轴。您看到所有索引都被打印的原因CartesianIndices是AbstractArray. 它也实现了这些getindex方法。因此,当您键入 时CartesianIndices(axes(A)),所有索引都是按需计算的。
您可以在此处查看有关 CartesianIndices 的更多讨论:https : //discourse.julialang.org/t/psa-replacement-of-ind2sub-sub2ind-in-julia-0-7/14666