Что делать, если код на Python замораживается

Назвали 5 способов борьбы с заморозкой кода на Python. Среди них — рефакторинг и профилирование кода, JIT, запуск на GPU, переход на Golang.

655 открытий2К показов

Давайте честно, Python порой тормозит. В моей практике бывают случаи, когда единственная ячейка в Colab “вешает” весь ноутбук. Выделенных мощностей не хватает, по «мнению» компилятора, и исполнение программы “замораживается”, пока вы не перезапустите среду и не сократите тот самый, проблемный, участок кода. 

Если вам знакома такая проблема, то ловите способы борьбы с ней, которые выработало сообщество за годы практики.

Использование более эффективных алгоритмов и структур данных для ускорения работы с данными

Еще при выпуске первой версии языка команда создателей придумала правила и назвала их PEP (наверняка вы уже читали про отступы с принципами именования на docs.python.org). Основная цель этих правил — улучшение самого  Python, а не оптимизация производительности. Но некоторые PEP’ы могут влиять и на скорость. Например, PEP 523 “Обработка многопоточных установок глобального интерпретатора” добавил функции, которые позволяют более эффективно использовать многопоточность в Python.

Если вы переживаете, что со всеми этими правила не сможете выразить индивидуальность в коде — поверьте, «авторский» стиль будет и так виден при исполнении типовых задач.

Вот несколько наглядных примеров таких эффективных структур:

  • Генераторы и итераторы вместо “загонки” списка в явный цикл
			>>> a = (i**2 for i in range(1,5))
>>> a
<generator object <genexpr> at 0x0000023A7524D6D0>
		
  • Лямбды для  для “вкладывания” функции в функцию
			def myfunc():
    n = 2
    return lambda a: a * n
		
  • Избегание переназначения переменных и использование локальных переменных в функциях.
			var = 'строковая переменная'
def some_func():
	pass

var = 123
		
  • Ограничение использований циклов for
  • Использование библиотек, таких как numpy или pandas, для работы с матрицами и таблицами.
			import pandas as pd
data = []
for row in some_function_that_yields_data():
    data.append(row)

df = pd.DataFrame(data)
		
  • Использование кортежей вместо списков.
			a = tuple('hello, world!')
		
Первая мысль при знакомстве с PEP8: “Порядок – это хорошо. Со временем, наверное, смогу разучить это”. То есть о подспудной пользе стандартов задумываться не приходится без необходимости. Теперь же, спустя семь лет, периодически сталкиваясь с проблемой “замороженного ноутбука” я понимаю, что даже такие крупицы, как “писать код по стандарту PEP” складываются в итоге в читаемый оптимальный код.

Список не ограничивается этими пунктами. В каждом из этих случаев замеры скорости исполнения покажут выигрыш в скорости исполнения. Проверено. Обычно этот способ ускорения сопровождается напарником – профилированием кода.

Профилирование кода

Это сбор характеристик работы программы, таких как время выполнения отдельных фрагментов, число верно предсказанных условных переходов, число кэш-промахов и т. д. с помощью инструментов вроде cProfile или line_profiler.

			import cProfile
import numpy as np
cProfile.run("20+10")
		

Вывод будет такой:

			3 function calls in 0.000 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
		

JIT (Just-In-Time) компилятор

Python – интерпретируемый язык, код выполняется построчно и в машинный код не переводится. Интерпретация медленнее по сравнению с компиляцией (C или C++). Однако с использованием JIT-компиляторов можно достичь приближенной к ним скорости.

Такие инструменты анализируют и оптимизируют в реальном времени, что позволяет улучшить производительность. Широкое признание в сообществе получили компиляторы Numba и Cython

Разгоняем код с Cython

Numba vs. Cython vs. Taichi

Запуск кода на GPU с помощью библиотек, таких как tensorflow, pytorch или theano.

Поиграться с таким интересным функционалом уже позволяют IDE вроде Google Colaboratory и Jupyter Notebook. 

Как переключиться на графический процессор в Colab

Пожалуй, это единственное для новоприбывших в Python применение графического процессора, да и то лишь для тех, кто ударился в Data Science и Machine Learning. И в целом не принято использовать этот подход в иных ситуациях.

Переход на Golang

Google решили проблему кардинально: написали новый язык. Зовут его Go. Кстати, если вы раздумываете, какой из этих двух языков выбрать, моя статья “Переход с Python на Go” поможет разобраться. Там же вы познакомитесь с реальными замерами скорости исполнения одной и той же программы на двух ЯП.

Заключение

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

Какие методы борьбы с заморозкой вы предпочитаете?
Рефакторинг кода
Использование графического процессора
JIT
Переход на другой язык
Посмотреть результаты
Следите за новыми постами
Следите за новыми постами по любимым темам
655 открытий2К показов