是通过全局标志变量安全的python多处理与过程间信号传导



我正在运行许多子过程(比我有更多的核心),如果符合某个条件,我设置了全局变量的值 global bailout

然后,如果设置了bailout,则所有随后的子过程尽快退出。

参见例如这个简单的示例,其中我将20个调用的结果乘以loop()函数,但是如果这些调用中的任何一个返回零:

import sys
import random
import multiprocessing
def loop(tup):
    global bailout
    if bailout==1:                    # obey a global bail out "flag"
        return 0
    x = random.random() - 0.5
    if x < 0:
        bailout = 1                   # set a global bail out "flag"
        return 0
    return x
def top():
    global bailout
    bailout = 0
    runtups = 20 * [[0]]              # a dummy parameter [0] for function "loop"
    pool = multiprocessing.Pool()
    results = pool.imap(loop, runtups)
    pool.close()
    res = 1
    sys.stdout.write("1")
    for result in results:
        sys.stdout.write(" * %g" % result)
        res = res * result
    sys.stdout.write(" = %gn" % res)
top()

它可以正常工作(或确切地说,每次尝试使用时,它都可以使用)。即,我的桌面有4个内核,如果前4个子过程之一将救助设置为1(在此示例中几乎总是发生),则所有后续运行均在 if bailout==1 条件上退出。

但是安全吗?

我的意思是,子进程都可以做的就是将bailout设置为1。但是,如果两个子过程都想将救助设置为1,该怎么办?他们是否有可能同时尝试,从而导致救助变得不确定?还是保证这将永远不会发生(也许是因为最高级别的过程总是在串行上处理完整的子过程?)

在过程之间未共享全球。如果您在loop中添加一些日志记录,则可以看到真正发生的事情:

def loop(tup):
    global bailout
    if bailout==1:
        print(f'pid {os.getpid()} had bailout 1')
        return 0
    x = random.random() - 0.5
    if x < 0:
        print(f'pid {os.getpid()} setting bailout 1')
        bailout = 1
        return 0
    return x

这将产生类似:

的输出
pid 30011 setting bailout 1
pid 30013 setting bailout 1
pid 30015 setting bailout 1
pid 30009 setting bailout 1
pid 30010 setting bailout 1
pid 30011 had bailout 1
pid 30013 had bailout 1
pid 30009 had bailout 1
pid 30014 setting bailout 1
pid 30015 had bailout 1
pid 30010 had bailout 1
pid 30011 had bailout 1
1 * 0.494123 * 0.0704172 * 0 * 0.10829 * 0 * 0.465238 * 0 * 0.0638724 * 0 * 0 * 0 * 0.227231 * 0 * 0 * 0 * 0 * 0 * 0 * 0.463628 * 0.372984 = 0

发生的事情是multiprocessing.Pool()正在启动4个过程,这些过程被重新使用,它们可以使用。因此,在处理runtups中的20个项目时,最终每个过程都将其bailout设置为1。当重复使用该过程时,它会触发Bailout子句。

由于您是随机决定何时设置bailout = 1,因此在处理20个项目时,它可能永远不会发生,或者可能在某些过程中而不是其他过程中发生,因此您可能不会得到我粘贴的相同结果,但是至少某些过程可能会进入救助模式。

如果您正在寻找一种在过程之间共享状态的可靠方法,请访问https://docs.python.org/3/library/multiprocessing.html#sharing-sharing-state-bet-bet-processes.

可能吗?
它安全吗?
是否保证?

虽然Gil-Stepping确实确实使所有基于线程的(不是基于子流程)的多处理工作仍然在纯[SERIAL]处理中出现,但问题更多地是关于主要方法,以及上述所有提出的问题是否存在安全满足。


不要试图违反有记录的建议:

最好地提及文档中的明确语句:

16.6.3。编程指南

...

明确将资源传递给子进程

在UNIX上,儿童过程可以利用使用全局资源在父过程中创建的共享资源。但是,最好将对象作为参数传递给子女过程的构造函数。

除了将代码(潜在)与Windows兼容之外,这还可以确保,只要子进程仍然活着,对象就不会在父进程中收集垃圾。如果对象在父过程中收集垃圾时释放某些资源,这可能很重要。


16.6.3.2 Windows

...

全局变量

请记住,如果代码在子进程中运行以访问全局变量,那么它看到的值(如果有)可能与 Process.start时父进程中的值不一样被称为。

但是,仅是模块级常数的全局变量不会引起任何问题。


除了帮助交流或quot的本地Pythonic工具外状态(不仅我在可能的情况下提倡永远不要共享),还有一些智能工具,用于设计确实使用的分布式系统,使用多代理概念,每个线程都可以使用其他轻巧的通信工具,绩效较少,而不是本机Gil-Steppped操作允许(参考Zeromq,Nanomsg等)。

相关内容

  • 没有找到相关文章

最新更新