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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

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

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

Python

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

Q&A

1回答

1316閲覧

シリアル通信の読み取り待機中はGILが解放されるのか

panpa-su

総合スコア0

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

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

シリアルポート

シリアルポートは一度に一ビットごと移行される物理的なインターフェイスです。一般的には、9ピンのd-subコネクタであるRS-232を指します。

Python

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

1グッド

0クリップ

投稿2021/07/13 06:05

編集2021/07/13 09:44

PythonはGILで実装されていて、マルチスレッドにしても実際には単一のスレッドしか実行されないことが知られています。
ただ、調べてみるとIOバウンド時はこのGILが解放されるということを知ったのですが、**シリアル通信の読み取り待機時(pyserialのread()で待機している時)**にもGILは解放されるのでしょうか。

以下のような状況の時です。

Python

1import serial 2with serial.Serial('COM3', 115200, timeout=100) as ser: # timeoutするまでの時間を100sに設定 3 x = ser.read() # COM3から100秒間応答なし。この100秒の間はGILが解放されている?

ネットでgil io-bound exampleとかで調べてみたのですがrequestsを使ったhttp通信についての例しか載っていなかったので他に調べる方法がなくこちらで質問させていただきました。

ozwk👍を押しています

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

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

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

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

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

guest

回答1

0

❌ マルチスレッドにしても実際には単一のスレッドしか実行されない
❌ IOバウンド時はこのGILが解放されるということを知った

前提でされている状況の説明が何かおかしいです。
(意図は汲み取れますが、説明が誤解を招きそうな表現。多分、ニュアンスの問題)

IOバウンドな処理では、通常は、そもそもGILが問題になる事はありません。
GILの心配自体が杞憂です。

前提として、恐らく共有できていそうな認識では

非同期処理I/O boundCPU bound
Multithreadox (GIL)
Multiprocessingoo

大筋の理解では、例えば、プログラムを組む際に
マルチスレッドかマルチプロセスかで悩んでいる、みたいな状況で
IOバウンド/CPUバウンドを判別の基準にする、は妥当な判断です。

Pythonのコードのみを対象とした場合は、大抵の場合正しいのですが、
マルチスレッドで GIL を回避 という選択肢もあります。


シリアル通信の読み取り待機時(pyserialのread()で待機している時)にもGILは解放されるのでしょうか。

GIL が掛かるのは、インタープリタでのバイトコードの実行単位でのロックなので、
Pythonのコードではなく、バイトコードやC拡張の内部のコード単位で論じる必要があります。

GILの理解が目的で質問されてる場合を想定して、細かい点ですが

IOバウンドな処理で、待機中であればPythonのコードを実行する必要はないので、
その間は GIL を解放する事ができます(ニュアンス的には、解放しても良い)。
しかし、これは実装次第であり、因果関係が、IOバウンドな処理だから解放されるという訳ではありません。
GIL を解放しない IO処理自体は成立します。(大抵、不具合扱いされますが)

pyserialのread()で待機している時

read() 内には複数の処理があります。
プラットフォーム毎にも実装が異なるので、実際にコードを書いて調べて見ましょう。

posix の場合、select/os.read を使った読み出し。実装は C 拡張。
https://github.com/python/cpython/blob/main/Python/fileutils.c

Release the GIL to call read(). The caller must hold the GIL.

例えば、windows の場合だと ctypes.WinDLL を経由し外部関数を呼び出してます。
WinDLL では、呼び出し前後で GIL が解放・獲得されます。

https://docs.python.org/ja/3/library/ctypes.html#ctypes.WinDLL

これらのライブラリがエクスポートするどの関数でも呼び出す前に Python GIL (global interpreter lock) は解放され、後でまた獲得されます。

こちらのケースでは、IOバウンドだから解放されるわけではなく、
外部関数呼び出しは、Pythonのオブジェクトを直接参照することが出来ないので、
一律でGILは解放してから呼び出すようになってます。

但し、read() 内にも複数の処理があり、Pythonのオブジェクトを扱う場面(バッファリングの部分等)では
依然として GIL を獲得しています。→ read()内部の実装詳細単位でみる必要がある。

結論ですが、read() 関数全体で見た場合、GILを獲得する部分もありますが、
CPU負荷では無い為、GILが問題(パフォーマンス上のボトルネック)となる事はありません。


参考

Python is NOT Single Threaded (and how to bypass the GIL)

  • Python is a single threaded language ... no
  • If you want to use multiple cores in python,
    don't use threading and use multiprocessing instead ... no

単純に「正解」「間違い」という意図ではありませんが、
「誤解」されやすい話題として取り上げられてます。

「単一のスレッドしか実行されない」は、流石に言葉不足で、誤解を招く表現だと思います。
2つ目の項目については、マルチスレッドでも CPUバウンドな処理をする際に
GIL を回避する方法がある、という主旨です。

他にも、GIL対策としては、公式にサブインタープリター単位のロックを導入する取り組みもありますが、
まだあまり実用的な段階ではない印象。

投稿2021/07/15 05:06

編集2021/07/16 01:21
teamikl

総合スコア8664

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問