通过降低 worker 中的内存使用量使用 Pool 进行多处理

Multiprocessing with Pool by lowering memory usage in worker

我的目标是对具有数百个并发请求的外部 api 进行多处理请求。我使用 Pool 函数执行此操作,它工作正常,但是对于 64 个工作人员,我得到 25Gb 的 RAM 使用量(与工作人员数量成比例),这对于一个简单的 http 请求来说似乎太高了。

如何将 RAM 使用率降至最低,以便启动数百个工作程序?

我的假设是 Pool 函数在每个 worker 中复制了整个进程内存。我怎样才能避免这种情况?

代码:

from multiprocessing import Pool

def get_results(self, query):
    self.data["query"] = query["query"]
    results = requests.post(url_to_external_api_with_query_data).json()
    return {"results":results, "original_query":query["original_query"], "original_query_string":query["query"]}

def multiprocess_results(self, queries):
    pool = Pool(64)
    results_all = pool.map(self.get_results, queries)
    pool.close()
    pool.join()

首先,如果您向 i/o 绑定的 HTTPS 发送请求,那么您可能需要考虑使用多线程而不是多处理,这应该可以立即解决您的内存问题。 多处理的另一个问题是,它创建了拥有 Python 解释器副本的重复进程。所以几个工作代码是并行的 运行 因此你使用的内存总量应该取决于你在做什么。

对于多处理和多线程,我经常推荐 concurent.futures 我推荐它的原因是它会根据可用内存量自动分配工作人员进行多处理任务(这可以在您需要时覆盖)。

使用此模块有时比使用典型的多处理模块更容易,因为您可以用更少的代码获得更多。

from concurrent.futures import ProcessPoolExecutor

....

with ProcessPoolExecutor() as executor:
    executor.submit(self.get_results, queries)

同样,由于这是发送 HTTPS 请求,因此它是一个 i/o 绑定操作,您应该考虑使用多线程。此模块中的两种操作都一样

from concurrent.futures import ThreadPoolExecutor

....

with ThreadPoolExecutor() as executor:
     executor.submit(self.get_results, queries)