朱莉娅(Julia)在特定索引处非初始化阵列



我正在撰写朱莉娅(Julia)的神经网络,该神经网络测试随机拓扑。我将所有索引留在一系列没有由节点占用的节点(但可能是未来拓扑的),因为它可以节省内存。当旧拓扑中的节点不再连接到新拓扑中的其他节点时,是否有一种方法可以使节点所属的索引非直接化?另外,有什么原因不这样做吗?

local preSyns = Array(Vector{Int64}, (2,2)) 
println(preSyns)
preSyns[1] = [3]
println(preSyns)

输出

[#undef #undef
#undef #undef]
[[1] #undef
#undef #undef]

如何像第一个打印输出一样使第一个索引不确定?

如果您不相信我,请对记忆问题请看以下

function memtest()
    y = Array(Vector{Int64}, 100000000)
end
function memtestF()
    y = fill!(Array(Vector{Int64}, 100000000),[])
end
@time memtest()
@time memtestF()

输出

elapsed time: 0.468254929 seconds (800029916 bytes allocated)
elapsed time: 30.801266299 seconds (5600291712 bytes allocated, 69.42% gc time)

一个联合国初始化的阵列进行0.8次演出,初始化为5个演出。我的活动监视器还确认了这一点。

未定义的值本质上是空的指针,并且没有一流的方法可以将数组元素"解开"回到空指针。由于您不想为代表未连接的节点的前哨值拥有太多(或任何)开销,因此这变得更加困难。在一个64位系统上,仅指针仅需1亿个元素即可占用〜800MB,而空数阵列的标题元数据占48个字节。因此,如果您将一个独立的空数组分配给每个元素,则最终会以〜5GB的数组标头。

fill!在Julia 0.3中的行为有点薄弱(已在0.4中进行了校正)。如果您没有用[]填充数组,而是用明确键入的Int64[] fill!,则每个元素都将指向相同的空数组。这意味着您的数组及其元素将仅占用48个字节,而不是非初始化的数组。但这也意味着修改一个节点的子阵列(例如,使用push!)将意味着 all nodes将获得该连接。这可能不是您想要的。您仍然可以将空数组用作前哨值,但是您必须非常小心才能不修改它。

如果您的阵列将密集地包装有子阵列,则该数组标题的开销没有直接的方式。具有独立空数组的数组初始化数组的一种更健壮和前向兼容的方法是理解:Vector{Int64}[Int64[] for i=1:2, j=1:2]。这也将在0.3中更具性能,因为它不需要将[]转换为每个元素的Int64[]。如果每个元素可能包含一个非空数组,则在任何情况下都需要支付阵列开销的费用。要从拓扑中删除节点,您只需调用empty!

但是,如果您的节点数组将被稀疏包装,则可以尝试使用不同的数据结构,以更直接地支持未设置元素。根据您的用例,您可以使用默认词典将索引键盘映射到向量(来自dataCtructures.jl;使用函数来确保"默认"是每次新分配和独立的空数阵列),或尝试专用于topologies之类的软件包。

最后,要回答您问的实际问题,是的,有一种骇人听闻的方法可以将数组的元素解散回#undef。这是不受支持的,可能随时破裂:

function unset!{T}(A::Array{T}, I::Int...)
    isbits(T) && error("cannot unset! an element of a bits array")
    P = pointer_to_array(convert(Ptr{Ptr{T}}, pointer(A)), size(A))        
    P[I...] = C_NULL
    return A
end

最新更新