Julia的Vector {Vector {T}}是否连续存储在内存中?

abe*_*ysh 4 arrays jagged-arrays multidimensional-array julia ragged

为了激发我的问题,请考虑在Julia 中处理元素类型的锯齿状数组(为简单起见)时的情况Int.有两种方法可以存储它们:

  1. Vector{Vector{Int}}
  2. As Vector{Union{Vector{Int}, Int}}(特别是,如果想要存储足够多的1元素向量)

我的问题是哪一个更有效/更快/更好?

为了回答这个问题,我需要知道每个内容是如何存储在内存中的.即:

  1. 我假定的类型的变量Vector{Vector{Int}},将被认为是均匀的型阵列,因此,我希望它被存储连续在存储器中,并且这样更CPU缓存友好.我对吗?或者连词只适用于元素数据类型是原始的数组?

  2. 一个类型的变量是否会Vector{Union{Vector{Int}, Int}}被视为异构数组,并且因此在内存中 连续存储?

  3. 如何将内存中连续表示的好处与不具有1-元素数组成员的数组容器的好处进行比较,即将它们存储为原始数据类型(Int在本例中)?哪一个产生更高的效率?

Mat*_* B. 7

T如果isbits(T)为真,Julia的数组将只存储未装箱类型的元素.也就是说,元素必须是不可变的和无指针的.查看元素是否立即存储的简单方法是分配未初始化的数组.未装箱(立即)值的连续数组将有胡言乱语:

julia> Array(Int, 3)
3-element Array{Int64,1}:
 4430901168
 4470602000
 4430901232
Run Code Online (Sandbox Code Playgroud)

而非isbits类型的数组将有#undef指针:

julia> Array(Vector{Int}, 3)
3-element Array{Array{Int64,1},1}:
 #undef
 #undef
 #undef
Run Code Online (Sandbox Code Playgroud)

想象一下如果后者返回一个连续的Ints 块会发生什么.怎么知道它有多大?或者一个矢量停止而下一个矢量开始?这将取决于载体的大小,这是尚不知道的.

A Vector{Union{Vector{Int}, Int}}同样会将其元素存储为指针; 这次是因为Julia不知道如何解释内联的每个元素(它应该读取整数或类似数组的内存吗?).它还有一个缺点,就是Julia不再知道它将从索引中返回什么类型.这是一种类型不稳定性,对于性能来说肯定比使用单元素向量糟糕.

可以创建自己的不规则数组类型来存储其元素内联,但是使它像普通数组一样使用标准库非常棘手,因为它打破了很多关于索引如何工作的假设.你可以看看我最近的尝试:RaggedArrays.jl.您可以看到我如何将它与问题#2中的先前工作进行比较.