Примечания к выпуску NumPy 2.1.0#

NumPy 2.1.0 предоставляет поддержку предстоящего выпуска Python 3.13 и прекращает поддержку Python 3.9. В дополнение к обычным исправлениям ошибок и обновленной поддержке Python, это помогает вернуться к обычному циклу выпусков после длительной разработки версии 2.0. Основные моменты этого выпуска:

  • Поддержка стандарта array-api 2023.12.

  • Поддержка Python 3.13.

  • Предварительная поддержка свободнопоточного Python 3.13.

Версии Python 3.10-3.13 поддерживаются в этом выпуске.

Новые функции#

Новая функция numpy.unstack#

Новая функция np.unstack(array, axis=...) была добавлена, которая разделяет массив на кортеж массивов вдоль оси. Она служит обратной к numpy.stack.

(gh-26579)

Устаревшие функции#

  • The fix_imports именованный аргумент в numpy.save устарело. Начиная с NumPy 1.17, numpy.save использует протокол pickle, который больше не поддерживает Python 2, и игнорировал fix_imports ключевое слово. Это ключевое слово сохранено только для обратной совместимости. Теперь оно устарело.

    (gh-26452)

  • Передача нецелочисленных входных данных в качестве первого аргумента bincount теперь устарел, потому что такие входные данные молча приводятся к целым числам без предупреждения о потере точности.

    (gh-27076)

Устаревшие устаревания#

  • Скаляры и 0D массивы запрещены для numpy.nonzero и numpy.ndarray.nonzero.

    (gh-26268)

  • set_string_function внутренняя функция была удалена и PyArray_SetStringFunction был заглушен.

    (gh-26611)

Изменения в C API#

API-символы теперь скрыты, но настраиваемы#

NumPy теперь по умолчанию скрывает символы API, которые он добавляет, чтобы разрешить все использования API NumPy. Это означает, что по умолчанию вы не можете динамически получать API NumPy из другой библиотеки (это никогда не было возможно в Windows).

Если вы сталкиваетесь с ошибками линковки, связанными с PyArray_API или PyArray_RUNTIME_VERSION, вы можете определить NPY_API_SYMBOL_ATTRIBUTE чтобы отказаться от этого изменения.

Если у вас возникают проблемы из-за того, что вышестоящий заголовок включает NumPy, решение состоит в том, чтобы убедиться, что вы #include "numpy/ndarrayobject.h" перед их заголовком и импортируйте NumPy самостоятельно на основе including-the-c-api.

(gh-26103)

Многие прокладки удалены из npy_3kcompat.h#

Многие старые обёртки и вспомогательные функции были удалены из npy_3kcompat.h. Если вам понадобятся эти функции, включите предыдущую версию файла в свою кодовую базу.

(gh-26842)

Новый PyUFuncObject field process_core_dims_func#

Поле process_core_dims_func был добавлен в структуру PyUFuncObject. Для обобщённых универсальных функций это поле может быть установлено в функцию типа PyUFunc_ProcessCoreDimsFunc которая будет вызываться при вызове ufunc. Она позволяет автору ufunc проверять, что основные размерности удовлетворяют дополнительным ограничениям, и устанавливать размеры основных размерностей вывода, если они не были предоставлены.

(gh-26908)

Новые возможности#

Предварительная поддержка свободнопоточного CPython 3.13#

CPython 3.13 будет доступен как экспериментальная сборка с свободными потоками. См. https://py-free-threading.github.io, PEP 703 и Примечания к выпуску CPython 3.13 для получения более подробной информации о свободнопоточном Python.

NumPy 2.1 имеет предварительную поддержку свободнопоточной сборки CPython 3.13. Эта поддержка была включена путём исправления ряда проблем с потокобезопасностью C в NumPy. До NumPy 2.1 NumPy использовала большое количество глобальных статических переменных C для хранения кэшей времени выполнения и другого состояния. Мы либо реорганизовали, чтобы избежать необходимости глобального состояния, преобразовали глобальное состояние в локальное для потока состояние, либо добавили блокировки.

Поддержка свободнопоточного Python не означает, что NumPy является потокобезопасным. Доступ только для чтения к общему ndarray должен быть безопасным. NumPy предоставляет общее изменяемое состояние, и мы не добавили никакой блокировки к самому объекту массива для сериализации доступа к общему состоянию. В пользовательском коде необходимо соблюдать осторожность, чтобы избежать гонок, если вы хотите изменять один и тот же массив в нескольких потоках. Конечно, возможно сломать NumPy, изменяя массив одновременно в нескольких потоках, например, вызывая ufunc и resize метод одновременно. Пока наше руководство: "не делайте этого". В будущем мы хотели бы предоставить более сильные гарантии.

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

