首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类实例的Python多进程

类实例的Python多进程
EN

Stack Overflow用户
提问于 2020-10-30 15:06:03
回答 2查看 238关注 0票数 0

我有一个问题,这个问题与我的问题并没有真正的关系,而是为什么它不是一个问题。也许有点傻,但我对课程不太熟悉,我正在努力学习。假设我有一个定义如下的类:

代码语言:javascript
复制
import numpy as np
import multiprocessing as mp


class Foo(object):
    def __init__(self, a):
        self.a = a

    def Sum(self, b):
        self.a = np.random.randint(10)
        return self.a + b, self.a

我创建了一个对象:

代码语言:javascript
复制
foo = Foo(1)

然后,在不同进程之间并行计算b的不同值的求和结果:

代码语言:javascript
复制
def Calc(b):
    return foo.Sum(b)

pool = mp.Pool(processes=2)
b = [0, 1, 2, 3]
out = pool.map(Calc, b)
print(out)

哪种打印(在一种情况下是随机的):

代码语言:javascript
复制
[(8, 8), (5, 4), (3, 1), (7, 4)]

这是正确的。我的问题是,不同的进程如何能够同时修改类属性a(在本例中,操作相当快,但在我的实际示例中,操作需要几秒钟,如果不是分钟,那么并行化)而不影响彼此?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-30 15:57:47

每个过程都是独立的,它们之间没有任何交流。当您将foo对象发送到不同的进程时,它们不再是同一件事了--它们中有许多是自己做的事情。您的问题实际上不是关于类或类实例,而是关于在不同进程中发生的事情。

打印实例的id及其a属性可以说明。

代码语言:javascript
复制
import multiprocessing as mp
import numpy as np

class Foo(object):
    def __init__(self, a):
        self.a = a
    def Sum(self, b):
        s = f'I am {id(self)}, a before={self.a}'
        self.a = np.random.randint(10)
        print(f'{s} | a after={self.a}')
        return self.a + b, self.a

foo = Foo(1)

def Calc(b):
    return foo.Sum(b)

if __name__ == '__main__':

    print(f'original foo id:{id(foo)}')

    pool = mp.Pool(processes=2)
    b = [0, 1, 2, 3, 5, 6, 7, 8]
    out = pool.map(Calc, b)
    print(out)
    print(f'{id(foo)}.a is still {foo.a}') 
    # not sure why this is necessary
    pool.terminate()

然后从命令提示符运行:

代码语言:javascript
复制
PS C:\pyprojects> py -m tmp
original foo id:2235026702928
I am 1850261105632, a before=1 | a after=4
I am 1905926138848, a before=1 | a after=1
I am 1850261105632, a before=4 | a after=8
I am 1905926138848, a before=1 | a after=9
I am 1850261105632, a before=8 | a after=2
I am 1905926138848, a before=9 | a after=9
I am 1850261105632, a before=2 | a after=7
I am 1905926138848, a before=9 | a after=3
[(4, 4), (2, 1), (10, 8), (12, 9), (7, 2), (15, 9), (14, 7), (11, 3)]
2235026702928.a is still 1

播放打印字符串:

代码语言:javascript
复制
import multiprocessing as mp
import numpy as np
import os

class Foo(object):
    def __init__(self, a):
        self.a = a
    def Sum(self, b):
        s = f'I am {id(self)}, a: before={self.a}'
        self.a = np.random.randint(10)
        s = f'{s} | after={self.a}'
        return os.getpid(),s,(self.a + b, self.a),b

foo = Foo(1)

def Calc(b):
    return foo.Sum(b)

if __name__ == '__main__':

    print(f'original foo id:{id(foo)}')

    pool = mp.Pool(processes=2)
    b = [0, 1, 2, 3, 5, 6, 7, 8]
    out = pool.map(Calc, b)
    out.sort(key=lambda x: (x[0],x[-1]))
    for result in out:
        print(f'pid:{result[0]} b:{result[-1]} {result[1]} {result[2]}')
    print(f'{id(foo)}.a is still {foo.a}')
    pool.terminate()

..。

代码语言:javascript
复制
PS C:\pyprojects> py -m tmp
original foo id:2466513417648
pid:10460 b:1 I am 2729330535728, a: before=1 | after=2 (3, 2)
pid:10460 b:3 I am 2729330535728, a: before=2 | after=5 (8, 5)
pid:10460 b:6 I am 2729330535728, a: before=5 | after=2 (8, 2)
pid:10460 b:8 I am 2729330535728, a: before=2 | after=2 (10, 2)
pid:13100 b:0 I am 2799588470064, a: before=1 | after=1 (1, 1)
pid:13100 b:2 I am 2799588470064, a: before=1 | after=6 (8, 6)
pid:13100 b:5 I am 2799588470064, a: before=6 | after=8 (13, 8)
pid:13100 b:7 I am 2799588470064, a: before=8 | after=0 (7, 0)
2466513417648.a is still 1
PS C:\pyprojects>
票数 2
EN

Stack Overflow用户

发布于 2020-10-30 15:17:04

每个进程都使用自己的内存,因此它们不能修改另一个进程的类属性。另一方面,如果您要对线程执行同样的操作,则会遇到争用条件的问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64610930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档