在多进程循环中访问全局变量

时间:2021-05-03 16:35:58

标签: python windows loops multiprocessing

我不知道发生了什么?!这很奇怪,所以你能解释一下原因并解决它吗? 我试图在 2 个循环中运行多处理,为了减少计算,我需要计算一些全局变量,即 'ga' 和 'gb',但在进入多处理的函数 'sirgr' 中,ga 和 gb 被扭曲了。 ga 到(循环 1 的最后一个范围减去 1 plus100 我的意思是 107)和 gb 也是(循环 2 的最后一个范围减去 1 plus100 我的意思是 123)所以这是怎么回事? global ga,gb 也没有任何帮助。 我知道 ofc 我可以将它发送给函数,但我需要全局。

import multiprocessing
def sirgr(row,col):
    global ga,gb
    print('sirgr',ga,gb)
    return ((row,col),(ga,gb))
def main():
    print('mainf',ga,gb)
    if __name__=="__main__":
        with multiprocessing.Pool() as pool:
            print('ino',tupleinput)
            output = list(pool.starmap(sirgr,tupleinput))
            print('out',output)
process_num=2
tupleinput=[]
for row in range(8):
    ga=row+100
    for col in range(20,24):
        gb=col+100
        print("r",row,'c',col)
        print('mainit',ga,gb)
        tupleinput.append((row,col))
        if len(tupleinput)==process_num:
            main()
            tupleinput=[]

结果:

#############
r 0 c 20
mainit 100 120
r 0 c 21
mainit 100 121
mainf 100 121
ino [(0, 20), (0, 21)]
out [((0, 20), (107, 123)), ((0, 21), (107, 123))]
#############
r 0 c 22
mainit 100 122
r 0 c 23
mainit 100 123
mainf 100 123
ino [(0, 22), (0, 23)]
out [((0, 22), (107, 123)), ((0, 23), (107, 123))]
....
#############
r 7 c 20
mainit 107 120
r 7 c 21
mainit 107 121
mainf 107 121
ino [(7, 20), (7, 21)]
out [((7, 20), (107, 123)), ((7, 21), (107, 123))]
#############
r 7 c 22
mainit 107 122
r 7 c 23
mainit 107 123
mainf 107 123
ino [(7, 22), (7, 23)]
out [((7, 22), (107, 123)), ((7, 23), (107, 123))]

例如在 r 0 c 21 输出之后的输出中

out [((0, 20), (100, 121)), ((0, 21), (100, 121))]

不过是

out [(({row}, {col-1}), (107, 123)), (({row}, {col}), (107, 123))] 用于所有输出 但我应该是

out [(({row}, {col-1}), ({row}, {col+100})), (({row}, {col}), {col+100})]

1 个答案:

答案 0 :(得分:1)

您没有提供 q 函数,所以我创建了自己的函数。

请参阅我关于无法修改主进程中的常规全局变量并期望它们在子进程的 addrss 空间中出现更改的评论。如果你坚持使用全局变量,这些必须是管理共享变量。必须通过其 value 属性访问它们的实际值。

注意:您的代码一次只使用两个元组调用 starmap,这确实不是最有效的处理方式,当然,除非您只有两个 CPU 内核,但即便如此,它仍然更好将所有任务排队并调用 starmap 一次 - 空闲时间会更少。由于您正在创建不带参数的池,它将创建一个池大小等于您拥有的 CPU 内核数,这很可能大于两个。因此,您应该充分利用您拥有的任何 CPU。

import multiprocessing

def q(*args):
    args = [str(arg) for arg in args]
    print(', '.join(args))

def init_pool(globala, globalb):
    global ga, gb
    ga = globala
    gb = globalb

def sirgr(row, col):
    q('sirgr', ga.value, gb.value)
    return ((row,col),(ga.value, gb.value))

def main(pool, tupleinput):
    q('mainf', ga.value, gb.value)
    q('ino',tupleinput)
    output = pool.starmap(sirgr, tupleinput)
    q('out',output)

if __name__ == '__main__':
    with multiprocessing.Manager() as manager:
        ga = manager.Value('i', 0)
        gb = manager.Value('i', 0)
        pool = multiprocessing.Pool(initializer=init_pool, initargs=(ga, gb))
        tupleinput=[]
        for row in range(8):
            ga.value = row+100
            for col in range(20,24):
                gb.value = col+100
                q("r", row, 'c', col)
                q('mainit',ga.value, gb.value)
                tupleinput.append((row, col))
        main(pool, tupleinput)

打印:

