julia,为什么函数内部的循环会发生内存分配?

时间:2016-09-24 20:08:08

标签: performance memory-management julia

julia --track-allocation=user的内存分配报告中,分配的最大值在此函数中:

        - function fuzzy_dot_square( v::Array{Int64, 1} )
        -     dot_prod = zero(Int64)
7063056168     for i::Int64 in 2:28
        0         dot_prod += v[i]*(v[i] + v[i-1] + v[i+1] + v[i+28])# / 4 # no "top" pixel
        -     end
        0     for i in 29:(28*27) # compiler should literate 28*27
        0         dot_prod += v[i]*(v[i] + v[i-1] + v[i+1] + v[i-28] + v[i+28])# / 5 # all pixels
        -     end
        0     for i in (28*27):(28*28 - 1)
        0         dot_prod += v[i]*(v[i] + v[i-1] + v[i+1] + v[i-28])# / 4 # no "bottom" pixel
        -     end
        -
        0     return dot_prod
        - end

- 它是一个"模糊点产品"矢量的平方,表示28乘28的像素图像(数字图像的已知MNIST数据集)。

为什么分配会在那里发生? 据我所知,dot_prod是唯一要分配的东西。 但该报告首先指出......

我还尝试用repl复制它:

v = Array{Int64,1}(1:100)
dot_prod = zero(Int64)
@allocated for i in 2:28
    dot_prod += v[i]
end

- 我在@allocated for ...发现了以下错误:

ERROR: UndefVarError: dot_prod not defined
 in macro expansion at ./REPL[3]:2 [inlined]
 in (::##1#f#1)() at ./util.jl:256

@time宏工作正常,可能@allocated中有一些错误?我有julia 0.5.0

1 个答案:

答案 0 :(得分:8)

这是--track-allocation=user的限制。没有类型不稳定,也没有分配。

julia> function fuzzy_dot_square(v)
           dot_prod = zero(eltype(v))
           for i in 2:28
               dot_prod += v[i]*(v[i] + v[i-1] + v[i+1] + v[i+28])# / 4 # no "top" pixel
           end
           for i in 29:(28*27) # compiler should literate 28*27
               dot_prod += v[i]*(v[i] + v[i-1] + v[i+1] + v[i-28] + v[i+28])# / 5 # all pixels
           end
           for i in (28*27):(28*28 - 1)
               dot_prod += v[i]*(v[i] + v[i-1] + v[i+1] + v[i-28])# / 4 # no "bottom" pixel
           end
           return dot_prod
       end
fuzzy_dot_square (generic function with 1 method)

julia> const xs = [1:28^2;];

julia> @allocated fuzzy_dot_square(xs)
0

另见朱莉娅documentation的这段话:

  

在解释结果时,有一些重要的细节。在用户设置下,由REPL代码本身发生的事件,直接从REPL调用的任何函数的第一行将显示分配。更重要的是,JIT编译还增加了分配计数,因为Julia的编译器大部分是用Julia编写的(并且编译通常需要内存分配)。建议的过程是通过执行要分析的所有命令强制编译,然后调用Profile.clear_malloc_data()来重置所有分配计数器。最后,执行所需的命令并退出Julia以触发生成.mem文件。

有关详细信息,请参阅this Julia issue