Тайм-менеджмент с Python
Без оптимизации времени выполнения кода при работе с данными большого размера никак не обойтись. Расскажем, какие существуют простые методы измерения скорости выполнения строк, функций и сценариев в Python.
Создадим датафрейм:
import pandas as pd import numpy as np data = np.random.normal(size=(5000000,3)) df = pd.DataFrame(data, columns=['first', 'second', 'third'])
Теперь перейдем к измерениям. Во-первых, время работы участка кода можно оценивать с помощью встроенных модулей:
import time start = time.time() df_sum = df.sum(axis=1) end = time.time() print(f'Затраченное время составило {end-start} сек')
Но наиболее удобные средства для этого предоставляет командная оболочка IPython, устанавливаемая как пакет в окружение интерпретатора и совместимая с популярными средами разработки - PyCharm, Jupyter, Spyder.
Время выполнения строк
В частности, для достижения той же цели можно воспользоваться магическими командами %time, %timeit (разница в том, что во второй для объектиности вычисляется среднее время нескольких итераций):
%time df.sum(axis=1)
%timeit df.sum(axis=1)
Следует отметить, что время для разных способов может отличаться ввиду различающихся подходов к использованию ресурсов компьютера.
Время выполнения блоков
Если вызывать магические команды с двумя символами процента, то происходит измерение времени выполнения блоков:
%%time df_new = df.copy() for i, row in df_new.iterrows(): if i<5: df_new.at[i, 'first'] = i
Профилирование сценариев
Посредством профилирования устанавливается время исполнения различных участков кода. В Python основное средство для этого – встроенный модуль cProfile.
Напишем небольшой скрипт и сохраним в файле :
def f_minus(a,b): return a-b def f_plus(a,b): return a+b c = [f_minus(3,4) for _ in range(10000)] d = [f_plus(1,3) for _ in range(20000)]
Ниже пример вызова профилирования сценария с флагом упорядочивания по времени исполнения:
python -m cProfile -s cumulative time_script.py
IPython предусматривает магические команды для более удобного применения cProfile. Так для получения схожих результатов можно применить %run с ключом -p:
%run -p -s cumulative time_script.py
Профилирование функций
С помощью магической команды %prun можно осуществить профилирование функции. Добавим в сценарий функцию:
def f_ops(): c = [f_minus(3,4) for _ in range(100000)] d = [f_plus(1,3) for _ in range(200000)]
теперь инициируем профилирование:
from time_script import f_ops %prun -s cumulative f_ops()
Результат показывает сколько времени тратится на вызов "подфункций".
Пошаговое профилирование функции
Для этого устанавливаем пакет:
pip install line_profiler
Далее загружаем расширение в оболочку (иначе получим ошибку):
%load_ext line_profiler
Теперь инициируем профилирование:
%lprun -f f_ops f_ops()