Profiling

IPython

Interactive Python provides some Built-in magic commands that can help up when developing code.

?

IPython's help.


In [ ]:
?

%quickref

Quick reference.


In [ ]:
%quickref

help

Python’s own help system.


In [ ]:
help

object?

Details about object. Use object?? for extra details.


In [ ]:
a = 1
a?

! <command>

Forks a shell, run a command in it, exits the shell and returns.


In [ ]:
!cd /

In [ ]:
!pwd

%cd

Change the current working directory.


In [ ]:
%cd /

In [ ]:
!pwd

In [ ]:
%cd ~/YAPT

In [ ]:
!pwd

who/whos

Print all interactive variables


In [ ]:
%whos

%time <Python statement/expression>

time <Python statement/expression>` Temporize the execution of a Python statement or expression, remembering its results.


In [ ]:
a

In [ ]:
%time a=3

In [ ]:
a

%timeit <Python statement/expression>

Really temporize the execution of a Python statement or expression, but forgeting its results.


In [ ]:
a

In [ ]:
%timeit a=4

In [ ]:
a

%run <python module>.py

Run the named file inside IPython as a program.


In [ ]:
%run hello_world.py

In [ ]:
# %load module.py
a = 1

In [ ]:
%run module.py

In [ ]:
%whos

In [ ]:
a

%run -t <python module>.py

Giving running times.


In [ ]:
!cat substract_curves.py

In [ ]:
!paste dataset1.txt dataset2.txt

In [ ]:
%run -t substract_curves.py dataset1.txt dataset2.txt

A longer example (for the sake of the correctness of substract_curves.py):


In [ ]:
# Generate two "random" similar signals.

import io
import numpy as np

x = 0
base = []
with io.open('dataset3.txt', 'w') as file:
    for i in range(100):
        x += np.random.randint(10) - 4.5
        file.write('{}\t{}\n'.format(i*2,x))
        base.append(x)

with io.open('dataset4.txt', 'w') as file:
    for i in range(99):
        x = base[i] + np.random.randint(10) - 4.5
        file.write('{}\t{}\n'.format(i*2+1,x))

In [ ]:
# Run "substract_curves.py" and its stdout is written in "differences.txt". 

import IPython.utils
with IPython.utils.io.capture_output() as captured:
    !python substract_curves.py dataset3.txt dataset4.txt
import io
with io.open('differences.txt', 'w') as file:
    file.write(captured.stdout)

In [ ]:
# Plot the signals.

import matplotlib.pyplot as plt
plt.plot(*np.loadtxt("dataset3.txt",unpack=True), linewidth=2.0)
plt.plot(*np.loadtxt("dataset4.txt",unpack=True), linewidth=2.0)
plt.plot(*np.loadtxt("differences.txt",unpack=True), linewidth=2.0)
plt.show()

line_profiler

Provides line-by-line running information of decorated methods.

  1. Decorate with @profile those methods you want to profile.
    @profile
    def profile_me(...):
     ...
  2. Profile your module with:
kernprof -l -v <your_module>.py

In [ ]:
!cat profile_quicksort.py

In [ ]:
!kernprof -l -v  profile_quicksort.py

<!-- !cat quicksort.c ->


In [ ]:
<!-- !python -m cProfile quicksort.py -->

Testing Cython

Extracted from this HPC tutorial.

$ pip install cython


In [1]:
%load_ext Cython

In [2]:
def f_slow(i):
    return i**4 + 3*i**2 + 10

In [3]:
%timeit f_slow(100)


837 ns ± 54.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [4]:
%%cython --annotate
def f_cython(int i):
    return i**4 + 3*i**2 + 10


Out[4]:
Cython: _cython_magic_c34e6c7d67fb447dfc07750a775456d3.pyx

Generated by Cython 0.29.2

Yellow lines hint at Python interaction.
Click on a line that starts with a "+" to see the C code that Cython generated for it.

+1: def f_cython(int i):
/* Python wrapper */
static PyObject *__pyx_pw_46_cython_magic_c34e6c7d67fb447dfc07750a775456d3_1f_cython(PyObject *__pyx_self, PyObject *__pyx_arg_i); /*proto*/
static PyMethodDef __pyx_mdef_46_cython_magic_c34e6c7d67fb447dfc07750a775456d3_1f_cython = {"f_cython", (PyCFunction)__pyx_pw_46_cython_magic_c34e6c7d67fb447dfc07750a775456d3_1f_cython, METH_O, 0};
static PyObject *__pyx_pw_46_cython_magic_c34e6c7d67fb447dfc07750a775456d3_1f_cython(PyObject *__pyx_self, PyObject *__pyx_arg_i) {
  int __pyx_v_i;
  PyObject *__pyx_r = 0;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("f_cython (wrapper)", 0);
  assert(__pyx_arg_i); {
    __pyx_v_i = __Pyx_PyInt_As_int(__pyx_arg_i); if (unlikely((__pyx_v_i == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 1, __pyx_L3_error)
  }
  goto __pyx_L4_argument_unpacking_done;
  __pyx_L3_error:;
  __Pyx_AddTraceback("_cython_magic_c34e6c7d67fb447dfc07750a775456d3.f_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __Pyx_RefNannyFinishContext();
  return NULL;
  __pyx_L4_argument_unpacking_done:;
  __pyx_r = __pyx_pf_46_cython_magic_c34e6c7d67fb447dfc07750a775456d3_f_cython(__pyx_self, ((int)__pyx_v_i));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static PyObject *__pyx_pf_46_cython_magic_c34e6c7d67fb447dfc07750a775456d3_f_cython(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_i) {
  PyObject *__pyx_r = NULL;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("f_cython", 0);
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_AddTraceback("_cython_magic_c34e6c7d67fb447dfc07750a775456d3.f_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = NULL;
  __pyx_L0:;
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
/* … */
  __pyx_tuple_ = PyTuple_Pack(2, __pyx_n_s_i, __pyx_n_s_i); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple_);
  __Pyx_GIVEREF(__pyx_tuple_);
/* … */
  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_c34e6c7d67fb447dfc07750a775456d3_1f_cython, NULL, __pyx_n_s_cython_magic_c34e6c7d67fb447dfc); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_f_cython, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+2:     return i**4 + 3*i**2 + 10
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyInt_From_long(((__Pyx_pow_long(((long)__pyx_v_i), 4) + (3 * __Pyx_pow_long(((long)__pyx_v_i), 2))) + 10)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;

In [5]:
%timeit f_cython(100)


86.7 ns ± 11.3 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)