Встраивание нескольких суб-интерпретаторов Python в программу на C - PullRequest
0 голосов
/ 29 декабря 2018

Я пишу C-программу, которая порождает несколько C-потоков, с одним суб-интерпретатором Python на каждый поток.Подинтерпретаторы не имеют общих переменных Python, они изолированы друг от друга.(Они имеют доступ только для чтения к общему PyObject (неизменяемому), который предоставляется из функции main () в программе на C).

Возможно ли это в Python 3.7 или 3.8, без совместного использования GIL междусуб-переводчики?

Вот псевдокод того, что я пытался:

void *spawnInterpreter(void* p) {
    …
    PyThreadState* save_tstate = PyThreadState_Swap(NULL);
    PyThreadState* tstate = Py_NewInterpreter();
    PyThreadState_Swap(save_tstate);

    //do some Python work (with variables that are NOT shared with other thread’s sub-interpreter
    PyRun_SimpleString( . . .);
    . . . 
}


int main() {
...
    pthread_create(&thread1, NULL, spawnInterpreter,  “in1”);
    pthread_create(&thread2, NULL, spawnInterpreter, "in2");
...
}

Я мог бы заставить это работать в 3.6 (без получения GIL или управления PyThreadState в потоках C),но в Python 3.7 я получаю:

[New Thread 0x7ffff5f78700 (LWP 16392)]
Fatal Python error: drop_gil: GIL is not locked

1 Ответ

0 голосов
/ 26 апреля 2019

К сожалению, субинтерпретаторы все еще разделяют GIL в 3.7 и 3.8.Это то, что я лично работаю над изменением.Смотрите PEP 554 и мой многоядерный проект Python .На следующей неделе я также выступаю с докладом на PyCon , в котором будет подробно освещена эта тема.

Я надеялся сделать это возможным в Python 3.8, но он выглядит более вероятным для 3.9.с этой точки зрения.Основная проблема заключается в том, что среда выполнения C-API и CPython не является поточно-ориентированной.Хотя большая часть C-API и среды выполнения могут переключаться на использование GIL для каждого интерпретатора, в этом сценарии придется изменить и другие вещи:

  • некоторые глобальные ресурсы процесса должны управляться более осторожно безGIL (например, env vars, дескрипторы файлов)
  • существует глобальное состояние времени выполнения, которое интерпретаторы должны продолжать совместно использовать, так что многое должно быть защищено глобальной блокировкой (хотя та, которая будет , а не * 1015)* необходимо заблокировать цикл вычисления байт-кода Python)
  • некоторые глобальные состояния времени выполнения необходимо перевести в состояние для каждого интерпретатора (например, GC, распределители памяти, предупреждения)
  • объектам потребуетсябыть строго для интерпретатора (пока), поэтому C-API должен быть строгим, чтобы объекты не могли пересекать границу интерпретатора
  • части C-API, не относящиеся к контексту интерпретатора, должны изменитьсябольше не требуется удерживать GIL

Проблема решаема, но требуется время, чтобы применить необходимую осторожность при работе oтакой критический код.Следовательно, вероятная цель 3.9.


Несмотря на это, я благодарен, что вы разместили здесь.Большая часть моих усилий была сосредоточена на воздействии на код Python, а не на C-API (например, на встраивающие устройства).Так что отзывы о том, как мой проект связан с использованием субинтерпретаторов через C-API, очень полезны.Например, одна вещь, о которой вы мне напомнили, заключается в том, что создание субинтерпретаторов через C-API немного отличается от аналога в PEP 554. Это необходимо рассмотреть более тщательно.Кроме того, PEP 554 практически не предоставляет никаких своих дополнений в C-API.Это, вероятно, хорошо, но взаимодействие с каналами из C-API может быть полезным в краткосрочной перспективе.

...