|
7 | 7 |
|
8 | 8 | import os
|
9 | 9 | import csv
|
10 |
| - from pandas import DataFrame |
| 10 | + from pandas import DataFrame, Series |
11 | 11 | import pandas as pd
|
12 | 12 | pd.options.display.max_rows=15
|
13 | 13 |
|
@@ -97,7 +97,7 @@ First we're going to need to import the cython magic function to ipython:
|
97 | 97 |
|
98 | 98 | .. ipython:: python
|
99 | 99 |
|
100 |
| - %load_ext cythonmagic |
| 100 | + %load_ext Cython |
101 | 101 |
|
102 | 102 |
|
103 | 103 | Now, let's simply copy our functions over to cython as is (the suffix
|
@@ -286,12 +286,62 @@ Even faster, with the caveat that a bug in our cython code (an off-by-one error,
|
286 | 286 | for example) might cause a segfault because memory access isn't checked.
|
287 | 287 |
|
288 | 288 |
|
289 |
| -Further topics |
290 |
| -~~~~~~~~~~~~~~ |
| 289 | +.. _enhancingperf.numba: |
| 290 | + |
| 291 | +Using numba |
| 292 | +----------- |
| 293 | + |
| 294 | +A recent alternative to statically compiling cython code, is to use a *dynamic jit-compiler*, ``numba``. |
| 295 | + |
| 296 | +Numba gives you the power to speed up your applications with high performance functions written directly in Python. With a few annotations, array-oriented and math-heavy Python code can be just-in-time compiled to native machine instructions, similar in performance to C, C++ and Fortran, without having to switch languages or Python interpreters. |
| 297 | + |
| 298 | +Numba works by generating optimized machine code using the LLVM compiler infrastructure at import time, runtime, or statically (using the included pycc tool). Numba supports compilation of Python to run on either CPU or GPU hardware, and is designed to integrate with the Python scientific software stack. |
| 299 | + |
| 300 | +.. note:: |
| 301 | + |
| 302 | + You will need to install ``numba``. This is simple with ``conda``, see :ref:`installing using miniconda<install.miniconda>`. |
| 303 | + By using: ``conda install numba`` |
| 304 | + |
| 305 | +We simply take the plain python code from above an annotate with the ``@jit`` decorator. |
| 306 | + |
| 307 | +.. code-block:: python |
| 308 | +
|
| 309 | + import numba |
| 310 | +
|
| 311 | + @numba.jit |
| 312 | + def f_plain(x): |
| 313 | + return x * (x - 1) |
| 314 | +
|
| 315 | + @numba.jit |
| 316 | + def integrate_f_numba(a, b, N): |
| 317 | + s = 0 |
| 318 | + dx = (b - a) / N |
| 319 | + for i in range(N): |
| 320 | + s += f_plain(a + i * dx) |
| 321 | + return s * dx |
| 322 | +
|
| 323 | + @numba.jit |
| 324 | + def apply_integrate_f_numba(col_a, col_b, col_N): |
| 325 | + n = len(col_N) |
| 326 | + result = np.empty(n, dtype='float64') |
| 327 | + assert len(col_a) == len(col_b) == n |
| 328 | + for i in range(n): |
| 329 | + result[i] = integrate_f_numba(col_a[i], col_b[i], col_N[i]) |
| 330 | + return result |
| 331 | +
|
| 332 | + def compute_numba(df): |
| 333 | + result = apply_integrate_f_numba(df['a'].values, df['b'].values, df['N'].values) |
| 334 | + return Series(result, index=df.index, name='result') |
| 335 | +
|
| 336 | +Similar to above, we directly pass ``numpy`` arrays directly to the numba function. Further |
| 337 | +we are wrapping the results to provide a nice interface by passing/returning pandas objects. |
| 338 | + |
| 339 | +.. code-block:: python |
291 | 340 |
|
292 |
| -- Loading C modules into cython. |
| 341 | + In [4]: %timeit compute_numba(df) |
| 342 | + 1000 loops, best of 3: 774 us per loop |
293 | 343 |
|
294 |
| -Read more in the `cython docs <http://docs.cython.org/>`__. |
| 344 | +Read more in the `numba docs <http://numba.pydata.org/>`__. |
295 | 345 |
|
296 | 346 | .. _enhancingperf.eval:
|
297 | 347 |
|
|
0 commit comments