我有一个面向对象的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秒钟。
有什么方法可以减少在这里度过的时间吗?我将做成千上万次这样的操作,性能对我来说至关重要。
答案 0 :(得分:0)
您正在做一些有潜在危险的事情:当您在obj_dict_manager中迭代键时,您将启动修改同一字典的进程。你永远不应该修改一些东西,当你迭代它时,从子进程异步进行修改可能会引入特别奇怪的结果。
1)我无法告诉共享字典中实际存储了多少个对象(因为我们没有create_empty_objects()的代码),但是如果它是一个很大的数量,你的子进程可能会竞争访问共享字典。特别是,既然你已经阅读了和,那么它会在很多时候被一个或另一个进程锁定。
2)由于我们无法查看共享字典中有多少个密钥,因此我们也无法查看正在启动的进程数。如果您在系统上创建了比核心更多的进程,那么您可能会使CPU受到大量context switching的影响,这将会减慢所有内容。
3)#1&的组合#2 - 如果管理员向一个进程授予锁定,那么这可能会特别成问题,然后该进程进入休眠状态,因为您有8个进程在8核计算机上争用CPU时间,现在每个人都必须等到进程唤醒并释放锁定。
1)如果您的问题偏向#1,请考虑拆分字典而不是使用共享字典,并将字典块传递给每个子流程,让他们做任何他们需要的事情,让他们返回结果字典,然后在流程完成时重新组合所有返回的词典。如果您可以将字典分开,那么像multiprocessing.map_async()这样的东西可能对您更有效。
2)在大多数情况下,尝试将产生的进程数量限制为系统中的核心数量,如果在系统上同时运行许多其他东西,则有时甚至更少。例外情况是,如果您正在进行大量并行处理,并且您希望子进程能够进行大量阻塞,例如并行执行IO时。