Python pathos.multiprocessing ProcessingPool。为什么池交换信息?
简介 我有大量数据,需要进行具体计算。不幸的是,如果我一个接一个地进行计算,整个过程将花费一天的时间。这就是为什么我在一台有32个CPU的机器上使用paths.multiprocessing ProcessingPool。这样,整个过程大约需要30分钟 问题 预期的行为是所有计算并行运行,并且彼此完全独立。我注意到,对于少量计算(例如40),这是正确的,但如果我将数字增加到90,数据会混合。这些过程似乎是相互“交流”的……换句话说,它们可以访问相同的变量 问题 知道发生了什么吗 有用链接: 代码 下面的代码是我机器上的简化版本,但想法是一样的。下面是代码:Python pathos.multiprocessing ProcessingPool。为什么池交换信息?,python,multiprocessing,pathos,Python,Multiprocessing,Pathos,简介 我有大量数据,需要进行具体计算。不幸的是,如果我一个接一个地进行计算,整个过程将花费一天的时间。这就是为什么我在一台有32个CPU的机器上使用paths.multiprocessing ProcessingPool。这样,整个过程大约需要30分钟 问题 预期的行为是所有计算并行运行,并且彼此完全独立。我注意到,对于少量计算(例如40),这是正确的,但如果我将数字增加到90,数据会混合。这些过程似乎是相互“交流”的……换句话说,它们可以访问相同的变量 问题 知道发生了什么吗 有用链接: 代码
from pathos.multiprocessing import ProcessingPool, cpu_count
class TestMultiprocessing:
def __init__(self):
self.number = 0
def do_something(self, args):
for arg in args:
self.number += arg
return self.number
def run(self):
# Generate a big list
l = []
for i in range(0, 100):
l.append([1,2,3])
pool = ProcessingPool(cpu_count())
results = pool.imap(self.do_something, l)
pool.close()
pool.join()
pool.clear()
results = list(results)
for result in results:
print(result)
tm = TestMultiprocessing()
tm.run()
更新
我不能展示示例代码,因为它是保密的,但我可以对代码的工作原理做一个简短的解释
有一个CSV文件,其中包含数千行数据(~80000行)。我编写的代码必须运行800个任务,每个任务执行特定的计算,从CSV文件中获取数据
机器有N个CPU,因此Pathos将所有800个任务分解为M个组,每个组包含N个任务(如果CPU的数量为偶数M*N=800)。Pathos创建N个并行执行所需计算的池。当计算完成时,每个池生成一个字典列表,并继续执行下一组任务-重复该过程M次
列表中的每个字典都包含一个与任务编号相对应的唯一键,该编号可以是1到800。通过这种方式,我可以检查池X是否生成与任务X相关的字典(例如103)。期望是池X生成的结果只包含键X
值得一提的是,上述过程消耗了机器的大部分内存
在对生成的结果进行详细观察后,我注意到以下几点。如果我运行N个任务(例如,4个任务对应一台有4个CPU的机器),则每个字典列表都包含对应于特定任务的键。例如,池X生成一个带有键X的字典列表
但是,如果我运行的任务超过N个,则与大于N的任务对应的字典将包含来自以前任务的数据。例如,池Y生成一个带有键Y、X等的字典列表
我的结论是,pool X不会从以前的计算中清除数据(内存),而下一个任务将从以前的计算中继承数据
解决方案
尽管我使用了pool.clear(),但这并不能帮助我解决问题。我找到的临时解决方案如下
我“手动”将任务分解为多个组
import numpy as np
import math
# Get the number of CPUs
cpus = cpu_count()
# Check how many groups of tasks we have to run
chunks = math.ceil(len(l)/cpus)
# Break down the list of tasks to chunks/groups
l_chunks = np.array_split(l, chunks)
# Loop the chunks
for l_chunk in l_chunks:
pool = ProcessingPool(cpus)
results = pool.imap(self.do_something, l_chunk.tolist())
pool.close()
pool.join()
pool.clear()
results = list(results)
for result in results:
print(result)
这就解决了我的问题。好吧,你是在多进程分叉之前初始化类来使用共享状态的……你说进程是通信的。展示你为什么这么想。换句话说,做一个适当的(顺便问一下,你需要
pathos
而不是内置的multiprocessing
包,有什么理由吗?@AKX我应该做什么更改来避免共享状态?谢谢我之所以使用pathos是因为我对pickle有问题。我得想想到底是什么问题。“那是很久以前的事了。”物理学家,我不能举出一个例子,但我可以解释。有一个包含几千行数据的CSV文件。我并行运行大约800个任务。每个任务从CSV文件加载数据并执行不同的操作。每个完成的任务都会生成一个字典列表。每个字典都包含作为计算结果的数据。此外,字典还包含一个唯一的键,用于标识执行计算的过程。期望pool X生成字典列表,每个字典都有键X。如果我运行少量任务,这是真的。