Потокобезопасность#

NumPy поддерживает использование в многопоточном контексте через threading модуль в стандартной библиотеке. Многие операции NumPy освобождают GIL, поэтому, в отличие от многих ситуаций в Python, можно улучшить параллельную производительность, используя многопоточный параллелизм в Python.

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

Возможно совместное использование массивов NumPy между потоками, но необходимо проявлять крайнюю осторожность, чтобы избежать проблем с потокобезопасностью при изменении массивов, которые разделяются между несколькими потоками. Если два потока одновременно читают и записывают в один и тот же массив, в лучшем случае они произведут несогласованные, гонковые результаты, которые не воспроизводимы, не говоря уже о корректности. Также возможно аварийное завершение работы интерпретатора Python, например, при изменении размера массива, пока другой поток читает из него для вычисления операции ufunc.

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

Обратите внимание, что операции, которые не освобождение GIL не приведет к повышению производительности от использования threading модуль, и вместо этого может быть лучше использовать multiprocessing. В частности, операции над массивами с dtype=np.object_ не освобождают GIL.

Контекстно-локальное состояние#

NumPy поддерживает некоторое состояние для ufuncs на основе контекстно-локальной области, что означает, что каждый поток в многопоточной программе или задача в программе asyncio имеет свою собственную независимую конфигурацию numpy.errstate (см. Обработка ошибок с плавающей точкой), и Параметры форматирования текста.

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

Свободнопоточный Python#

Новое в версии 2.1.

Начиная с NumPy 2.1 и CPython 3.13, NumPy также имеет экспериментальную поддержку для сред выполнения Python с отключенным GIL. См. https://py-free-threading.github.io для получения дополнительной информации об установке и использовании свободнопоточный Python, а также информация о поддержке в библиотеках, зависящих от NumPy.

Поскольку свободнопоточный Python не имеет глобальной блокировки интерпретатора для сериализации доступа к объектам Python, появляется больше возможностей для потоков изменять общее состояние и создавать проблемы безопасности потоков. В дополнение к ограничениям по блокировке ndarray объект, упомянутый выше, это также означает, что массивы с dtype=np.object_ не защищены GIL, создавая гонки данных для python объектов, которые невозможны вне свободнопоточного python.

Поддержка многопоточности в C-API#

Для разработчиков, пишущих C-расширения, взаимодействующие с NumPy, несколько частей Документация по C-API массивов предоставлять подробную информацию о соображениях многопоточности.

Смотрите также#