Программирование и разработка программного обеспечения

Как использовать Numba для ускорения вычислительных моделей Python в финансовых услугах

Chad Schuster из Milliman объясняет, как Numba может преобразовывать части программ Python в оптимизированный код с помощью LLVM, используя параллельную обработку и GPU. Эксперимент демонстрирует значительный прирост производительности, но также выявляет ограничения объектно-ориентированного программирования, вывода типов и времени компиляции, поэтому выбор подходящих частей для ускорения становится критически важным.

2026-08-27
5 мин. чтения
13 просмотров
فريق تحرير certi.news
Как использовать Numba для ускорения вычислительных моделей Python в финансовых услугах

Chad Schuster, Principal в подразделении управления финансовыми рисками Milliman, представил практический опыт создания высокопроизводительных вычислительных моделей с использованием Python и Numba вместо полной зависимости от приложений, написанных на C++. Опыт начинается с распространённой проблемы в финансовых услугах: моделям, имитирующим денежные потоки для большого числа сценариев, требуются значительные вычислительные ресурсы, тогда как рабочие команды хотят сохранить скорость разработки и простоту сопровождения Python.

Проблема особенно важна для моделей страхования жизни и пенсионных продуктов, таких как annuities, где расчёты используются для оценки будущих обязательств и запуска множества сценариев. Согласно презентации, страховые компании исторически полагались на локальные сети из 5 000–10 000 узлов, однако переход в облако сделал время выполнения и стоимость каждой операции более очевидными при принятии инфраструктурных решений.

Что Numba добавляет в Python?

Традиционный Python, или CPython, интерпретирует код во время выполнения, тогда как компилируемые языки, например C++, преобразуют код в машинные инструкции до запуска. Numba пытается сократить этот разрыв с помощью компиляции Just-in-Time: подходящие функции компилируются во время работы программы с использованием LLVM, после чего исходная функция заменяется скомпилированной реализацией.

Обычно разработчик включает этот процесс с помощью декораторов Python, таких как JIT или njit. Numba работает на уровне функции: анализирует код и преобразует его в собственное промежуточное представление, затем выводит типы переменных, параметров и возвращаемых значений, после чего понижает представление до LLVM IR и выполняет необходимые оптимизации. Если функция вызывается с разными типами, Numba может создавать специализированные скомпилированные реализации для каждой комбинации типов посредством того, что она называет polymorphic dispatch.

Прирост производительности не является фиксированным показателем

В представленном Schuster доказательстве концепции Numba сделала программу примерно в 75 раз быстрее по сравнению с интерпретируемым Python. В другой модели результат был иным: перенос ресурсоёмких числовых вычислений в Numba на центральный процессор обеспечил ускорение примерно в два раза, а последующий переход на GPU дал дополнительное ускорение в 750 раз в рамках конкретного запуска. В презентации отмечалось, что такой уровень улучшения сделал GPU примерно эквивалентным 750 ядрам, использованным в этом запуске, при ориентировочном снижении стоимости до примерно одной десятой.

Однако эти результаты не являются общей гарантией для любого приложения. Улучшение зависит от объёма компилируемого кода, соотношения вычислительных операций и операций ввода-вывода, эффективности исходного Python и способности LLVM оптимизировать полученный код. Обработка на GPU также подходит не для каждого алгоритма, поэтому перед перестройкой модели необходимо измерить фактическое узкое место.

Что практически меняется для инженерных команд?

Опыт рекомендует по возможности оставлять слои подготовки данных, ввода и вывода в Python, а в Numba переносить только ресурсоёмкую числовую часть. Такой подход ограничивает объём переписывания и сохраняет значительную часть среды Python, сосредотачивая усилия по оптимизации на функциях, которые занимают большую часть времени выполнения. Когда числовые функции ограничены и чётко определены, Schuster считает, что Numba может быть прямым вариантом для тех, кто хочет оставаться в рамках Python.

При добавлении в Numba масштабной и сложной логики возрастают затраты на проектирование и сопровождение. В эксперименте использовались массивы NumPy, tuples и простые структуры данных, поскольку поддержка Numba не охватывает все возможности Python. Среди упомянутых ограничений — словари с гибкими типами, исключения, контекстные менеджеры, замыкания и списки, создаваемые с помощью comprehensions, а также ограниченная поддержка некоторых распространённых функций, таких как print, sorted и getattr.

Ограничения, которые следует учитывать заранее

Объектно-ориентированное программирование остаётся важным слабым местом в этом опыте. Numba предоставляет экспериментальные возможности, такие как jitclasses и structrefs, для придания поведению характеристик, схожих с объектными, но они могут меняться между версиями и не поддерживают GPU, что сделало их неподходящими для использованного командой подхода. Поэтому приложение перешло к стилю, более близкому к функциональному программированию, и простым структурам данных, несмотря на то что объектно-ориентированный дизайн был желателен с точки зрения сопровождаемости и передачи моделей клиентам.

Ошибки вывода типов и ошибки lowering также могут быть сложными для отслеживания, особенно в программах с множеством уровней вызовов. Ошибка может указывать на функцию, удалённую от места, где фактически возникла проблема. Один из предложенных практических подходов — использовать JIT вместо njit при необходимости, чтобы временно отключить Numba и вернуться к интерпретируемому Python для упрощения отладки, а затем снова включить ускорение в рабочем запуске.

Существует также первоначальное время компиляции, возникающее при первом вызове каждой функции; оно может увеличиваться при широком использовании техники inlining. Для устранения этой задержки можно прибегнуть к предварительной компиляции Ahead-of-Time, однако это может снизить способность кода адаптироваться к фактическому устройству по сравнению с компиляцией Just-in-Time.

Редакционное чтение: основная ценность этого опыта заключается не в самом показателе «750 раз», а в подходе, связывающем измерение производительности с декомпозицией модели. Numba подходит, когда узкое место связано с вычислениями и может быть изолировано в функциях с понятными типами и структурами; попытка превратить всю систему Python в компилируемый код может перенести проблему от медленного выполнения к сложности разработки и отладки. Поэтому финансовым и инженерным командам следует сопоставить скорость выполнения, сопровождаемость, время компиляции и совместимость с GPU, прежде чем рассматривать Numba как полноценную альтернативу C++ или более масштабной переработке системы.

Источник новости
InfoQ - Architecture Articles
Открыть первоисточник ↗
ف
Автор

فريق تحرير certi.news

В той же категории

Вам также может понравиться

Все новости