Выпуск GIL и смешивание потоков из C и Python

Опубликовано: 12 Апреля, 2022

Выпуск GIL в расширении C:
Укажите код расширения C, и нужно будет выполнять его одновременно с другими потоками в интерпретаторе Python. Для этого Global Interpreter Lock (GIL) должен быть разблокирован и повторно установлен.

Code #1 : Releasing and Reacquiring GIL by inserting following macros

#include "Python.h"
...
PyObject *pyfunc(PyObject *self, PyObject *args)
{
    ...
    Py_BEGIN_ALLOW_THREADS
      
    // Threaded C code. 
    // Must not use Python API functions
    ...
    Py_END_ALLOW_THREADS
    ...
    return result;
}

Смешивание потоков из C и Python:
Учитывая ситуацию, когда данная программа включает сочетание C, Python и потоков. Но некоторые из данных потоков создаются из C вне контроля интерпретатора Python, а также некоторые потоки используют функции в API Python C.

Какое тогда решение?
Если есть сочетание Python, C и потоков, важна правильная инициализация и управление глобальной блокировкой интерпретатора Python (GIL). Приведенный ниже код объясняет ситуацию, их код можно использовать где угодно (до создания потоков) в программе C.

Код №2:

#include <Python.h>
...
if (!PyEval_ThreadsInitialized())
{
    PyEval_InitThreads();
}
...

For any C involving Python objects or the Python C API, GIL needs to be acquired and released first. This can be performed using PyGILState_Ensure() and PyGILState_Release() as in the code given below. Every call to PyGILState_Ensure() must have a matching call to PyGILState_Release().

Code #3 :

...
// Make sure we own the GIL
// Use functions in the interpreter
PyGILState_STATE state = PyGILState_Ensure();
  
...
// Restore previous GIL state and return 
PyGILState_Release(state);
...

Note :
It is not so easy to have so much things going at once, involving a mix of a Python code, C code and their threads. To perform so, it is to be taken care that the interpreter is properly initialized and that C code involving the interpreter has the proper GIL management calls, it all should work.
Also, the PyGILState_Ensure() call does not immediately preempt or interrupt the interpreter. If other code is currently executing, this function will block until that code decides to release the Global Interpreter Lock (GIL).

Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.

Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.