Python管理器字典效率

时间:2014-07-01 15:57:52

标签: python dictionary pandas multiprocessing

我有一个面向对象的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秒钟。

有什么方法可以减少在这里度过的时间吗?我将做成千上万次这样的操作,性能对我来说至关重要。

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时。