简体   繁体   English

如何在python中使用多处理正确终止子进程

[英]How to properly terminate child processes with multiprocessing in python

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. 我目前的做法是创建一个带有multiprocessing.Value的共享c_bool并将其设置为True ,然后在创建它们时将其分发给我的所有进程。 My processes all run a while loop using the shared bool like so: 我的进程都使用共享bool运行while循环,如下所示:

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. 然后,我可以从我的父进程将bool切换为False ,并且所有子进程将完成其最终循环并退出。

I've been told by many people, and have read in the docs that one should try avoid using shared memory when using multiprocessing. 许多人都告诉我,并且已经在文档中读到,在使用多处理时应该尝试避免使用共享内存。 I was told the best way to avoid this is to daemonize the process, give it a custom signal handler and send it a sigint/sigterm/etc... 我被告知避免这种情况的最佳方法是守护进程,给它一个自定义信号处理程序并发送一个sigint / sigterm / etc ......

My question is, is exclusively using the bool to keep a loop alive and ONLY ever alter it's value from my parent process, and read it from multiple child processes a suitable solution to make all of my child processes terminate quickly and safely? 我的问题是,是专门使用bool来保持循环活动,并且只是从我的父进程改变它的值,并从多个子进程读取一个合适的解决方案,以使我的所有子进程快速安全地终止? I feel like there is less overhead for all the children to just look at the one shared bool, than to send x number of sigints to them. 我觉得所有孩子只需要查看一个共享bool就可以减少开销,而不是向他们发送x个sigints。

Would daemonizing be a better solution? 守护是否会成为更好的解决方案? If so I'd like some help understanding why. 如果是这样,我想帮助理解为什么。

There are a lot of good reasons to go with your solution: 您的解决方案有很多很好的理由:

  • It's easier to think about than signals. 思考比信号更容易。
  • It's got fewer cross-platform issues to deal with. 它需要处理的跨平台问题较少。
  • You've already got code that works this way. 你已经有了以这种方式工作的代码。
  • It makes it easy to add a "graceful shutdown" mechanism if you want to in the future. 如果您希望将来添加“正常关闭”机制,则可以轻松添加。

… and so on. … 等等。

Keep in mind that, unless you can prove to yourself that multiprocessing and the underlying OS primitives, on every platform you care about, are guaranteed to work without synchronization here, you need to put a Lock or something else around every access to the shared bool. 请记住,除非你能够证明你所关心的每个平台上的multiprocessing和底层操作系统原语都保证在没有同步的情况下工作,你需要在每次访问共享bool时放置一个Lock或其他东西。 。 That isn't exactly complicated, but… once you've done that, using, eg, an Event without the shared bool might be even simpler. 这并不是很复杂,但是......一旦你完成了这一点,使用例如没有共享bool的Event可能会更简单。

At any rate, if any of those were your reason, I'd say great, do it that way. 无论如何,如果有任何这些是你的理由,我会说很好,就这样做。 But according to your question, you actually chose this because of performance: 但根据你的问题,你实际上是因为性能而选择了这个:

I feel like there is less overhead for all the children to just look at the one shared bool, than to send x number of sigints to them 我觉得所有孩子只需要查看一个共享bool的开销就少了,而不是向他们发送x个sigints

If that's your reason, you're almost certainly wrong. 如果这是你的理由,你几乎肯定是错的。 The children have to look at the shared bool (and acquire the shared lock!) every time through some loop, while a signal only has to be sent to each child once. 孩子们每次通过一些循环都必须查看共享bool(并获取共享锁!),而信号只需要发送给每个孩子一次。 So, your overhead is almost certainly going to be much higher this way. 所以,你的开销几乎肯定会高得多。

But really, I can't imagine the overhead of sending one signal per child process, or even grabbing an interprocess lock once per loop per process, is anywhere close to a bottleneck in any useful program, so… why does the overhead even matter here in the first place? 但实际上,我无法想象每个子进程发送一个信号的开销,甚至每个进程每个循环抓取一次进程间锁定的开销,在任何有用的程序中都是接近瓶颈的,所以......为什么这里的开销很重要首先? Do what makes the most sense in the most simple way. 以最简单的方式做最有意义的事情。

Since you are careful about who modifies the shared variable, it should be fine. 既然你要小心修改共享变量的人,那应该没问题。

There are many different solutions possible. 有许多不同的解决方案可能。 Eg use a multiprocessing.Event , and have the processes terminate when it is set. 例如,使用multiprocessing.Event ,并在进程设置时终止进程。 Or using multiprocessing.Connection objects (from Pipe). 或者使用multiprocessing.Connection对象(来自Pipe)。 The latter could be used for two-way communication between parent and children. 后者可用于父母与子女之间的双向沟通​​。 Like a signal to the children to stop, followed by a confirmation to the parent. 就像一个给孩子停下来的信号,然后向父母确认。

The people who tell you "don't do this" are wrong. 告诉你“不要这样做”的人是错的。 The point of shared memory is to share memory among multiprocessors and that's exactly what you are doing. 共享内存的关键是在多处理器之间共享内存,而这正是您正在做的事情。

You have a solution that 1) is simple, and 2) works. 你有一个解决方案1)很简单,2)工作。 The signal/daemon approach is 1) really cool and 2) harder to code correctly and 3) much harder to understand. 信号/守护进程方法1)非常酷,2)更难以正确编码和3)更难理解。

The only pitfall I see in your approach is the possibility that a process could see a stale copy of the bool from the CPU's cache, and be delayed slightly in shutting down. 我在你的方法中看到的唯一缺陷是一个进程可能从CPU的缓存中看到bool的陈旧副本,并在关闭时稍微延迟。 There are ways to flush cache to ensure that this is not happening, but you probably don't need them because for most applications the cache flushing happens often enough automatically. 有一些方法可以刷新缓存以确保不会发生这种情况,但是您可能不需要它们,因为对于大多数应用程序来说,缓存刷新经常会自动发生。

Stand your ground. 坚守阵地。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM