This notebook demonstrates the use of Robert Kern's line_profiler
(https://github.com/rkern/line_profiler) to profile cython
functions line by line. Thanks to Robert Bradshaw for implementing this feature (https://groups.google.com/forum/#!topic/cython-users/FH3TYK8BkeA).
#Load Robert Kern's line profiler
%load_ext line_profiler
import line_profiler
#Set compiler directives (cf. http://docs.cython.org/src/reference/compilation.html)
from Cython.Compiler.Options import directive_defaults
directive_defaults['linetrace'] = True
directive_defaults['binding'] = True
%%cython -a -f --compile-args=-DCYTHON_TRACE=1
#We need to define the macro CYTHON_TRACE=1 (cf. http://docs.cython.org/src/reference/compilation.html)
def cumulative_sum(int n):
cdef int s=0, i
for i in range(n):
s += i
return s
Generated by Cython 0.22.beta0
1: #We need to define the macro CYTHON_TRACE=1 (cf. http://docs.cython.org/src/reference/compilation.html)
2:
+3: def cumulative_sum(int n):
/* Python wrapper */ static PyObject *__pyx_pw_46_cython_magic_67a1c782057df134c860e5ee2814a620_1cumulative_sum(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/ static PyMethodDef __pyx_mdef_46_cython_magic_67a1c782057df134c860e5ee2814a620_1cumulative_sum = {"cumulative_sum", (PyCFunction)__pyx_pw_46_cython_magic_67a1c782057df134c860e5ee2814a620_1cumulative_sum, METH_O, 0}; static PyObject *__pyx_pw_46_cython_magic_67a1c782057df134c860e5ee2814a620_1cumulative_sum(PyObject *__pyx_self, PyObject *__pyx_arg_n) { int __pyx_v_n; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("cumulative_sum (wrapper)", 0); assert(__pyx_arg_n); { __pyx_v_n = __Pyx_PyInt_As_int(__pyx_arg_n); if (unlikely((__pyx_v_n == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L3_error;} } goto __pyx_L4_argument_unpacking_done; __pyx_L3_error:; __Pyx_AddTraceback("_cython_magic_67a1c782057df134c860e5ee2814a620.cumulative_sum", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_46_cython_magic_67a1c782057df134c860e5ee2814a620_cumulative_sum(__pyx_self, ((int)__pyx_v_n)); int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyObject *__pyx_pf_46_cython_magic_67a1c782057df134c860e5ee2814a620_cumulative_sum(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_n) { int __pyx_v_s; int __pyx_v_i; PyObject *__pyx_r = NULL; __Pyx_TraceDeclarations(__pyx_codeobj_) __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("cumulative_sum", 0); __Pyx_TraceCall("cumulative_sum", __pyx_f[0], 3); /* … */ __Pyx_TraceLine(3) /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_3); __Pyx_AddTraceback("_cython_magic_67a1c782057df134c860e5ee2814a620.cumulative_sum", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_TraceReturn(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* … */ __pyx_tuple__2 = PyTuple_Pack(4, __pyx_n_s_n, __pyx_n_s_n, __pyx_n_s_s, __pyx_n_s_i); if (unlikely(!__pyx_tuple__2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_tuple__2); __Pyx_GIVEREF(__pyx_tuple__2); /* … */ __pyx_t_1 = __Pyx_CyFunction_NewEx(&__pyx_mdef_46_cython_magic_67a1c782057df134c860e5ee2814a620_1cumulative_sum, 0, __pyx_n_s_cumulative_sum, NULL, __pyx_n_s_cython_magic_67a1c782057df134c8, __pyx_d, ((PyObject *)__pyx_codeobj_)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_cumulative_sum, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+4: cdef int s=0, i
__Pyx_TraceLine(4)
__pyx_v_s = 0;
+5: for i in range(n):
__Pyx_TraceLine(5)
__pyx_t_1 = __pyx_v_n;
for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
__pyx_v_i = __pyx_t_2;
+6: s += i
__Pyx_TraceLine(6)
__pyx_v_s = (__pyx_v_s + __pyx_v_i);
}
7:
+8: return s
__Pyx_TraceLine(8) __Pyx_XDECREF(__pyx_r); __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_s); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;} __Pyx_GOTREF(__pyx_t_3); __pyx_r = __pyx_t_3; __pyx_t_3 = 0; goto __pyx_L0;
#Print profiling statistics using the `line_profiler` API
profile = line_profiler.LineProfiler(cumulative_sum)
profile.runcall(cumulative_sum, 100)
profile.print_stats()
Timer unit: 1e-06 s Total time: 4.9e-05 s File: /Users/tillhoffmann/.ipython/cython/_cython_magic_67a1c782057df134c860e5ee2814a620.pyx Function: cumulative_sum at line 3 Line # Hits Time Per Hit % Time Line Contents ============================================================== 3 def cumulative_sum(int n): 4 1 9 9.0 18.4 cdef int s=0, i 5 1 1 1.0 2.0 for i in range(n): 6 100 39 0.4 79.6 s += i 7 8 1 0 0.0 0.0 return s
#Print profiling statistics using the `lprun` magic
%lprun -f cumulative_sum cumulative_sum(100)