python mutiprocessing:使用带有共享对象的实例化类的类方法

python mutiprocessing:使用带有共享对象的实例化类的类方法,python,multiprocessing,Python,Multiprocessing,我不熟悉并行处理,但有一个应用程序,它将是有用的。 我有大约10-100k个对象实例(类型为ClassA),我想使用多处理模块来分配在每个对象上调用特定类方法的工作。我已经阅读了大部分的多处理文档和几篇关于调用类方法的帖子,但是我还有一个额外的复杂问题,那就是ClassA对象都有一个指向另一种类型(ClassB)的同一实例的属性,它们可以向另一种类型添加/删除它们自己或其他对象。我知道共享状态对并发进程不利,所以我想知道这是否可能。老实说,代理/管理器mutliprocessing方法有点让我不

我不熟悉并行处理,但有一个应用程序,它将是有用的。 我有大约10-100k个对象实例(类型为
ClassA
),我想使用多处理模块来分配在每个对象上调用特定类方法的工作。我已经阅读了大部分的多处理文档和几篇关于调用类方法的帖子,但是我还有一个额外的复杂问题,那就是ClassA对象都有一个指向另一种类型(
ClassB
)的同一实例的属性,它们可以向另一种类型添加/删除它们自己或其他对象。我知道共享状态对并发进程不利,所以我想知道这是否可能。老实说,代理/管理器mutliprocessing方法有点让我不知所措,无法理解它们对共享对象的所有影响,但是如果其他人向我保证我可以让它工作,我会花更多的时间来理解它们。如果不是,这将是为分布式进程设计的一个教训

以下是我的问题的简化版本:

ClassA:
定义初始(self,classB_state1,classB_state2,另一个对象):
#指向共享ClassB实例的指针
self.state1=classB_state1
self.state2=classB_state2
self.state1.add(self)
self.object=另一个对象
def运行(B类其他公用池):
#对自己做点什么
如果#self.object的某些属性:
classB_另一个CommonPool.add(对象)
self.object=None
self.switch_states()
def开关_状态(自):
如果self处于self.state1:
self.state1.remove(self)
self.state2.add(self)
elif self在self.state2中:
self.state2.删除(self)
self.state1.add(self)
其他:
打印“状态切换失败!”
乙级(套):
#这本质上是一个带有散列的美化集,因此我可以拥有集的集合。
#如果这是一个糟糕的设计选择,我也想知道为什么
定义初始化(self,name):
self.name=名称
super(ClassB,self)。\uuuu init\uuuuu()
定义散列(自我):
返回id(自身)
C类:
定义初始化(自身,属性):
self.property=属性
#为ClassA方法定义一个可导入的函数,用于多处理
def unwrap_ClassA_运行(ClassA_实例):
返回classA\u实例。运行(classB\u另一个公共池)
def初始化_状态():
全球国家1
全球国家2
全球其他公共池
state1=B类(“state1”)
state2=B类(“state2”)
另一个CommonPool=ClassB(“objpool”)
现在,在定义类的同一个.py文件中:

来自多处理导入池的

def test_多处理():
初始化状态()
#实际上有10-10万个classA实例
object1=ClassC('iamred')
object2=ClassC('iamblue')
classA1=ClassA(状态1、状态2、对象1)
classA2=ClassA(状态1、状态2、对象2)
池=池(进程=2)
map(展开类运行,[classA1,classA2])

如果我在解释器中导入此模块并运行test_multiprocessing(),则在运行时不会出现错误,但会显示“切换状态失败!”消息,如果检查classA1/2对象,则它们没有修改各自的objects1/2,也没有切换任何ClassB状态对象的成员身份(因此ClassA对象不会注册为state1集合的成员)。谢谢!

有多个问题与在代码中使用多个进程无关,例如,Python无效。在将对象添加到基于哈希的容器中后,不应修改对象(这就是为什么
frozenset
set
不同,它是可散列的),修改全局共享状态也需要同步(您可以使用
多处理.dummy
进行调试,它使用线程(默认情况下状态是共享的),同时提供相同的接口)。最后,在不更改数据表示(和algirithm)的情况下;使用mp不太可能提高性能。不要将内置子类化!在99.9%的情况下,这是一个坏主意。此外,你不认为如果将
设置为可散列的那么简单,开发人员就已经实现了吗?@J.F.Sebastian抱歉,在简化过程中有些事情搞砸了,全局变量实际上是在另一个函数中声明y(I已更新)。我将阅读更多关于基于散列的容器的详细信息,等等。我现在正在学习一些关于数据容器的介绍类,希望这将有助于填补我现在缺少的一些概念。假设我可以修复容器类型,我能问另一个关于我在这篇文章中的基本假设的天真问题吗:为什么mp不能帮助run时间到了?@Bakuriu是的,这就是为什么我在代码中指出它可能不好的原因,感谢您的输入。正如J.F.Sebastian所提到的,这使得
frozenset
更有意义。@williaster:这不是一个天真的问题,这是一个非常有效的问题:1.在进程之间共享状态有两种主要方式:在进程之间复制(作为参数传递的对象)或将其放入共享内存()。在您的情况下,这需要大量复制和很少的处理。2.您可能需要序列化对全局共享状态的访问(例如,以避免读取不一致的状态)。