Nano Hash - криптовалюты, майнинг, программирование

Параллелизм: на расширения Python, написанные на C/C++, влияет глобальная блокировка интерпретатора?

Одной из самых сильных сторон Python является простота написания расширений C и C++ для ускорения выполнения частей кода, интенсивно использующих процессор. Могут ли эти расширения избежать глобальной блокировки интерпретатора или они также ограничены GIL? Если нет, то эта «легкость расширения» является даже более убийственной функцией, чем я думал ранее. Я подозреваю, что ответ не будет простым «да» или «нет», но я не уверен, поэтому я задаю вопрос здесь, в StackOverflow.

16.03.2009

Ответы:


1

Да, вызовы расширений C (подпрограммы C, вызываемые из Python) по-прежнему подпадают под действие GIL.

Однако вы можете вручную освободить GIL внутри вашего расширения C, если вы будете осторожны, чтобы повторно подтвердить его, прежде чем вернуть управление виртуальной машине Python.

Для получения информации взгляните на макросы Py_BEGIN_ALLOW_THREADS и Py_END_ALLOW_THREADS: http://docs.python.org/c-api/init.html#thread-state-and-the-global-interpreter-lock

16.03.2009
  • Можете ли вы взглянуть на этот вопрос и дайте мне знать, что вы думаете? stackoverflow.com/questions/53855880/ 19.12.2018

  • 2

    Расширения C/C++ для Python не связаны GIL. Тем не менее, вам действительно нужно знать, что вы делаете. http://docs.python.org/c-api/init.html:

    Глобальная блокировка интерпретатора используется для защиты указателя на текущее состояние потока. При снятии блокировки и сохранении состояния потока указатель текущего состояния потока должен быть извлечен до того, как блокировка будет снята (поскольку другой поток может немедленно получить блокировку и сохранить свое состояние потока в глобальной переменной). И наоборот, при получении блокировки и восстановлении состояния потока блокировка должна быть получена до сохранения указателя состояния потока.

    Почему я так подробно рассказываю об этом? Потому что, когда потоки создаются из C, они не имеют глобальной блокировки интерпретатора и не имеют для них структуры данных состояния потока. Такие потоки должны запустить себя, сначала создав структуру данных состояния потока, затем получив блокировку и, наконец, сохранив свой указатель состояния потока, прежде чем они смогут начать использовать API Python/C. По завершении они должны сбросить указатель состояния потока, снять блокировку и, наконец, освободить свою структуру данных состояния потока.

    16.03.2009
  • Возможно, вы думаете о коде C, который встраивает Python, а не о расширениях C? Когда поток в интерпретаторе Python вызывает ваше расширение C, он по-прежнему удерживает GIL, если вы не освободите его специально. В процитированном вами разделе речь идет о потоках, созданных вне Python. 16.03.2009
  • Я думаю, что ОП неоднозначен. Вы можете запустить поток в расширении C, которое не связано с GIL. 16.03.2009

  • 3

    Проверьте Cython, он имеет синтаксис, аналогичный Python, но с несколькими конструкциями, такими как «cdef», быстрыми функциями доступа к numpy и оператором «with nogil» (который делает то, что он говорит).

    09.04.2009

    4

    Если вы пишете расширение на C++, вы можете использовать RAII для простого и разборчивого написания кода, управляющего GIL. Я использую эту пару структур RAII:

    namespace py {
    
        namespace gil {
    
            struct release {
                PyThreadState* state;
                bool active;
    
                release()
                    :state(PyEval_SaveThread()), active(true)
                    {}
    
                ~release() { if (active) { restore(); } }
    
                void restore() {
                    PyEval_RestoreThread(state);
                    active = false;
                }
            };
    
            struct ensure {
                PyGILState_STATE* state;
                bool active;
    
                ensure()
                    :state(PyGILState_Ensure()), active(true)
                    {}
    
                ~ensure() { if (active) { restore(); } }
    
                void restore() {
                    PyGILState_Release(state);
                    active = false;
                }
            };
    
        }
    
    }
    

    … позволяет переключать GIL для данного блока (семантический способ, который может показаться смутно знакомым любому поклоннику контекстного менеджера Pythonista):

    PyObject* YourPythonExtensionFunction(PyObject* self, PyObject* args) {
    
        Py_SomeCAPICall(…);     /// generally, if it starts with Py* it needs the GIL
        Py_SomeOtherCall(…);    /// ... there are exceptions, see the docs
    
        {
            py::gil::release nogil;
            std::cout << "Faster and less block-y I/O" << std::endl
                      << "can run inside this block -" << std::endl
                      << "unimpeded by the GIL";
        }
    
        Py_EvenMoreAPICallsForWhichTheGILMustBeInPlace(…);
    
    }
    

    … Действительно, лично я также нахожу простоту расширения Python и уровень контроля над внутренними структурами и состоянием убийственной функцией.

    08.04.2016
  • Н.Б. если вы используете какие-либо эти вызовы API, вы сначала захотите сделать первоначальный вызов PyEval_InitThreads() (например, в функции инициализации вашего модуля), прежде чем пытаться выполнить какое-либо ручное управление GIL. 08.04.2016
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..