加快新型深度复印

时间:2017-05-13 11:41:36

标签: julia

问题:我有一个新类型type MyFloat; x::Float64 ; end。我想在deepcopy上执行Vector{MyFloat}。在Ubuntu 16.04上使用Julia v0.5.0,该操作比等效长度deepcopy上的Vector{Float64}调用慢大约150倍。是否可以加快deepcopy上的Vector{MyFloat}

代码段:使用以下代码片段可以看到150倍减速,该代码段可以粘贴到REPL:

#Just my own floating point type
type MyFloat
    x::Float64
end

#This function performs N deepcopy operations on a Vector{MyFloat} of length J
function f1(J::Int, N::Int)
    v = MyFloat.(rand(J))
    x = [ deepcopy(v) for n = 1:N ]
end

#The same as f1, but on Vector{Float64} instead of Vector{MyFloat}
function f2(J::Int, N::Int)
    v = rand(J)
    x = [ deepcopy(v) for n = 1:N ]
end

#Pre-compilation step
f1(2, 2);
f2(2, 2);

#Timings
@time f1(100, 15000);
@time f2(100, 15000);

在我的机器上产生:

julia> @time f1(100, 15000);
  1.944410 seconds (4.61 M allocations: 167.888 MB, 7.72% gc time)

julia> @time f2(100, 15000);
  0.013513 seconds (45.01 k allocations: 19.113 MB, 78.80% gc time)

查看答案here,我可以通过为copy定义自己的MyFloat方法来加快速度。我尝试过这样的事情:

Base.deepcopy(x::MyFloat)::MyFloat = MyFloat(x.x);
Base.deepcopy(v::Vector{MyFloat})::Vector{MyFloat} = [ MyFloat(y.x) for y in v ]
Base.copy(x::MyFloat)::MyFloat = MyFloat(x.x)
Base.copy(v::Vector{MyFloat})::Vector{MyFloat} = [ MyFloat(y.x) for y in v ]

但这并没有任何区别。

最后注意事项a = MyFloat.([1.0, 2.0]),我可以使用b = copy(a)并且没有速度惩罚。这很好,只要我小心谨慎地执行b[1] = MyFloat(3.0)之类的操作(这将修改b而不是a)。但如果我草率并且不小心写了b[1].x = 3.0,那么这将修改ab

顺便说一句,完全有可能我对copydeepcopy之间的差异没有深刻的理解......我已经阅读了this很棒的博文(谢谢@ChrisRackauckas),但我对更深层次的情况肯定有点模糊。

1 个答案:

答案 0 :(得分:1)

Try changing type MyFloat in the definition to immutable MyFloat or struct MyFloat (the keyword changed in 0.6). This makes the times almost equal.

As @Gnimuc mentioned, a mutable, which is not a bitstype, makes Julia keep track of a lot of other stuff. See here and in the comments.