function - Julia 函数中的内存分配

标签 function memory julia

这是 Julia 0.5 中的一个简单函数。

function foo{T<:AbstractFloat}(x::T)
  a = zero(T)
  b = zero(T)
  return x
end

我从julia --track-allocation=user开始。然后include("test.jl")。 test.jl只有这个功能。运行foo(5.)。然后是Profile.clear_malloc_data()。再次在 REPL 中 foo(5.) 。离开 Julia 。查看文件 test.jl.mem。

        - function foo{T<:AbstractFloat}(x::T)
        -   a = zero(T)
   194973   b = zero(T)
        0   return x
        - end
        - 

为什么这里分配了194973字节的内存?这也不是函数的第一行。尽管在 Profile.clear_malloc_data() 之后,这应该不重要。

最佳答案

让我们澄清相关documentation的一些部分,这可能有点误导:

In interpreting the results, there are a few important details. Under the user setting, the first line of any function directly called from the REPL will exhibit allocation due to events that happen in the REPL code itself.

事实上,分配的行不是第一行。然而,它仍然是第一条跟踪行,因为 Julia 0.5 在跟踪实际第一条语句的分配方面存在一些问题(在 v0.6 上为 fixed)。请注意,它也可能(与文档所述相反)传播到函数中,即使它们使用 @noinline 进行注释。唯一真正的解决方案是确保所调用的第一个语句是您不想测量的内容。

More significantly, JIT-compilation also adds to allocation counts, because much of Julia’s compiler is written in Julia (and compilation usually requires memory allocation). The recommended procedure is to force compilation by executing all the commands you want to analyze, then call Profile.clear_malloc_data() to reset all allocation counters. Finally, execute the desired commands and quit Julia to trigger the generation of the .mem files.

您是对的,Profile.clear_malloc_data() 会阻止对 JIT 编译的分配进行计数。然而,本段与第一段是分开的;由于“REPL 代码本身发生的事件”,clear_malloc_data 不会对分配执行任何操作。

确实,正如我确定您所怀疑的那样,此函数中没有分配:

julia> function foo{T<:AbstractFloat}(x::T)
         a = zero(T)
         b = zero(T)
         return x
       end
foo (generic function with 1 method)

julia> @allocated foo(5.)
0

您看到的数字是由于 REPL 本身的事件造成的。为了避免此问题,请将要测量的代码包装在函数中。也就是说,我们可以使用它作为我们的测试工具,也许在使用 @noinline 禁用 foo 上的内联之后。例如,这是修改后的 test.jl:

@noinline function foo{T<:AbstractFloat}(x::T)
    a = zero(T)
    b = zero(T)
    return x
end

function do_measurements()
    x = 0.  # dummy statement
    x += foo(5.)
    x       # prevent foo call being optimized out
            # (it won't, but this is good practice)
end

然后是 REPL session :

julia> include("test.jl")
do_measurements (generic function with 1 method)

julia> do_measurements()
5.0

julia> Profile.clear_malloc_data()

julia> do_measurements()
5.0

这会产生预期的结果:

        - @noinline function foo{T<:AbstractFloat}(x::T)
        0     a = zero(T)
        0     b = zero(T)
        0     return x
        - end
        -
        - function do_measurements()
   155351     x = 0.  # dummy statement
        0     x += foo(5.)
        0     x       # prevent foo call being optimized out
        -             # (it won't, but this is good practice)
        - end
        -

关于function - Julia 函数中的内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39811011/

相关文章:

matlab - 检查 Matlab 函数的输入参数是否存在

android - SQLite 数据库或 XML string[] 哪个内存效率更高?

c - C 中不使用下取整函数将 float 向下舍入为整数值

C 递归 - 将数字的每个数字加 1,除了数字 9 为 0

C++ 传递临时堆栈对象作为对函数的引用

python进程每天都在增加内存使用量

memory - gdb & 找出内存地址何时被写入

arrays - 使用嵌套填充创建二维字符串数组

string - Julia - 在文件中打印或写入字符串中的反斜杠

parallel-processing - 如何在 Julia 中到处定义宏?