当前位置:  开发笔记 > 编程语言 > 正文

快速索引数组

如何解决《快速索引数组》经验,为你挑选了2个好方法。

访问(也许替换)大型多维数组中的条目的最有效方法是什么?我在循环中使用这样的东西:

tup = (16,45,6,40,3)
A[tup...] = 100

但我想知道是否有更有效的方法.特别是,有什么方法可以避免使用...



1> David P. San..:

要迭代多维数组,建议这样做for index in eachindex(A); 见例如

https://groups.google.com/forum/#!msg/julia-users/CF_Iphgt2Wo/V-b31-6oxSkJ

如果A是标准数组,那么这对应于使用单个整数进行索引,这是访问数组的最快方式(原始问题):

A = rand(3, 3)

for i in eachindex(A)
   println(i)
end

但是,如果A是一个更复杂的对象,例如子阵列,那么eachindex(A)将为您提供一个不同的,高效的访问对象:

julia> for i in eachindex(slice(A, 1:3, 2:3))
           println(i)
       end

CartesianIndex{2}((1,1))
CartesianIndex{2}((2,1))

等等



2> Matt B...:

splatting并不总是会受到惩罚,但确定它的效率并不总是显而易见(或容易).你的琐碎例子实际上和写作一样有效A[16,45,6,40,3] = 100.你可以通过比较看到这一点

   function f(A)
       tup = (16,45,6,40,3)
       A[tup...] = 100
       A
   end
   function g(A)
       A[16,45,6,40,3] = 100
       A
   end
julia> code_llvm(f, Tuple{Array{Int, 5}})
# Lots of output (bounds checks).
julia> code_llvm(g, Tuple{Array{Int, 5}})
# Identical to above

如果有一个泼溅惩罚,你会以分配的形式看到它.您可以使用@allocated宏来测试这个,或者只是检查code_llvm一个引用@jl_pgcstack- 这就是垃圾收集器,这在任何时候都需要分配.请注意,在更复杂的函数中很可能还会导致分配,因此它的存在并不一定意味着存在splatting悲观化.但如果这是一个热循环,你想最小化所有分配,所以它是一个伟大的目标......即使你的问题不是由于splatting.您也应该使用@code_warntype,因为类型不好的代码肯定会使splats和许多其他操作失望.如果您的元组输入不好,将会发生以下情况:

   function h(A)
       tup = ntuple(x->x+1, 5) # type inference doesn't know the type or size of this tuple
       A[tup...] = 100
       A
   end
julia> code_warntype(h, Tuple{Array{Int,5}})
# Lots of red flags

所以优化这个splat将高度依赖于你如何构建或获得tup.

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有