内存不会在多个线程中释放

时间:2018-09-18 07:08:12

标签: garbage-collection julia

我一直在使用Julia对大量数据进行多线程处理,并观察到一种交错模式。内存使用量(由htop报告)缓慢增长,直到该进程被OS终止。该项目很复杂,很难产生合适的MWE,但是我进行了一个简单的实验:

using Base.Threads
f(n) = Threads.@threads for i=1:n
    x = zeros(n)
end

现在,我反复调用f(n)以获得n的各种值(在我的64 Gb计算机上介于10 ^ 4和10 ^ 5之间)。结果是,有时一切都按预期工作,并且返回后释放内存,但是有时情况并非如此,htop报告的已用内存量即使看起来似乎没有进行任何计算,也都挂在一个很大的值上:

enter image description here

显式垃圾回收GC.gc()只能帮助一点点,释放一些内存,但是只有一小块。同样,有时在函数GC.gc()中的循环中调用f会有所帮助,但是问题仍然存在,并且当然会降低性能。退出Julia后,分配的内存恢复正常(可能已由OS释放)。

我已经阅读了朱莉娅如何管理其记忆以及仅在记忆计数大于某个值时才释放记忆。但就我而言,它导致进程被操作系统杀死。在我看来,GC某种程度上丢失了所有分配的内存的记录

有人可以解释这种行为以及如何通过重复调用GC.gc()来防止这种行为而又不会减慢代码的速度吗?为什么用这种方式破坏垃圾收集?

更多详细信息:

  • 仅当在多个线程中处理大数据(分配大量内存)时才会发生这种情况。我只用一个线程就无法复制相同的东西。
  • 我检查了代码,了解我所知道的所有可能增加内存消耗(全局变量,类型稳定性等)的事情,但没有得到积极的结果。据我所知,这些问题会导致更高的内存分配,但我的问题是,从函数返回后内存不会释放
  • 这是我的versioninfo输出:

    julia> versioninfo()
    Julia Version 0.7.0
    Commit a4cb80f3ed (2018-08-08 06:46 UTC)
    Platform Info:
      OS: Linux (x86_64-pc-linux-gnu)
      CPU: Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz
      WORD_SIZE: 64
      LIBM: libopenlibm
      LLVM: libLLVM-6.0.0 (ORCJIT, skylake)
    Environment:
      JULIA_NUM_THREADS = 36
    

1 个答案:

答案 0 :(得分:0)

自从很久以前就有人问过这个问题,希望这不再发生——尽管我无法在没有 MWE 的情况下进行测试。

然而,值得注意的一点是 Julia 垃圾收集器是单线程的;即,无论您有多少线程生成垃圾,都只有一个垃圾收集器。

因此,如果您要在并行工作流中生成大量垃圾,通常建议使用多处理(即 MPI.jl 或 Distributed.jl)而不是多线程。在多处理中,与多线程相比,每个进程都有自己的 GC。