11

I have a few callback functions and I'd like to launch as multiple processes and have them all terminate via signal from the parent process.

My current way of doing this is creating a shared c_bool with multiprocessing.Value and setting it to True, then distributing it to all of my processes when they are created. My processes all run a while loop using the shared bool like so:

while myC_bool: ...keep running...

I can then just switch the bool to False from my parent process and all child processes will complete their final loop and exit.

很多人都告诉过我,并且在文档中阅读过在使用多处理时应该尽量避免使用共享内存。有人告诉我避免这种情况的最佳方法是守护进程,给它一个自定义信号处理程序并向它发送一个 sigint/sigterm/etc...

我的问题是,是否专门使用 bool 来保持循环处于活动状态,并且只能从我的父进程中更改它的值,并从多个子进程中读取它是一个合适的解决方案,以使我的所有子进程快速安全地终止?我觉得所有孩子只看一个共享布尔值的开销比向他们发送 x 个信号要少。

守护进程会是更好的解决方案吗?如果是这样,我需要一些帮助来理解为什么。

4

3 回答 3

14

使用您的解决方案有很多充分的理由:

  • 它比信号更容易思考。
  • 它需要处理的跨平台问题更少。
  • 您已经获得了以这种方式工作的代码。
  • 如果您将来想要添加“优雅关闭”机制,它可以很容易地添加。

… 等等。

请记住,除非您可以向自己证明,multiprocessing并且底层操作系统原语,在您关心的每个平台上,都可以保证在没有同步的情况下工作,Lock否则您需要在每次访问共享布尔时放置一个或其他内容。这并不复杂,但是……一旦你这样做了,使用例如Event没有共享布尔值的 an 可能会更简单。

无论如何,如果其中任何一个是你的理由,我会说很好,那样做。但是根据您的问题,您实际上是因为性能而选择了这个:

我觉得所有孩子只看一个共享布尔值的开销比向他们发送 x 个信号要少

如果这是你的理由,那你几乎肯定是错的。孩子们每次都必须通过某个循环查看共享布尔值(并获取共享锁!),而信号只需要发送给每个孩子一次。因此,您的开销几乎肯定会以这种方式高得多。

但实际上,我无法想象每个子进程发送一个信号,甚至每个进程每个循环捕获一次进程间锁的开销,在任何有用的程序中都接近瓶颈,所以......为什么开销在这里甚至很重要首先?用最简单的方式做最有意义的事情。

于 2013-04-02T00:13:25.320 回答
2

由于您很小心谁修改了共享变量,所以应该没问题。

有许多不同的解决方案可能。例如,使用 a multiprocessing.Event,并在设置时终止进程。或使用multiprocessing.Connection对象(来自管道)。后者可用于父母和孩子之间的双向通信。就像给孩子一个停止的信号,然后给父母一个确认。

于 2013-04-01T22:10:33.847 回答
0

告诉你“不要这样做”的人是错误的。共享内存的重点是在多处理器之间共享内存,而这正是您正在做的事情。

您有一个 1) 简单且 2) 有效的解决方案。信号/守护程序方法是 1) 非常酷 2) 更难正确编码和 3) 更难理解。

我在您的方法中看到的唯一缺陷是进程可能会从 CPU 的缓存中看到 bool 的陈旧副本,并在关闭时稍微延迟。有一些方法可以刷新缓存以确保不会发生这种情况,但您可能不需要它们,因为对于大多数应用程序来说,缓存刷新经常自动发生。

坚守阵地。

于 2013-04-01T22:16:19.770 回答