【问题标题】:Python Manager Dictionary EfficiencyPython Manager 字典效率
【发布时间】:2014-07-01 15:57:51
【问题描述】:

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

有什么方法可以减少我在这里花费的时间吗?我将进行数千次这样的操作,性能对我来说至关重要。

【问题讨论】:

    标签: python dictionary pandas multiprocessing


    【解决方案1】:

    重要提示

    您正在做一些具有潜在危险的事情:当您迭代 obj_dict_manager 中的键时,您正在启动修改同一个字典的进程。您永远不应该在迭代时修改某些内容,并且从子流程异步进行修改可能会引入特别奇怪的结果。

    问题的可能原因

    1) 我无法确定您的共享字典中实际存储了多少对象(因为我们没有 create_empty_objects() 的代码),但如果数量很大,您的子进程可能会争用访问权限到共享字典。特别是,由于您同时读取字典,它会在很多时候被一个或另一个进程锁定。

    2) 由于我们无法看到您的共享字典中有多少键,因此我们也无法看到有多少进程正在启动。如果您在系统上创建的进程多于内核,则您的 CPU 可能会受到大量 context switching 的影响,这会降低一切的速度。

    3) #1 和 #2 的组合 - 如果管理器将锁授予一个进程,那么这可能会特别成问题,然后该进程将进入睡眠状态,因为您有数十个进程在 8- 上竞争 CPU 时间核心机器,现在每个人都必须等到该进程唤醒并释放锁。

    如何解决

    1) 如果您的问题偏向于#1,请考虑拆分您的字典而不是使用共享字典,并将字典的一部分传递给每个子进程,让他们做任何他们需要的事情,让他们返回结果字典,然后在进程完成时重新组合所有返回的字典。如果你能把字典分开,像multiprocessing.map_async() 这样的东西可能更适合你。

    2) 在大多数情况下,尝试将生成的进程数限制为系统上的内核数,如果系统上同时运行许多其他东西,有时甚至更少。一个例外情况是,如果您正在执行大量并行处理,并且您希望子进程经常阻塞,例如在并行执行 IO 时。

    【讨论】:

      猜你喜欢
      • 2018-04-21
      • 2015-03-24
      • 1970-01-01
      • 2018-07-20
      • 2012-09-14
      • 2012-04-28
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      相关资源
      最近更新 更多