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

时间:2016-01-13 03:00:35

标签: arrays multidimensional-array julia jagged-arrays ragged

为了激发我的问题,请考虑在Julia中处理元素类型Int的{​​{3}}(为简单起见)时的情况。有两种方法可以存储它们:

  1. 作为Vector{Vector{Int}}
  2. 作为Vector{Union{Vector{Int}, Int}}(特别是,如果想要存储足够多的1元素向量)
  3. 我的问题是哪一个更有效/更快/更好?

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

    1. 我假设Vector{Vector{Int}}类型的变量被认为是同类型数组,因此我希望它在内存中连续存储,因此更加cpu-cache友好。我对吗?或者连续性仅适用于其元素为'数据类型是原始的吗?

    2. 类型Vector{Union{Vector{Int}, Int}}的变量是否会考虑异构数组,并且在内存中存储 连续

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

1 个答案:

答案 0 :(得分:7)

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

julia> Array(Int, 3)
3-element Array{Int64,1}:
 4430901168
 4470602000
 4430901232

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

julia> Array(Vector{Int}, 3)
3-element Array{Array{Int64,1},1}:
 #undef
 #undef
 #undef

想象一下,如果后者返回一个连续的Int块,会发生什么。怎么知道它有多大?或者一个矢量停止而下一个矢量开始?这将取决于矢量的大小,这还不为人所知。

Vector{Union{Vector{Int}, Int}}同样会将其元素存储为指针;这次是因为Julia不知道如何解释内联的每个元素(它应该像整数一样读取内存还是像数组一样?)。它还有一个缺点,就是朱莉娅不再知道它会从索引中返回什么类型。这是一种类型不稳定性,并且对于性能而言肯定会比使用单元素向量更差

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