我有一个面向对象的Python程序,其中我使用多处理在每个对象中执行特定的数据操作。我将每个对象存储在一个通用的管理器字典中。当我想要更新一个对象时,首先,我从字典中检索对象,在更新之后,我将它放回原处。我的类结构如下
from src.data_element import Data_element
from multiprocessing import freeze_support, Process, Manager
import pandas as pd
class Data_Obj(Data_element):
def __init__(self, dataset_name,name_wo_fields, fields):
Data_element.__init__(self, dataset_name, name_wo_fields, fields)
self.depends=['data_1','data_2']
def calc(self,obj_dict_manager):
data_1=obj_dict_manager['data_1']
data_2=obj_dict_manager['data_2']
self.df = pd.merge(
data_1.df,
data_2.df,
on='week',
suffixes=('', '_y')
)[['week','val']]
def calculate(obj_dict_manager,data):
data_obj=obj_dict_manager[data]
data_obj.calc(obj_dict_manager)
obj_dict_manager[data]=data_obj
if __name__ == '__main__':
freeze_support()
manager=Manager()
obj_dict_manager=manager.dict()
obj_dict_manager=create_empty_objects(obj_dict_manager)
joblist=[]
for data in obj_dict_manager.keys():
p=Process(target=calculate, args=(obj_dict_manager,data))
joblist.append(p)
p.start()
for job in joblist:
job.join() 在这些操作期间,有大量的时间花费在
data_1=obj_dict_manager['data_1']
data_2=obj_dict_manager['data_2']即,在从管理器字典中检索对象期间花费的1秒,而计算的其余部分又花费1秒。
有什么办法可以缩短我在这里花费的时间吗?我将进行数千次这样的操作,性能对我来说至关重要。
发布于 2014-07-17 04:39:35
重要的注意事项
您正在做一些具有潜在危险的事情:当您在obj_dict_manager中迭代键时,您将启动修改同一字典的进程。你永远不应该在迭代的时候修改某些东西,并且从子过程异步地进行修改可能会带来特别奇怪的结果。
问题的可能原因
1)我不知道您的共享字典中实际存储了多少对象(因为我们没有create_empty_objects()的代码),但如果数量很大,您的子进程可能会争用对共享字典的访问。特别是,由于您同时对字典进行读取和写入,因此它将在很多时候被一个或另一个进程锁定。
2)由于我们看不到您的共享字典中有多少key,我们也看不到有多少进程正在启动。如果您在系统上创建的进程比内核多,那么您的CPU可能会受到大量context switching的影响,这将使一切变慢。
3) #1和#2的组合-如果管理器将锁授予一个进程,然后该进程进入睡眠状态,这可能会特别有问题,因为在8核机器上,有几十个进程竞争CPU时间,现在每个人都必须等待,直到该进程唤醒并释放锁。
如何修复它
1)如果您的问题倾向于#1,请考虑拆分字典而不是使用共享字典,并将字典的一块传递给每个子进程,让它们执行所需的任何操作,让它们返回结果字典,然后在进程完成时重新组合所有返回的字典。如果你能把字典分成几部分,像multiprocessing.map_async()这样的东西可能更适合你。
2)在大多数情况下,尝试将产生的进程数量限制为系统上的核心数量,如果您的系统上同时运行了许多其他程序,则有时甚至更少。这种情况的一个例外是,如果你正在进行大量的并行处理,并且你预计子进程会被阻塞很多,比如在并行IO时。
https://stackoverflow.com/questions/24514656
复制相似问题