Линейное профилирование с помощью Cython в блокноте Jupyter
Я пытаюсь использовать библиотеку liner_profiler в ноутбуке Jupyter с функцией Cython. Это работает только на полпути. Результат, который я получаю, состоит только из первой строки функции и без результатов профилирования.
%%cython -a
# cython: linetrace=True
# cython: binding=True
# distutils: define_macros=CYTHON_TRACE_NOGIL=1
import numpy as np
cimport numpy as np
from datetime import datetime
import math
cpdef np.int64_t get_days(np.int64_t year, np.int64_t month):
cdef np.ndarray months=np.array([31,28,31,30,31,30,31,31,30,31,30,31])
if month==2:
if (year%4==0 and year%100!=0) or (year%400==0):
return 29
return months[month-1]
Для результата профилирования int onlt показывает одну строку кода
Timer unit: 1e-07 s
Total time: 0.0015096 s
File: .ipython\cython\_cython_magic_0154a9feed9bbd6e4f23e57d73acf50f.pyx
Function: get_days at line 15
Line # Hits Time Per Hit % Time Line Contents
==============================================================
15 cpdef np.int64_t get_days(np.int64_t year, np.int64_t month):
1 ответ
Это можно рассматривать как ошибку в line_profiler
(если предполагается поддержка Cython). Чтобы получить код профилированной функции, line_profiler
читает pyx
-файл и пытается извлечь код с помощью inspect.getblock
:
...
# read pyx-file
all_lines = linecache.getlines(filename)
# try to extract body of the function strarting at start_lineno:
sublines = inspect.getblock(all_lines[start_lineno-1:])
...
Тем не мение, getblock
ничего не знает о cpdef
-функция, так как питон имеет только def
-функции и, следовательно, дает неправильное тело функции (т.е. только подпись).
Временное решение:
Простой обходной путь - ввести пустышку def
-функция, которая была бы часовым для cpdef
-функция таким образом, что inspect.getblock
выдаст все тело функции cpdef + тело функции часового, то есть:
%%cython
...
cpdef np.int64_t get_days(np.int64_t year, np.int64_t month):
...
def get_days_sentinel():
pass
а теперь отчет %lprun -f get_days get_days(2019,3)
выглядит следующим образом:
Timer unit: 1e-06 s
Total time: 1.7e-05 s
File: XXXX.pyx
Function: get_days at line 10
Line # Hits Time Per Hit % Time Line Contents
==============================================================
10 cpdef np.int64_t get_days(np.int64_t year, np.int64_t month):
11 1 14.0 14.0 82.4 cdef np.ndarray months=np.array([31,28,31,30,31,30,31,31,30,31,30,31])
12 1 1.0 1.0 5.9 if month==2:
13 if (year%4==0 and year%100!=0) or (year%400==0):
14 return 29
15 1 2.0 2.0 11.8 return months[month-1]
16
17 def get_days_sentinel():
18 pass
От стража все еще есть несколько отвратительные следы, но, вероятно, лучше вообще ничего не видеть.