4

Python インタープリターにはグローバル インタープリター ロックがあり、拡張機能はマルチスレッド環境でグローバル インタープリター ロックを取得する必要があると理解しています。しかし、Boost.Python HOWTO ページには、拡張関数は GIL を解放し、終了時に再取得する必要があると書かれています。

ここで推測する誘惑に抵抗したいので、次のシナリオでGILロックパターンがどうあるべきかを知りたいです:

  1. 拡張機能は Python から呼び出されます (おそらく Python スレッドで実行されます)。
  2. そして、拡張機能のバックグラウンド スレッドが関数にコールバックしPy_*ます。

最後の質問は、なぜリンクされたドキュメントが GIL を解放して再取得する必要があると述べているのですか?

4

1 に答える 1

6

Whenever Python is interpreting bytecode the GIL is being held by the currently running thread. No other Python thread can run until it manages to acquire the GIL.

When the interpreter has called into native code that code has two options regarding the GIL:

  1. It could do nothing at all.
  2. It could release the GIL while it works and then reacquire it before returning to Python

If the native code makes a lot of calls back to Python's runtime it should take option 1: you can never call Python's runtime safely unless you hold the GIL (with a few exceptions such as making the call to acquire the GIL if you don't have it).

If the native code does a lot of work which doesn't involve Python in any way then you can use option 2: as soon as you release the GIL Python will be able to schedule another Python thread so you get some parallelism. If you don't release the GIL then none of Python's other threads can execute while your Boost code is running: that's why the docs tell you to release and reacquire the GIL.

If you go this way then you must be careful to make all your access to Py_* functions before you release the GIL or after you reacquire it. This may mean you have to make local copies of data as you cannot safely access Python data types such as list or dictionary elements while the GIL is released.

If your Boost code needs to call back into Python while the GIL is released then you need to acquire the GIL, make the call, release the GIL. Try to avoid making such calls from threads that weren't created by Python as they need additional work to be able to acquire the GIL.

于 2010-05-13T12:23:32.717 に答える