r, 0, c, 20
mainit, 100, 120
r, 0, c, 21
mainit, 100, 121
r, 0, c, 22
mainit, 100, 122
r, 0, c, 23
mainit, 100, 123
r, 1, c, 20
mainit, 101, 120
r, 1, c, 21
mainit, 101, 121
r, 1, c, 22
mainit, 101, 122
r, 1, c, 23
mainit, 101, 123
r, 2, c, 20
mainit, 102, 120
r, 2, c, 21
mainit, 102, 121
r, 2, c, 22
mainit, 102, 122
r, 2, c, 23
mainit, 102, 123
r, 3, c, 20
mainit, 103, 120
r, 3, c, 21
mainit, 103, 121
r, 3, c, 22
mainit, 103, 122
r, 3, c, 23
mainit, 103, 123
r, 4, c, 20
mainit, 104, 120
r, 4, c, 21
mainit, 104, 121
r, 4, c, 22
mainit, 104, 122
r, 4, c, 23
mainit, 104, 123
r, 5, c, 20
mainit, 105, 120
r, 5, c, 21
mainit, 105, 121
r, 5, c, 22
mainit, 105, 122
r, 5, c, 23
mainit, 105, 123
r, 6, c, 20
mainit, 106, 120
r, 6, c, 21
mainit, 106, 121
r, 6, c, 22
mainit, 106, 122
r, 6, c, 23
mainit, 106, 123
r, 7, c, 20
mainit, 107, 120
r, 7, c, 21
mainit, 107, 121
r, 7, c, 22
mainit, 107, 122
r, 7, c, 23
mainit, 107, 123
mainf, 107, 123
ino, [(0, 20), (0, 21), (0, 22), (0, 23), (1, 20), (1, 21), (1, 22), (1, 23), (2, 20), (2, 21), (2, 22), (2, 23), (3, 20), (3, 21), (3, 22), (3, 23), (4, 20), (4, 21), (4, 22), (4, 23), (5, 20), (5, 21), (5, 22), (5, 23), (6, 20), (6, 21), (6, 22), (6, 23), (7, 20), (7, 21), (7, 22), (7, 23)]
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
sirgr, 107, 123
out, [((0, 20), (107, 123)), ((0, 21), (107, 123)), ((0, 22), (107, 123)), ((0, 23), (107, 123)), ((1, 20), (107, 123)), ((1, 21), (107, 123)), ((1, 22), (107, 123)), ((1, 23), (107, 123)), ((2, 20), (107, 123)), ((2, 21), (107, 123)), ((2, 22), (107, 123)), ((2, 23), (107, 123)), ((3, 20), (107, 123)), ((3, 21), (107, 123)), ((3, 22), (107, 123)), ((3, 23), (107, 123)), ((4, 20), (107, 123)), ((4, 21), (107, 123)), ((4, 22), (107, 123)), ((4, 23), (107, 123)), ((5, 20), (107, 123)), ((5, 21), (107, 123)), ((5, 22), (107, 123)), ((5, 23), (107, 123)), ((6, 20), (107, 123)), ((6, 21), (107, 123)), ((6, 22), (107, 123)), ((6, 23), (107, 123)), ((7, 20), (107, 123)), ((7, 21), (107, 123)), ((7, 22), (107, 123)), ((7, 23), (107, 123))]

更新

如果你真的想一次提交两个任务,那么(假设提交的任务总数是2的倍数):

if __name__ == '__main__':
    with multiprocessing.Manager() as manager:
        ga = manager.Value('i', 0)
        gb = manager.Value('i', 0)
        pool = multiprocessing.Pool(2, initializer=init_pool, initargs=(ga, gb))
        tupleinput=[]
        for row in range(8):
            ga.value = row+100
            for col in range(20,24):
                gb.value = col+100
                q("r", row, 'c', col)
                q('mainit',ga.value, gb.value)
                tupleinput.append((row, col))
                if len(tupleinput) == 2:
                    main(pool, tupleinput)
                    tupleinput = []

更新 2

我碰巧重新访问了这个,看到我正在使用 managed Value 实例来实现 gagb,它们可以工作,但还有更多共享内存 Value 个实例的开销,对于这个问题你只需要:

if __name__ == '__main__':
    ga = multiprocessing.Value('i', 0, Lock=False) # no synchronization required
    gb = multiprocessing.Value('i', 0, Lock=False) # no synchronization required
    pool = multiprocessing.Pool(2, initializer=init_pool, initargs=(ga, gb))
    ... # etc.
相关问题