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

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

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

Возможно совместное использование массивов NumPy между потоками, но необходимо проявлять крайнюю осторожность, чтобы избежать проблем с потокобезопасностью при изменении массивов, которые разделяются между несколькими потоками — пожалуйста, ознакомьтесь с документацией NumPy по потокобезопасности для получения дополнительных сведений. Функции SciPy не будут изменять массивы, которые пользователь передаёт, если только функция явно не документирует, что она это делает (что редко). Следовательно, вызов функций SciPy в многопоточном режиме на одном и том же массиве NumPy безопасен.

Хотя большая часть SciPy состоит из функции, требуется больше осторожности с классы и структуры данных.

Классы, которые имеют состояние, такие как некоторые объекты интегрирования и интерполяции в scipy.integrate и scipy.interpolate, обычно устойчивы к параллельным вызовам. Они либо принимают параллельные вызовы, либо вызывают информативную ошибку. Например, scipy.integrate.ode может вызвать IntegratorConcurrencyError для методов интегрирования, которые не поддерживают параллельное выполнение.

SciPy предлагает несколько структур данных, а именно разреженные массивы и матрицы в scipy.sparse, и k-D деревья в scipy.spatial. Эти структуры данных являются в настоящее время не потокобезопасно. Пожалуйста, избегайте, в частности, операций, изменяющих структуру данных, таких как присваивание элементов или срезов в разреженных массивах, пока данные используются несколькими потоками. Это может привести к повреждению данных, сбоям или другому нежелательному поведению.

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

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

Добавлено в версии 1.15.0.

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

Поскольку свободнопоточный Python не имеет глобальной блокировки интерпретатора (GIL) для сериализации доступа к объектам Python, появляется больше возможностей для потоков изменять общее состояние и создавать проблемы потокобезопасности. Весь функционал SciPy тестируется на использование из параллельных потоков, однако мы ожидаем, что могут быть ещё не обнаруженные проблемы - если вы столкнётесь с проблемой, пожалуйста, проверьте Проблемы GitHub с меткой free-threading и открыть новую проблему, если она еще не существует для функции, которая работает некорректно.