質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

2121閲覧

joblibの並列化関数を利用する場合、並列実行される関数の中のprint()文が?

insecticide

総合スコア315

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/06/11 23:57

編集2022/06/11 23:59

joblibの並列化関数を利用する場合、並列実行される関数の中のprint()文が全部出力できなくなります。
原因は何でしょうか。
この場合中間結果を確認したい場合どうすれば良いのでしょうか。

環境 Google Colaboratory

実行文の例:

Python

1Parallel(n_jobs=-1,verbose=11)(delayed(myFunc)(x) for x in range(100) )

myFunc()中のprint()文が全部自動的に無効になってしまいました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

joblib については詳しく知りませんが、サブプロセス側でのprint デバッグは
logging モジュールの QueueHandler 等を用いて、メインプロセス側でまとめて出力するように構成します。
⇛ サンプルコードは、ロギングクックブックの複数プロセスからのログを参照してください。

問題の原因は、サブプロセスの利用方法次第では、
実行環境で設定された python上のsys.stdout 等のリダイレクトが適応されない、という問題です。
google colab 以外にも IDE 内の実行でも同様の症状が確認されています。
(解決可能な不具合ではなく、実装による制限のようです)

Pararell の引数に backend="multithread" を指定すると、print() の表示自体は出来るようになりますが、
マルチプロセスでは実行タイミングが保証されない為、ログ出力が崩れる原因にも成りかねません。

デバッグで一時的に出力が見たいだけの場合等は、printが手軽かもしれませんが、
マルチスレッド・マルチプロセスではlogging モジュールをお勧めします。

実際の用途を想定すると
外部ライブラリ内で logging モジュールを使っている場合もあるので、
例えばサブプロセス側でそういったライブラリを使う場合、
正しく logging の設定を構成できないと、ログ出力に気付かない
もしくは、ログが壊れる、といったことが起こる可能性があります。


関連:

FileHandler の代わりに StreamHandler を使うと notebook 内に出力できますが、
ログが大量になる時に、便利そうな記事を見つけたので関連として紹介。
他、Google Colab (Jupyter 環境等) での logging モジュール利用の注意点もあります。

投稿2022/06/12 08:58

teamikl

総合スコア8817

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Google colabで試した結果を載せます。
Backendがloky以外なら表示できます。
※Stackoverflowにて記事発見。「lokyモジュールがそうさせている」とのこと。

後はお好みでどうぞ。

Python3

1import joblib 2 3# # backend: multithread, expected one of ['loky', 'multiprocessing', 'sequential', 'threading'] 4# back_end = "loky" # 表示されない。割愛した時のデフォルトの引数 5# back_end = "multiprocessing" # 表示される。並列処理の特性上、必ず順番通りになるわけではない。 6# back_end = "sequential" # 表示される。joblibのガワはかぶっていても並列処理はしていないので、必ず順番通りに表示される。 7back_end = "threading" # 表示される。並列処理の特性上、必ず順番通りになるわけではない(はずなのに、Google Colabだと順番通りに…)。 8 9def myFunc(val): 10 print("Child:",val,flush=True) # 質問事項の検証用 11 return val 12 13ans = joblib.Parallel(n_jobs=-1,verbose=0,backend=back_end)(joblib.delayed(myFunc)(x) for x in range(100) ) 14print("ans:",ans) 15

投稿2022/06/12 01:47

編集2022/06/12 22:35
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

insecticide

2022/06/12 12:35

>手元の環境ではちゃんと表示されています。 Google Colaboratory も大丈夫でしょうか?
退会済みユーザー

退会済みユーザー

2022/06/12 22:22 編集

Windows x Python3.6では確認しました。 Google Colabで試したところ途中経過はprintされませんでした。 引数指定を明示的にすると表示できるようになりました。回答を修正します。
insecticide

2022/06/14 09:09

お返事ありがとうございます。 >Backendがloky以外なら表示できます。 自分の印象ではBackendがlokyであるのはお決まりのようなもんですけれども?
退会済みユーザー

退会済みユーザー

2022/06/14 22:28 編集

> 自分の印象ではBackendがlokyであるのはお決まりのようなもんですけれども? 「お決まり」のモジュールなのにこんなすぐわかりそうなバグがすり抜けてしまった理由は、stackoverflowのコメントにありますが、恐らくOSやモジュールのバージョンの微妙な関係性で成り立っているバグだから、と私は思っています。 しかも、その「お決まり」のlokyが参照する(恐らく内部でsubprocessして並列処理させる時の依存関係にある)ipythonモジュールがprintしようとすると、(Jupyter notebookやGoogle colabの表示回りという限定環境において)表示されなくなるというわけです。だから、「お決まり」の引数指定なし=標準でPrintされない状態が発生していると思っています。Ipythonの作者がWindwos環境でしかデバグしなかっただとか、バグをすり抜ける特定のバージョンのモジュールを使っていた、とかそっち系の話と思います。 その上に、「どうせ引数に『お決まり』のlokyではなく、multiprocessingやthreadingを指定すれば回避できるんだろ?」という気持ちが使用者界隈に横たわっていて、バグレポートが出されていても放置され続けている、バグレポートも止まっている、が恐らくが実態です。 ―ーという状況下にありながら、それでもなお > 自分の印象ではBackendがlokyであるのはお決まりのようなもんですけれども? というように、「お決まり」のくせいにおかしいじゃないか、ということでしたら以下のgithubのリポジトリでバグレポートとソースコードのどの辺がおかしいかソースコードのどこを直せばいいといった指摘すれば直してもらえるのではないでしょうか。 https://github.com/ipython/ipykernel/issues/402
guest

0

自己解決

マルチプロセスの場合、print 文の表示がタイミング的乱れがあるという印象でした。

投稿2022/06/13 08:34

編集2022/06/13 09:02
insecticide

総合スコア315

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

teamikl

2022/06/13 11:46 編集

タイミングに乱れがある(非同期の特性)と 本題(表示されない問題の原因:サブプロセスに標準出力のリダイレクトが伝搬されていない)は別問題です。 一応、表示させるだけなら backend="multiprocessing" 指定だけでも対応可能です。 (但し、タイミング問題は潜在的な問題として残ります)
insecticide

2022/06/13 12:54

> backend="multiprocessing" 指定だけでも対応可能です。 これは有難いですね。 試してみたらOKです❣ 本当にありがとうございました。
退会済みユーザー

退会済みユーザー

2022/06/13 15:06

print(○○,flush=True)でPython側でのラグは減らせます。 が、Multiprosessingは同時性を犠牲にしてその代わりに並列化して早く済ませる処理です。タイミングを期待するものではないです。完全に揃えるならback_end = "sequential"で並列処理を止める必要があります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問