当前位置: 首页 > 知识库问答 >
问题:

Python多处理内存分配过高

邰英毅
2023-03-14

我已经读了一些关于我的问题的帖子(比如这篇文章),但没有一篇能解决这个问题。在我的Flask应用程序中,我使用内置在多处理中的Python(在16个物理核心上)并行下载了32-64个图像,如下所示:

pool = Pool(int(torch.multiprocessing.cpu_count()/2), maxtasksperchild=maxchilds)
download_func = partial(download)
img_dicts = pool.map(download_func, url_dicts)
pool.close()
pool.join()
gc.collect()


def download(url_dict):
try:
    image = io.imread(url_dict["img_url"])
except Exception:
    image = None
gc.collect()

return {"post_id": url_dict["post_id"], "img": image}

下载工作正常,除了内存使用外,速度显著提高。在下载过程中,Python分配了大约100GB的RAM,尽管实际只使用了大约2GB。每个进程分配超过6 gb的RAM,仅用于下载最多4个图像,每个图像的容量为300-700KB。maxchildspertask被设置为3,以避免高内存使用率,但没有带来显著的改进。

我在Windows上运行,Python 3.7,64位

你有同样的经历或者你有什么想法,我该如何修复记忆问题?

共有1个答案

巫马化
2023-03-14

心理调试告诉我,您在主脚本中分配了一些大的东西,但没有用if_name__=='__main__':保护来保护它,例如,您的主脚本如下所示:

# Perform imports (some of which might contain their own definitions of big_stuff)

# Define classes and/or functions

big_stuff = make_big_stuff()

# ... do more things ...

# ... eventually run code that makes Pool ...

而不是:

# Perform cheap imports

# Define classes and/or functions

def main():
    # Perform any imports which might contain definitions of their own big_stuff
    big_stuff = make_big_stuff()

    # ... do more things ...

    # ... eventually run code that makes Pool ...

if __name__ == '__main__':
    main()

当您执行前者时,每个新生成的worker都会在启动时尽职尽责地重新创建big_stuff,试图模拟forking行为,以确保主脚本中的所有全局在父脚本和子脚本中定义相同。正如您所看到的,这导致了爆炸性的内存使用。解决方案是保护以下任何代码的执行:

    null

使用:

if __name__ == '__main__':

guard,所以它只在父进程中运行(workers是在主html" target="_blank">脚本以'__mp_main__'或类似名称运行的情况下启动的,因此它们不会执行这样保护的代码)。这意味着如果需要的话,子进程无法访问的任何内容都必须通过(因此,如果所有进程都需要6 GB的数据,则需要查看共享内存以避免复制),但至少在工作人员根本不需要的情况下,您不会在启动时立即消耗它。

 类似资料:
  • 程序每天使用的内存在增加。有人能搞清楚是怎么回事吗? 当作业超出运行方法的范围时,内存应该是空闲的,对吗?

  • 问题内容: 我写了一个程序,可以总结如下: 实际代码(尤其是)要复杂得多。仅使用将其当作参数的这些值(意味着它不引用) 基本上,它将巨大的数据集加载到内存中并进行处理。输出的写操作委托给一个子进程(它实际上写到多个文件中,这需要很多时间)。因此,每次处理一个数据项时,它都会通过res_queue发送到子流程,然后该子流程根据需要将结果写入文件中。 子流程不需要访问,读取或修改以任何方式加载的数据。

  • 本文向大家介绍python内存动态分配过程详解,包括了python内存动态分配过程详解的使用技巧和注意事项,需要的朋友参考一下 一、前言 大多数编译型语言,变量在使用前必须先声明,其中C语言更加苛刻:变量声明必须位于代码块最开始,且在任何其他语句之前。其他语言,想C++和java,允许“随时随地”声明变量,比如,变量声明可以在代码块的中间,不过仍然必须在变量被使用前声明变量的名字和类型。 在Pyt

  • 本文向大家介绍C++ 内存分配处理函数set_new_handler的使用,包括了C++ 内存分配处理函数set_new_handler的使用的使用技巧和注意事项,需要的朋友参考一下 一、函数的定义 函数在namespace std中有如下定义(C++98与C++11版本不一致): 二、函数介绍 该函数的作用是:当new操作或new[]操作失败时调用参数所指的new_p函数 异常安全: C++98

  • 使用ResNet50预训练的权重我试图构建一个分类器。代码库完全在Keras高级Tensorflow API中实现。完整的代码发布在下面的GitHub链接中。 源代码:使用RestNet50架构进行分类 预训练模型的文件大小为94.7mb。 我加载了预先训练过的文件 并符合模型 在训练数据集中,我有两个文件夹狗和猫,每个文件夹持有近10,000张图像。当我编译脚本时,我得到以下错误 纪元1/1 2