多重处理pool.apply\u异步消耗内存

2024-05-03 12:00:06 发布

您现在位置:Python中文网/ 问答频道 /正文

用例:

  1. 用10台服务器(16核128GB RAM)处理20亿个参数组合
  2. 每台服务器使用pool.apply\u异步()(Python版本3.7)
  3. 使总处理时间尽可能短

问题:

  1. Python耗尽所有内存并抛出错误“RuntimeError:cannotstart new thread”和“OSError:[Errno 12]Cannot allocate memory

我正在考虑将.apply\u async()方法替换为.apply(),但我猜如果将非阻塞模式更改为阻塞模式,将严重影响总处理时间。你知道吗

有没有人能帮我们找到这个场景的最佳解决方案(花费最少的时间)?你知道吗

我的代码:

exec_log = multiprocessing.Manager().list([0, ''])
lock = multiprocessing.Manager().Lock()
cores = multiprocessing.cpu_count()
pool = multiprocessing.Pool(processes=cores)

# Parameters a to j
for a in a_list: # a_list contains 2 elements
    for b in b_list: # b_list contains 2 elements
        for c in c_list: # c_list contains 5 elements
            for d in d_list: # d_list contains 10 elements
                for e in e_list: # e_list contains 10 elements
                    for f in f_list: # f_list contains 5 elements
                        for g in g_list: # g_list contains 20 elements
                            for h in h_list: # h_list contains 10 elements
                                for i in i_list: # i_list contains 10 elements
                                    for j in j_list: # j_list contains 10 elements
                                        pool.apply_async(prestart, (df, start_date, end_date, curr_date, 
                                                                    analysis_period, a, b, c, d, e,
                                                                    f, g, h, i, j, exec_log, lock))
pool.close()
pool.join()
logger.info(exec_log[1])

Tags: in服务器logfordateasync时间模式
1条回答
网友
1楼 · 发布于 2024-05-03 12:00:06

Q : Could anyone help to find the best solution (consumes least time) for this scenario?

当然,让我们检查一下购物清单的可见部分:

1)
避免Lock()-处理,因为任何形式的Lock()-处理仍然存在,你希望代码执行的并行组织内爆回到一个阻塞状态,一个接一个地重新编排(让所有其他的等待轮到他们——不管你在steriods服务器上放置多少个大RAM——都等待轮到他们,在大部分时间里试着“抓住”这个Lock()

2)
避免使用任何形式的共享,如果任何形式的共享资源仍然存在,您希望拥有并行工作流(再次)的方法是等待某一时刻,任何此类共享资源从任何其他人的使用中解放出来,并可能开始被此流程使用。你知道吗

3)
避免任何过多的进程/内存实例化(除了您已经经历过的RAM崩溃之外,对于HPC级并行问题解决方案来说,这些都是非常昂贵的—包括:

  • [TIME]-域。。。实例化加载项开销。。。~大量的[ns]
  • [SPACE]-域。。。新的内存分配需求是由O/S以显著的附加成本以不断增长的规模处理的,远远超过了~数千[ns]的大量数据,最糟糕的是陷入虚拟内存交换窒息。。。同样,为移动数据存储器块支付相关的[TIME]域成本(在RAM副本中,对于NUMA CPU核心非本地RAM目的地,成本约为300-350 ns)+基于数据量的I/O带宽驱动和空闲RAM信道可用性进一步限制了这种数据传输延迟。在掉入交换的情况下,O/S编排的交换流(即在您的控制域之外)的代价是~1000 x ~10000 x更糟。。。并通过具有最高优先级来阻止在该时间段内任何其他计算和读/写到RAM的尝试,因此没有人希望这些在计算期间发生的另一个原因)

使用multiprocessing.get_all_start_methods()将显示localhost O/S可以提供的所有选项,以消除(小规模缓解)不需要的过多RAM分配。你知道吗

使用len( os.sched_getaffinity(0) )控件而不是上面使用的multiprocessing.cpu_count(),将消除localhost过度订阅免费使用的CPU内核的数量(也有更少的“just”-[CONCURRENT]-RAM副本,这些副本必须等待调度程序顺序的转换,在它们的RAM/CPU执行转换之前…),如果O/S关联映射策略限制用户程序使用指定的所有平台硬件内核。你知道吗


基于“可怕的”for的“外部”迭代器可能总是会得到改进,但核心策略更为重要:

可能会将代码重构为计算:

一个干净的、以性能为中心的计算方法可以平衡现实世界的成本和一个人在花费这些成本后将获得的净性能收益。你知道吗

许多“记住语法”的方法无法扩展到远远超过某些主要的不断增长的大小-首先,通过体验从缓存计算中逐出的罪恶,感受到RAM的实际成本(在教科书示例和演示中没有观察到),接下来是RAM数据流的成本,对于越来越大的数据大小,最后,但并非最不重要的是,来自多处理的天真期望的成本(这取决于O/S和版本,可能会引入分配许多完整python会话副本的生成附加成本,这可能会导致内存错误崩溃,就像上面发布的情况一样)

假设10台服务器各有16个内核和128gbram,那么这个有前途的move-in概念将测试python进程在使用数据和下一个内存计算prestart()时的大小在一台服务器中,不要让更多的“工作者”进入RAM(以避免交换),接下来创建一个消息传递/信令元层,使用任何高性能、低延迟的工具(如ZeroMQ或nanomsg are)来协调分布工作者池中的多个作业的智能参数传递,并设计工作流,以便由于系统和O/S属性的原因,您永远不会将一段数据传递两次(因为传递参数的附加成本比O(n)更高),因此在性能驱动的系统中,永远不会将一段数据移动两次。你知道吗


遵循这几个简单的规则并不便宜,但是没有更快的方法(免费的越少…)你知道吗

相关问题 更多 >