【问题标题】:Using multiprocessing to call instances of a class method from another class使用多处理从另一个类调用类方法的实例
【发布时间】:2021-06-24 23:02:15
【问题描述】:

我需要在一个类中使用多处理技术来调用另一个类的方法。解释如下。

我正在编写多代理策略。因此,我的代码分为 3 个类:

  1. 代理类
  2. 环境类
  3. 主要。

在代理类中,我正在运行一个返回决策变量字典的 MILP 问题:

class Agent:
    def __init__():
        ....
    def Optimisation():
       .....
       return decision_agent

类环境接收所有代理的输出以计算“社区”输出。由于每个代理都是一个独立的实体,代理将并行计算他们的优化问题。因此,我想在环境类中使用多处理来获取所有代理的决策

import Agent as Agent

class Env:
    def __init__():
         self.agents = #list of agents in my environment

    def community_output():
        #**start the part of code I want to multiprocess**
        for agent in self.agents:
            agents_output.append(agent.Optimisation) 
        #**end the part of code I want to multiprocess**

        """compute community_output based on agents_output """

        return community_output

然后在main中,调用方法community_output()

import Env as Env

if __name__ == '__main__': 
    env = Env()
    result = env.community_output()

请问我该怎么做?

由于我有一个实例方法列表作为可迭代对象,因此我尝试了以下方法:

def job(instance):
    instance.Optimisation()
    return instance

if __name__ == '__main__':
   pool = mp.Pool(processes=4)
   agents_output= pool.map(job, agents)
   pool.close() 
   pool.join()

这仅在我删除 Env 类并将其所有处理放在 def job(instance) 之前才有效。

当我将它集成到Env 类中时:

import Agent as Agent

class Env:
    def __init__():
         self.agents = #list of agents in my environment

    def job(instance):
        instance.Optimisation()
        return instance

    def community_output():
        pool = mp.Pool(processes=4)
        agents_output = pool.map(self.job, self.agents)
        pool.close() 
        pool.join()

        """ Compute community_output based on agents_output """

        return community_output
Import Env as Env
if __name__ == '__main__': 
    env = Env()
    result = env.community_output()

我得到了错误:

  File "C:\Users\chaim\...\Env.py", line 576, in community_output
    results = pool.map(self.job, self.agents)
  File "C:\Users\chaim\anaconda3\envs\picos\lib\multiprocessing\pool.py", line 268, in map
    return self._map_async(func, iterable, mapstar, chunksize).get()
  File "C:\Users\chaim\anaconda3\envs\picos\lib\multiprocessing\pool.py", line 657, in get
    raise self._value
multiprocessing.pool.MaybeEncodingError: Error sending result: '[{'opt_prob': <Mixed-Integer Linear Program>, 'q_us_val': <190x1 matrix, tc='d'>, 'q_ds_val': 0.0, 'p_net_exp_val': <48x1 matrix, tc='d'>, 'q_sup_sell_val': <48x1 matrix, tc='d'>, 'q_sup_buy_val': <48x1 matrix, tc='d'>, 'p_es_ch_val': <48x1 matrix, tc='d'>, 'p_es_dis_val': <48x1 matrix, tc='d'>, 'q_ds_0': <1×1 Real Constant: 0>, 'q_us_0': <1×1 Real Constant: q_usᵀ·[190×1]>}]'. Reason: 'PicklingError("Can't pickle <function <lambda> at 0x000001B8B9C31288>: attribute lookup <lambda> on picos.modeling.options failed")'

我注意到:

{'opt_prob': <Mixed-Integer Linear Program>, '... q_usᵀ·[190×1]>}

agent.Optimisation方法返回的字典,picos是使用的优化API。

有什么办法可以解决这个问题吗?

【问题讨论】:

  • 类方法都会自动接收一个初始参数——通常命名为self——这是它们所属的类的实例。您的几乎所有代码中都没有。请提供一个可运行的minimal reproducible example,其他人可以使用它来测试他们的答案。
  • 是的,我的所有类方法中都包含“自我”。我将尝试详细说明一个最小的可重现示例以避免混淆。

标签: python python-multiprocessing picos-api


【解决方案1】:

您是否尝试从代理模块调用 Optimisation()?如果是,那么不应该

def job(instance):
    instance.Optimisation()
    return instance

改为

def job():
    return Agent.Optimisation()

【讨论】:

  • 实际上,我正在尝试从 Env 模块调用优化。复杂之处在于我想使用多处理从 Env 调用 Optimisation()。
【解决方案2】:

我对 PICOS 本身并不熟悉,但在对它做了一些假设之后,我认为以下是关于如何做你想做的事情的大致概述。请注意,传递给pool.map() 的函数参数是unbound Agent 类方法optimisation()。它将使用您在它们列表中的Agent 实例之一调用。

import multiprocessing as mp
from random import randrange  # For testing purposes.


class Agent:
    def __init__(self):
        ...
    def optimisation(self):
       decision_agent = {'var1': randrange(10), 'var2': randrange(10), 'var3': randrange(10)}
       return decision_agent


class Env:
    def __init__(self, num_agents):
         self.agents = [Agent() for _ in range(num_agents)]

    def community_output(self):
        with mp.Pool(processes=4, maxtasksperchild=1) as pool:
            agents_output = pool.map(Agent.optimisation, self.agents)
        return agents_output


if __name__ == '__main__':
    env = Env(3)
    result = env.community_output()
    print(result)

【讨论】:

  • 感谢您的回复。该建议仍然产生相同的错误。我试图详细说明一个最小的可重现示例。但令人惊讶的是,它工作得很好!我认为我的课程结构有问题。
  • 错误来自于我在字典中返回优化问题本身 {'opt_prob': 是 picos.Problem()} 的实例。现在,它返回一个异常
  • Exception in thread Thread-4: Traceback (most recent call last): File "C:\Users\chaim\anaconda3\envs\tf\lib\threading.py", line 932, in _bootstrap_inner self.run() File "C:\Users\chaim\anaconda3\envs\tf\lib\threading.py", line 870, in run self._target(*self._args, **self._kwargs) File "C:\Users\chaim\anaconda3\envs\tf\lib\multiprocessing\pool.py", line 576, in _handle_results task = get()
  • File "C:\Users\chaim\anaconda3\envs\tf\lib\multiprocessing\connection.py", line 251, in recv return _ForkingPickler.loads(buf.getbuffer()) TypeError: __new__() missing 2 required positional arguments: 'glyph' and 'operands'
  • 当你在 Python 中向进程传递参数或从进程返回值时,它们必须是“可腌制的”——看起来返回的字典包含不能这样的值。
猜你喜欢
  • 2015-06-10
  • 2011-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多