Если вас интересует свободнопоточный Python, например, потому что у вас есть рабочий процесс на основе многопроцессорности, который вы хотите запустить с потоками Python, мы рекомендуем тестирование и эксперименты.

Если вы столкнулись с проблемами, которые, как вы подозреваете, связаны с NumPy, пожалуйста, создать issue, сначала проверяя, возникает ли ошибка также в «обычной» сборке CPython 3.13 без свободных потоков. Многие ошибки потоков могут возникать и в коде, который освобождает GIL; отключение GIL только упрощает возникновение ошибок потоков.

(gh-26157)

  • numpy.reshape и numpy.ndarray.reshape теперь поддерживает shape и copy аргументы.

    (gh-26292)

  • NumPy теперь поддерживает DLPack v1, поддержка старых версий будет устаревать в будущем.

    (gh-26501)

  • numpy.asanyarray теперь поддерживает copy и device аргументы, соответствующие numpy.asarray.

    (gh-26580)

  • numpy.printoptions, numpy.get_printoptions, и numpy.set_printoptions теперь поддерживают новую опцию, override_repr, для определения пользовательских repr(array) поведение.

    (gh-26611)

  • numpy.cumulative_sum и numpy.cumulative_prod были добавлены как совместимые альтернативы Array API для numpy.cumsum и numpy.cumprod. Новые функции могут включать фиксированный начальный (нули для sum и единицы для prod) в результате.

    (gh-26724)

  • numpy.clip теперь поддерживает max и min именованные аргументы, которые предназначены для замены a_min и a_max. Также, для np.clip(a) или np.clip(a, None, None) вместо вызова ошибки будет возвращена копия входного массива.

    (gh-26724)

  • numpy.astype теперь поддерживает device аргумент.

    (gh-26724)

f2py может генерировать C-расширения, совместимые с freethreading#

Передать --freethreading-compatible в инструмент CLI f2py для создания C-расширения, помеченного как совместимое с интерпретатором CPython со свободной потоковой моделью. Это предотвращает повторное включение GIL интерпретатором во время выполнения при импорте C-расширения. Обратите внимание, что f2py не анализирует фортран-код на потокобезопасность, поэтому вы должны убедиться, что обёрнутый фортран-код является потокобезопасным, прежде чем помечать расширение как совместимое.

(gh-26981)

Улучшения#

histogram автоматическая бинизация теперь возвращает размеры бинов >=1 для целочисленных входных данных#

Для целочисленных входных данных размеры бинов меньше 1 приводят к ложным пустым бина. Теперь этого избегают, когда количество бинов вычисляется с использованием одного из алгоритмов, предоставленных histogram_bin_edges.

(gh-12150)

ndarray Параметр типа формы теперь ковариантен и ограничен tuple[int, ...]#

Статическая типизация для ndarray является долгосрочным усилием, которое продолжается с этим изменением. Это обобщённый тип с параметрами типа для формы и типа данных. Ранее параметр типа формы мог быть любым значением. Это изменение ограничивает его кортежем целых чисел, как можно было бы ожидать от использования ndarray.shape. Кроме того, параметр shape-type был изменён с инвариантного на ковариантный. Это изменение также применяется к подтипам ndarray, например, numpy.ma.MaskedArray. См. документация по типизации для получения дополнительной информации.

(gh-26081)

np.quantile с методом closest_observation выбирает ближайшую чётную порядковую статистику#

Это изменяет определение ближайшего для граничных случаев с ближайшей нечетной порядковой статистики на ближайшую четную порядковую статистику. Реализация numpy теперь соответствует другим эталонным реализациям.

(gh-26656)

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

NumPy предоставляет минимальную низкопроизводительную версию LAPACK под названием lapack_lite который можно использовать, если при сборке не обнаружена система BLAS/LAPACK.

До сих пор, lapack_lite не был потокобезопасным. Однопоточные случаи использования не вызывали проблем, но выполнение операций линейной алгебры в нескольких потоках могло привести к ошибкам, некорректным результатам или сегфолтам из-за гонок данных.

