[英]Memory leaks in Jpype with multiprocessing
我有一个 python 代码,它通过 jpype 使用 java 库。 目前,我的 function 的每次运行都会检查 JVM 是否存在,如果不存在则创建它
import jpype as jp
def myfunc(i):
if not jp.isJVMStarted():
jp.startJVM(jp.getDefaultJVMPath(), '-ea', ('-Djava.class.path=' + jar_location))
do_something_hard(i)
此外,我想使用 python 多处理库并行化我的代码。 每个线程(据说)独立工作,用不同的参数计算我的 function 的值。 例如
import pathos
pool = pathos.multiprocessing.ProcessingPool(8)
params = np.arange(100)
result = pool.map(myfunc, params)
这种结构工作正常,但在池中使用超过 1 个核心时,它会出现严重的 memory 泄漏。 我注意到,当 python 关闭时,所有 memory 都已释放,但 memory 仍会随着时间的推移而累积,而pool.map
。 jpype 文档非常简短,建议通过使用jp.attachThreadToJVM
和jp.detachThreadToJVM
包装 python 线程来同步线程。 但是,我无法在网上找到一个关于如何实际操作的示例。 我尝试使用这些语句将 function do_something_hard
包装在myfunc
中,但它对泄漏没有影响。 我还尝试使用 jp.shutdownJVM 在myfunc
末尾显式关闭jp.shutdownJVM
。 但是,在这种情况下,JVM 似乎在我拥有超过 1 个内核时立即崩溃,这让我相信存在竞争条件。
请帮忙:
问题在于多处理的性质。 Python 可以分叉或生成一个新进程。 对于 JVM,fork 选项似乎存在重大问题。 linux 上的默认值为 fork。
使用生成上下文 (multiprocessing.get_context("spawn")) 创建 Python 的生成版本将允许创建新的 JVM。 每个生成的副本都是完全独立的。 在 github 上的测试目录中的 subrun.py 中有示例,因为它用于测试 JPype 的不同 JVM 选项。
fork 版本创建原始进程的副本,包括先前运行的 JVM。 至少从我的测试来看,分叉的 JVM 没有按预期工作。 较早版本的 JPype (0.6.x) 将允许分叉版本调用 startJVM,这会造成大的 memory 泄漏。 当前版本 0.7.1 给出了 JVM 无法重新启动的例外情况。
如果您使用线程(而不是进程),则所有线程共享相同的 JVM,并且不需要单独使用 JVM。 在 github 的“限制”部分下的最新文档中,有更多关于使用 JPype 进行多处理的文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.