LaTeX957300 views
小学算数1194618 views
世界の国560595 views
中学英語808712 views
教育148875 views
小学社会308636 views
中学社会667106 views
英語607877 views
高校倫理1433119 views
りんご192546 views
Help
Tools

English

Python の ThreadPoolExecutor は max_workers を適切に指定しないとゾンビのプロセスが生まれるかもしれない

注意:この記事は情報に誤りがあるかもしれない

Python の ThreadPoolExecutor は基本的に with 内で動かすが、実際のスレッド数を超える値を max_workers に指定すると予想外のことが起きる。

例えば 3 つのプロセスを並列化したいとき、max_workers を 4 にすると、4 - 3 = 1 のゾンビ・プロセスが生まれる。全体のプログラムがデーモン化されている場合、この 1 個のスレッドが with で回収されない。

例えば gunicorn で動かす Django または Flask のプログラム内に ThreadPoolExecutor で並列化した関数があるとする。この ThreadPoolExecutor で max_workers を関数の数よりも多く設定していると

13474  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13510  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13511  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13512  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13513  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13514  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13549  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13550  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13551  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13552  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13553  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13578  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13579  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13580  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13581  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13582  gunicorn --bind 127.0.0.1:8080 main:app --daemon
13586  gunicorn --bind 127.0.0.1:8080 main:app --daemon

などとなる。これらのゾンビ・デーモンはシグナルで強制終了されない限り消えない。

デーモンになっていないプログラム、例えばローカルで動かしている Flask では max_workers の値にかかわらず、余ったスレッドは with で消される(たぶん)。

また ThreadPoolExecutor は OS に依存するため、実際は Pebble などを使う。Python の並列化でシグナルを直接扱っているソースコードをよく見かけるが、たぶん避けたほうがいい。