Мы добавили глобальную блокировку, сериализующую доступ к lapack_lite в нескольких потоках.

(gh-26750)

The numpy.printoptions контекстный менеджер теперь потокобезопасен и безопасен для асинхронности#

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

(gh-26846)

Аннотация типов numpy.polynomial#

Начиная с релиза 2.1, аннотации типов PEP 484 были включены для функций и вспомогательных классов в numpy.polynomial и его подпакеты.

(gh-26897)

Улучшено numpy.dtypes подсказки типов#

Аннотации типов для numpy.dtypes теперь лучше отражают время выполнения: numpy.dtype псевдонимы типов были заменены специализированными dtype подтипы, и ранее отсутствующие аннотации для numpy.dtypes.StringDType были добавлены.

(gh-27008)

Улучшения и изменения производительности#

  • numpy.save теперь использует протокол pickle версии 4 для сохранения массивов с dtype object, что позволяет сохранять объекты pickle размером более 4 ГБ и улучшает скорость сохранения примерно на 5% для больших массивов.

    (gh-26388)

  • OpenBLAS на x86_64 и i686 собран с меньшим количеством ядер. На основе тестирования выделено 5 кластеров производительности вокруг этих ядер: PRESCOTT NEHALEM SANDYBRIDGE HASWELL SKYLAKEX.

    (gh-27147)

  • OpenBLAS в Windows линкуется без quadmath, упрощая лицензирование

    (gh-27147)

  • Из-за регрессии в OpenBLAS на Windows, улучшения производительности при использовании нескольких потоков для OpenBLAS 0.3.26 были отменены.

    (gh-27147)

ma.cov и ma.corrcoef теперь значительно быстрее#

Приватная функция была рефакторизована вместе с ma.cov и ma.corrcoef. Теперь они значительно быстрее, особенно на больших маскированных массивах.

(gh-26285)

Изменения#

  • Поскольку numpy.vecdot теперь является ufunc, у него менее точная сигнатура. Это связано с ограничениями заглушки типизации ufunc.

    (gh-26313)

  • numpy.floor, numpy.ceil, и numpy.trunc теперь не будет выполнять приведение к типу с плавающей точкой для входных массивов целочисленного и булевого типа.

    (gh-26766)

ma.corrcoef может вернуть немного другой результат#

Парный подход наблюдения в настоящее время используется в ma.corrcoef для расчёта стандартных отклонений для каждой пары переменных. Это было изменено, так как используется для нормализации ковариации, оценённой с помощью ma.cov, который не рассматривает наблюдения для каждой переменной попарно, делая это ненужным. Нормализация была заменена более подходящим стандартным отклонением для каждой переменной, что значительно сокращает время выполнения, но возвращает немного другие оценки коэффициентов корреляции в случаях, когда наблюдения между парой переменных не выровнены. Однако во всех остальных случаях возвращаются те же оценки, включая возврат той же матрицы корреляции, что и corrcoef при использовании маскированного массива без замаскированных значений.

(gh-26285)

Исправления безопасности приведения типов в copyto и full#

copyto теперь корректно использует NEP 50 и применяет это к своей безопасности приведения. Приведение целых чисел Python к целым числам NumPy и чисел с плавающей точкой Python к числам с плавающей точкой NumPy теперь считается «безопасным», даже если присваивание может завершиться неудачно или точность может быть потеряна. Это означает, что следующие примеры немного изменяются:

  • np.copyto(int8_arr, 1000) ранее выполнил небезопасное/однородное приведение

    целого числа Python. Теперь он всегда будет вызывать исключение; для небезопасного приведения необходимо передать массив или скаляр NumPy.

  • np.copyto(uint8_arr, 1000, casting="safe") вызовет OverflowError вместо TypeError из-за приведения одного типа.

  • np.copyto(float32_arr, 1e300, casting="safe") переполнится до inf (float32 не может содержать 1e300) вместо вызова TypeError.

Кроме того, только dtype используется при присвоении скаляров NumPy (или 0-мерных массивов), что означает, что следующее ведет себя по-разному:

  • np.copyto(float32_arr, np.float64(3.0), casting="safe") вызывает исключение.

  • np.coptyo(int8_arr, np.int64(100), casting="safe") вызывает исключение. Ранее NumPy проверял, подходит ли 100 в int8_arr.

Это выравнивает copyto, full, и full_like с правильным поведением NumPy 2.

(gh-27091)