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

Šim*_*lík 8 garbage-collection julia

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

using Base.Threads
f(n) = Threads.@threads for i=1:n
    x = zeros(n)
end
Run Code Online (Sandbox Code Playgroud)

现在,我f(n)反复调用n的各种值(在我的64 Gb机器上大约10 ^ 4到10 ^ 5之间).结果是,有时一切都按预期工作,内存在返回后被释放,但有时情况并非如此,并且htop即使看起来没有进行计算,也会挂起大量值的已用内存量:

在此输入图像描述

显式垃圾收集GC.gc()只能帮助一点,一些内存被释放,但只有一小块.此外,GC.gc()有时在函数循环中调用有f帮助,但问题仍然存在,当然,性能会降低.退出Julia后,分配的内存恢复正常(可能由操作系统释放).

我已经读过julia如何管理它的内存以及只有当内存计数大于某个值时才释放内存.但就我而言,它会导致进程被操作系统杀死.在我看来,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
    
    Run Code Online (Sandbox Code Playgroud)

cbk*_*cbk 1

由于很久以前就有人问过这个问题,希望这种情况不再发生——尽管如果没有 MWE,我无法进行测试来确定。

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

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