python - 多处理池意外杀死线程

标签 python python-3.x multiprocessing

我在下面的 python 3.6.3 中编写并执行了一个简单的测试程序。它正在具有 4 个内核的机器上执行。

import multiprocessing
import time

def f(num):
  print(multiprocessing.current_process(), num)
  time.sleep(1)
  if (num % 2):
    raise Exception


pool = multiprocessing.Pool(5)

try:
  pool.map(f, range(1,20))
except Exception as e:
  print("EXCEPTION")

pool.close()
pool.join()

pool = multiprocessing.Pool(5) 的输出:

<ForkProcess(ForkPoolWorker-1, started daemon)> 1
<ForkProcess(ForkPoolWorker-2, started daemon)> 2
<ForkProcess(ForkPoolWorker-3, started daemon)> 3
<ForkProcess(ForkPoolWorker-4, started daemon)> 4
<ForkProcess(ForkPoolWorker-5, started daemon)> 5
<ForkProcess(ForkPoolWorker-2, started daemon)> 6
<ForkProcess(ForkPoolWorker-1, started daemon)> 7
<ForkProcess(ForkPoolWorker-4, started daemon)> 8
<ForkProcess(ForkPoolWorker-3, started daemon)> 9
<ForkProcess(ForkPoolWorker-5, started daemon)> 10
<ForkProcess(ForkPoolWorker-2, started daemon)> 11
<ForkProcess(ForkPoolWorker-1, started daemon)> 12
<ForkProcess(ForkPoolWorker-4, started daemon)> 13
<ForkProcess(ForkPoolWorker-3, started daemon)> 14
<ForkProcess(ForkPoolWorker-5, started daemon)> 15
<ForkProcess(ForkPoolWorker-2, started daemon)> 16
<ForkProcess(ForkPoolWorker-1, started daemon)> 17
<ForkProcess(ForkPoolWorker-3, started daemon)> 18
<ForkProcess(ForkPoolWorker-4, started daemon)> 19
EXCEPTION

但是如果我将池的进程数更改为等于或小于我机器上的内核数,则每次调用 f() where num甚至不打印。

使用 pool = multiprocessing.Pool(4) 输出:

<ForkProcess(ForkPoolWorker-1, started daemon)> 1
<ForkProcess(ForkPoolWorker-2, started daemon)> 3
<ForkProcess(ForkPoolWorker-3, started daemon)> 5
<ForkProcess(ForkPoolWorker-2, started daemon)> 7
<ForkProcess(ForkPoolWorker-1, started daemon)> 9
<ForkProcess(ForkPoolWorker-3, started daemon)> 11
<ForkProcess(ForkPoolWorker-3, started daemon)> 13
<ForkProcess(ForkPoolWorker-1, started daemon)> 15
<ForkProcess(ForkPoolWorker-2, started daemon)> 17
<ForkProcess(ForkPoolWorker-1, started daemon)> 19
EXCEPTION

我不明白为什么这些进程会被杀死,尤其是当函数中的 print 语句之后才抛出异常时。我真的不明白为什么只有当池中的进程数等于或小于机器上的内核数时才会发生这种情况。

最佳答案

引用multiprocessing.Pool.map的规范 你可以看到一个可选参数 chunksize,如果你将它指定为 1,即 pool.map(f, range(1,20), 1),那么你会 yield预期的结果。

如果您增加 block 大小(例如 = 6),您可能会看到:

<SpawnProcess(SpawnPoolWorker-1, started daemon)> 1
<SpawnProcess(SpawnPoolWorker-4, started daemon)> 7
<SpawnProcess(SpawnPoolWorker-3, started daemon)> 13
<SpawnProcess(SpawnPoolWorker-2, started daemon)> 19

这表明将 chunksize 的任务分配给 Pool 中的单个线程,当您在每个线程中引发异常时,当然不会执行剩余 chuck 中的任务。

从这里你可以知道 chunksize 的默认值在你的情况下是 2,这个变量存在的原因,很容易看出,是为了减少新线程的数量需要初始化(当您有适当的 block 大小时,这可能会节省资源和处理时间)。

关于python - 多处理池意外杀死线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54136598/

相关文章:

python - 在Python中重命名文件: WindowsError: [Error 2] The system cannot find the file specified

python - 在 re 或 str.split() python 中使用括号作为分隔符

python-3.x - macOS 中 Python 子进程标准输出中出现带有 0xc3 的 UnicodeDecodeError

python - Python 中的上下文变量

java - 在进程关闭之前读取所有进程输出

c - 我已经使用 C 程序实现了简单的 bash 像 shell,但它没有按预期工作

python - 从 Django 管理员调试

python - 根据字典中的值将键写入单独的csv

python - 如何使用带有多个参数的多处理 pool.map

python - 来自整数列表列表的 Scipy 稀疏矩阵