Язык 1957 года ускорил мой Python-скрипт в 150 раз

Не переписывал логику. Просто делегировал тяжёлую работу тому, кто умеет её делать.

У Python есть потолок. Не баг, не плохой код — просто физика интерпретатора. На каждой итерации цикла он проверяет типы, выделяет память под объекты, ищет методы. Тысячи операций — незаметно. Миллионы — скрипт превращается в слайд-шоу.

Обычно в таких случаях говорят: «используй numpy». Это работает, но только если задачу можно выразить через матричные операции. Как только появляется итеративная зависимость — когда текущее значение считается из предыдущего — векторизация либо невозможна, либо превращает код в нечитаемую кашу.

Именно в такую ситуацию я и попал.

Задача

Генерация фрактала Мандельброта. Картинка 2000×2000 пикселей. Для каждой точки — цикл до 200 итераций с комплексными числами. Итого: порядка 400 миллионов операций.

Python считал кадр 30 секунд. Для любого реального применения это неприемлемо.

Векторизовать не получилось — каждая итерация зависит от предыдущей. Писать расширение на C++ не хотелось — это отдельная история с управлением памятью и компилятором.

Я выбрал третий путь.

F2PY — инструмент, который уже есть в вашем numpy

Внутри пакета numpy живёт утилита F2PY. Она берёт файл с кодом на Fortran и одной командой компилирует его в модуль, который Python импортирует как родную библиотеку:

python -m numpy.f2py -c fractal_mod.f90 -m fractal_lib

После этого в Python просто пишешь:

import fractal_lib result = fractal_lib.mandelbrot(width, height, max_iter)

Никакого переписывания логики. Только делегирование вычислений туда, где они выполняются быстро.

Сам Fortran выглядит не страшно

Забудьте про стереотипы о перфокартах. Современный стандарт Fortran 2008/2018 читается нормально:

subroutine mandelbrot(width, height, max_iter, result) implicit none integer, intent(in) :: width, height, max_iter integer, intent(out) :: result(height, width) integer :: i, j, k real(8) :: x, y, zr, zi, zr2, zi2 real(8) :: x_min, x_max, y_min, y_max x_min = -2.5d0; x_max = 1.0d0 y_min = -1.25d0; y_max = 1.25d0 do j = 1, width x = x_min + (x_max - x_min) * (j - 1) / (width - 1) do i = 1, height y = y_min + (y_max - y_min) * (i - 1) / (height - 1) zr = 0.0d0; zi = 0.0d0; k = 0 do while (zr*zr + zi*zi <= 4.0d0 .and. k < max_iter) zr2 = zr*zr - zi*zi + x zi = 2.0d0*zr*zi + y zr = zr2; k = k + 1 end do result(i, j) = k end do end do end subroutine

Математика читается почти как псевдокод.

Результат

Язык 1957 года ускорил мой Python-скрипт в 150 раз

Те же 2000×2000 пикселей — 0.2 секунды вместо 30.

Ускорение в 150 раз. Просто переложив «узкое горлышко» на язык, созданный для математики.

Где это реально нужно

Фрактал — это демонстрация. Но та же схема работает в продакшне:

Monte Carlo в финансах. Прогнать миллион сценариев для оценки рисков. Python управляет данными, Fortran считает.

Обработка сигналов. Нестандартный фильтр для потока с датчиков или видео 4K — там, где стандартных функций OpenCV уже не хватает.

Legacy-код в науке. В геофизике и климатологии существуют терабайты проверенного Fortran-кода. Переписывать на C++ дорого и опасно. Проще обернуть через F2PY и использовать в современном стеке.

Инженерное моделирование. Решатели уравнений теплопроводности и гидродинамики — исторически территория Fortran. Интерфейс делается на Python, расчёты остаются там, где работают быстро.

Вывод

Fortran в 2025 году — это «второй пилот» для Python в задачах с тяжёлыми вычислениями. Безопаснее C++, синтаксис заточен под математику, интеграция с Python из коробки.

Если ваш код упирается в процессор — иногда правильнее не оптимизировать Python, а делегировать работу тому, кто умеет её делать.

Если тема зацепила — я собрал практический курс по Fortran: от синтаксиса до интеграции с Python через F2PY. Ссылка в описании профиля.

1
Начать дискуссию