performance - Julia - CartesianIndices 的性能

标签 performance julia benchmarking

我正在研究 Base.IteratorsMD 的源代码,我确信 CartesianIndexBase.nextind 的实现(在 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

我假设在每次调用中创建 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)

Base.nextindmynextind 快几个数量级(7 微秒对 12 毫秒)。此外,Base.nextind 似乎没有进行任何内存分配。现在我试图理解为什么会这样。 CartesianIndices 是否真的创建了所有索引?

最佳答案

I assumed that creating a new instance of CartesianIndices(...) in every call must be very expensive, since on my machine a call to CartesianIndices(...) via REPL seems to create all indices.

这是无效的。

当您在 REPL 中打印 CartesianIndices(...) 时,将打印所有元素。但这并不意味着它将创建所有索引。

正如您在此处的 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

关于performance - Julia - CartesianIndices 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58001957/

相关文章:

java - 为什么这个内部循环第一次迭代通过外部循环快 4 倍?

julia - 定义了自定义 `show` 时显示复合类型的默认打印

arrays - reshape 广播表达

julia - 在 Julia 中以特定格式解压二进制数据

c++ - SPEC CPU 基准测试中各种浮点运算的百分比

performance - 当数组大于 800,000,000 时,我的 Fortran 筛选会显着减慢

c# - 性能/风格 : Changing an object by reference vs returning a copy in C#

python - 在 numba nopython 函数中计算阶乘的最快方法

python - 为什么在 C++ 中从 stdin 读取行比 Python 慢得多?

c++ - 为什么 C++ 初始分配比 C 大得多?