LoginSignup
2
0

More than 3 years have passed since last update.

"AssertionError: daemonic processes are not allowed to have children"について

Posted at

環境

  • Python 3.8.6
  • Xubuntu 18.04

問題

multiprocessing.pool.Poolを使って、並列実行しています。
並列実行しているcube_for_row関数内で、さらに並列実行したら、「AssertionError: daemonic processes are not allowed to have children」が発生しました。

main.py
from typing import List
import multiprocessing


def cube(value: float) -> float:
    return value * value * value


def cube_for_row(row: List[float]) -> List[float]:
    with multiprocessing.Pool() as pool:
        return pool.map(cube, row)


def cube_for_matrix(matrix: List[List[float]], is_parallel:bool) -> List[List[float]]:
    if is_parallel:
        with multiprocessing.Pool() as pool:
            return pool.map(cube_for_row, matrix)
    else:
        return [cube_for_row(row) for row in matrix]


def main():
    matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
    result1 = cube_for_matrix(matrix, False)
    print(result1)
    # OK
    result2 = cube_for_matrix(matrix, True)
    print(result2)
    # NG
multiprocessing.pool.RemoteTraceback: 
"""
Traceback (most recent call last):
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/multiprocessing/pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/multiprocessing/pool.py", line 48, in mapstar
    return list(map(*args))
  File "/home/vagrant/Downloads/run.py", line 8, in cube_for_row
    with multiprocessing.Pool() as p:
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/multiprocessing/context.py", line 119, in Pool
    return Pool(processes, initializer, initargs, maxtasksperchild,
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/multiprocessing/pool.py", line 212, in __init__
    self._repopulate_pool()
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/multiprocessing/pool.py", line 303, in _repopulate_pool
    return self._repopulate_pool_static(self._ctx, self.Process,
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/multiprocessing/pool.py", line 326, in _repopulate_pool_static
    w.start()
  File "/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/multiprocessing/process.py", line 118, in start
    assert not _current_process._config.get('daemon'), \
AssertionError: daemonic processes are not allowed to have children
"""

原因

エラーメッセージは「デーモンプロセスは子プロセスを持てない」と言っています。
multiprocessing.pool.Poolに渡している関数は、デーモンプロセスで実行されているようです。

multiprocessing.Process.daemon のドキュメントをには、「デーモンプロセスは子プロセスを作成できない」と記載されています。

デーモンプロセスであるかのフラグであり、ブール値です。この属性は start() が呼び出される前に設定されている必要があります。
初期値は作成するプロセスから継承します。
あるプロセスが終了するとき、そのプロセスはその子プロセスであるデーモンプロセスすべてを終了させようとします。

デーモンプロセスは子プロセスを作成できないことに注意してください。もし作成できてしまうと、そのデーモンプロセスの親プロセスが終了したときにデーモンプロセスの子プロセスが孤児になってしまう場合があるからです。さらに言えば、デーモンプロセスはUnix デーモンやサービスでは なく 通常のプロセスであり、非デーモンプロセスが終了すると終了されます (そして join されません)。

暫定的な解決方法1

「AssertionError」なので無視することもできます。

$ python -O main.py
[[1, 8, 27, 64], [125, 216, 343, 512], [729, 1000, 1331, 1728]]

ただ無視すると、ゾンビプロセスが生まれてしまうようです。

暫定的な解決方法2

デーモンプロセスの場合は並列処理しないようにします。

def cube_for_row(row: List[float]) -> List[float]:
    """並列実行できるなら並列実行する"""
    process = multiprocessing.current_process()
    if process.daemon:
        return [cube(v) for v in row]
    else:
        with multiprocessing.Pool() as pool:
            return pool.map(cube, row)


2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0