{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Making Python faster\n", "====\n", "\n", "The Julia website has a set of benchmarks to show how fast it is. These are for toy functions, but serve as a nice set of examples for the basics of using `cython` and `numba` in Python.\n", "\n", "These examples are adapted from [here](https://www.ibm.com/developerworks/community/blogs/jfp/entry/python_meets_julia_micro_performance?lang=en)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
FortranJuliaPythonRMatlab
1fib0.702.1177.76533.5226.89
2parse_int5.051.4517.0245.73802.52
3quicksort1.311.1532.89264.544.92
4mandel0.810.7915.3253.167.58
5pi_sum1.001.0021.999.561.00
6rand_mat_stat1.451.6617.9314.5614.52
7rand_mat_mul3.481.021.141.571.12
\n", "
" ], "text/plain": [ " Fortran Julia Python R Matlab\n", "1 fib 0.70 2.11 77.76 533.52 26.89\n", "2 parse_int 5.05 1.45 17.02 45.73 802.52\n", "3 quicksort 1.31 1.15 32.89 264.54 4.92\n", "4 mandel 0.81 0.79 15.32 53.16 7.58\n", "5 pi_sum 1.00 1.00 21.99 9.56 1.00\n", "6 rand_mat_stat 1.45 1.66 17.93 14.56 14.52\n", "7 rand_mat_mul 3.48 1.02 1.14 1.57 1.12" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "benchmarks = pd.read_pickle('julia_benchmarks.pic')\n", "benchmarks.ix[:, :6]" ] }, { "cell_type": "code", "execution_count": 145, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import time\n", "import random\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 119, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from numba import njit, jit" ] }, { "cell_type": "code", "execution_count": 120, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The cython extension is already loaded. To reload it, use:\n", " %reload_ext cython\n" ] } ], "source": [ "%load_ext cython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Utility function" ] }, { "cell_type": "code", "execution_count": 121, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def timer(f, *args, **kwargs):\n", " start = time.clock()\n", " ans = f(*args, **kwargs)\n", " return ans, time.clock() - start" ] }, { "cell_type": "code", "execution_count": 130, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def report(fs, *args, **kwargs):\n", " ans, t = timer(fs[0], *args, **kwargs)\n", " print('%s: %.1f' % (fs[0].__name__, 1.0)) \n", " for f in fs[1:]:\n", " ans_, t_ = timer(f, *args, **kwargs)\n", " print('%s: %.1f' % (f.__name__, t/t_))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Fib\n", "----" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def fib(n):\n", " if n<2:\n", " return n\n", " return fib(n-1)+fib(n-2)" ] }, { "cell_type": "code", "execution_count": 64, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "6765" ] }, "execution_count": 64, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fib(20)" ] }, { "cell_type": "code", "execution_count": 113, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100 loops, best of 3: 5.84 ms per loop\n" ] } ], "source": [ "%timeit fib(20)" ] }, { "cell_type": "code", "execution_count": 68, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from functools import lru_cache\n", "\n", "@lru_cache()\n", "def fib_lru(n):\n", " if n<2:\n", " return n\n", " return fib(n-1)+fib(n-2)" ] }, { "cell_type": "code", "execution_count": 114, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The slowest run took 92.76 times longer than the fastest. This could mean that an intermediate result is being cached \n", "1000000 loops, best of 3: 213 ns per loop\n" ] } ], "source": [ "%timeit fib_lru(20)" ] }, { "cell_type": "code", "execution_count": 115, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_a7383439b4d9daca4b8a6d569c53a027.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.4

\n", "

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

\n", "
 1: 
\n", "
+2: cpdef long fib_cython(int n):
\n", "
static PyObject *__pyx_pw_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_1fib_cython(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/\n",
       "static long __pyx_f_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_fib_cython(int __pyx_v_n, CYTHON_UNUSED int __pyx_skip_dispatch) {\n",
       "  long __pyx_r;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"fib_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L0:;\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_1fib_cython(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/\n",
       "static PyObject *__pyx_pw_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_1fib_cython(PyObject *__pyx_self, PyObject *__pyx_arg_n) {\n",
       "  int __pyx_v_n;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"fib_cython (wrapper)\", 0);\n",
       "  assert(__pyx_arg_n); {\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 = 2; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_a7383439b4d9daca4b8a6d569c53a027.fib_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_fib_cython(__pyx_self, ((int)__pyx_v_n));\n",
       "  int __pyx_lineno = 0;\n",
       "  const char *__pyx_filename = NULL;\n",
       "  int __pyx_clineno = 0;\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_fib_cython(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_n) {\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"fib_cython\", 0);\n",
       "  __Pyx_XDECREF(__pyx_r);\n",
       "  __pyx_t_1 = __Pyx_PyInt_From_long(__pyx_f_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_fib_cython(__pyx_v_n, 0)); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_r = __pyx_t_1;\n",
       "  __pyx_t_1 = 0;\n",
       "  goto __pyx_L0;\n",
       "\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_1);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_a7383439b4d9daca4b8a6d569c53a027.fib_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "
+3:     if n<2:
\n", "
  __pyx_t_1 = ((__pyx_v_n < 2) != 0);\n",
       "  if (__pyx_t_1) {\n",
       "/* … */\n",
       "  }\n",
       "
+4:         return n
\n", "
    __pyx_r = __pyx_v_n;\n",
       "    goto __pyx_L0;\n",
       "
+5:     return fib_cython(n-1) + fib_cython(n-2)
\n", "
  __pyx_r = (__pyx_f_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_fib_cython((__pyx_v_n - 1), 0) + __pyx_f_46_cython_magic_a7383439b4d9daca4b8a6d569c53a027_fib_cython((__pyx_v_n - 2), 0));\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 115, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "cpdef long fib_cython(int n):\n", " if n<2:\n", " return n\n", " return fib_cython(n-1) + fib_cython(n-2)" ] }, { "cell_type": "code", "execution_count": 116, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10000 loops, best of 3: 129 µs per loop\n" ] } ], "source": [ "%timeit fib_cython(20)" ] }, { "cell_type": "code", "execution_count": 82, "metadata": { "collapsed": true }, "outputs": [], "source": [ "@njit\n", "def fib_numba(n):\n", " a, b = 0, 1\n", " for i in range(n-1):\n", " a, b = b, a + b\n", " return b" ] }, { "cell_type": "code", "execution_count": 83, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The slowest run took 49263.70 times longer than the fastest. This could mean that an intermediate result is being cached \n", "3 loops, best of 3: 501 ns per loop\n" ] } ], "source": [ "%timeit -r3 -n3 fib_numba(20)" ] }, { "cell_type": "code", "execution_count": 84, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%load_ext cython" ] }, { "cell_type": "code", "execution_count": 123, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_106e06d591bbaf06dba1a9e2a3411245.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.4

\n", "

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

\n", "
 01: 
\n", "
+02: def fib_cython_seq(int n):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_106e06d591bbaf06dba1a9e2a3411245_1fib_cython_seq(PyObject *__pyx_self, PyObject *__pyx_arg_n); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_106e06d591bbaf06dba1a9e2a3411245_1fib_cython_seq = {\"fib_cython_seq\", (PyCFunction)__pyx_pw_46_cython_magic_106e06d591bbaf06dba1a9e2a3411245_1fib_cython_seq, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_106e06d591bbaf06dba1a9e2a3411245_1fib_cython_seq(PyObject *__pyx_self, PyObject *__pyx_arg_n) {\n",
       "  int __pyx_v_n;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"fib_cython_seq (wrapper)\", 0);\n",
       "  assert(__pyx_arg_n); {\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 = 2; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_106e06d591bbaf06dba1a9e2a3411245.fib_cython_seq\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_106e06d591bbaf06dba1a9e2a3411245_fib_cython_seq(__pyx_self, ((int)__pyx_v_n));\n",
       "  int __pyx_lineno = 0;\n",
       "  const char *__pyx_filename = NULL;\n",
       "  int __pyx_clineno = 0;\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_106e06d591bbaf06dba1a9e2a3411245_fib_cython_seq(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_n) {\n",
       "  CYTHON_UNUSED int __pyx_v_i;\n",
       "  long __pyx_v_a;\n",
       "  long __pyx_v_b;\n",
       "  long __pyx_v_tmp;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"fib_cython_seq\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_3);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_106e06d591bbaf06dba1a9e2a3411245.fib_cython_seq\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple_ = PyTuple_Pack(6, __pyx_n_s_n, __pyx_n_s_n, __pyx_n_s_i, __pyx_n_s_a, __pyx_n_s_b, __pyx_n_s_tmp); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_106e06d591bbaf06dba1a9e2a3411245_1fib_cython_seq, NULL, __pyx_n_s_cython_magic_106e06d591bbaf06db); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_fib_cython_seq, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 03:     cdef int i
\n", "
 04:     cdef long a, b, tmp
\n", "
+05:     a = 0
\n", "
  __pyx_v_a = 0;\n",
       "
+06:     b = 1
\n", "
  __pyx_v_b = 1;\n",
       "
+07:     for i in range(n-1):
\n", "
  __pyx_t_1 = (__pyx_v_n - 1);\n",
       "  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {\n",
       "    __pyx_v_i = __pyx_t_2;\n",
       "
+08:         tmp = a
\n", "
    __pyx_v_tmp = __pyx_v_a;\n",
       "
+09:         a = b
\n", "
    __pyx_v_a = __pyx_v_b;\n",
       "
+10:         b += tmp
\n", "
    __pyx_v_b = (__pyx_v_b + __pyx_v_tmp);\n",
       "  }\n",
       "
+11:     return b
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __pyx_t_3 = __Pyx_PyInt_From_long(__pyx_v_b); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __pyx_r = __pyx_t_3;\n",
       "  __pyx_t_3 = 0;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 123, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "def fib_cython_seq(int n):\n", " cdef int i\n", " cdef long a, b, tmp\n", " a = 0\n", " b = 1\n", " for i in range(n-1):\n", " tmp = a\n", " a = b\n", " b += tmp\n", " return b" ] }, { "cell_type": "code", "execution_count": 124, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The slowest run took 15.42 times longer than the fastest. This could mean that an intermediate result is being cached \n", "10000000 loops, best of 3: 122 ns per loop\n" ] } ], "source": [ "%timeit fib_cython_seq(20)" ] }, { "cell_type": "code", "execution_count": 131, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "fib: 1.0\n", "fib_lru: 1151.4\n", "fib_cython: 26.0\n", "fib_numba: 639.7\n", "fib_cython_seq: 1919.0\n" ] } ], "source": [ "report([fib, fib_lru, fib_cython, fib_numba, fib_cython_seq], 20)" ] }, { "cell_type": "code", "execution_count": 442, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6765\n", "6765\n", "6765\n", "6765\n", "6765\n" ] } ], "source": [ "fs = fib, fib_lru, fib_cython, fib_numba, fib_cython_seq\n", "for f in fs:\n", " print(f(20))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parse_int\n", "----" ] }, { "cell_type": "code", "execution_count": 158, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def parse_int():\n", " for i in range(1,1000):\n", " n = random.randint(0,2**31-1)\n", " s = hex(n)\n", "# if s[-1]=='L':\n", "# s = s[0:-1] \n", " m = int(s,16)\n", " assert m == n" ] }, { "cell_type": "code", "execution_count": 142, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100 loops, best of 3: 4.56 ms per loop\n" ] } ], "source": [ "%timeit parse_int()" ] }, { "cell_type": "code", "execution_count": 159, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def parse_int_numpy():\n", " for i in range(1,1000):\n", " n = np.random.randint(0,2**31-1)\n", " s = hex(n) \n", " m = int(s,16)\n", " assert m == n" ] }, { "cell_type": "code", "execution_count": 160, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1000 loops, best of 3: 1.51 ms per loop\n" ] } ], "source": [ "%timeit parse_int_numpy()" ] }, { "cell_type": "code", "execution_count": 169, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_2d3f37e15c7a44b97af38354a036490d.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.4

\n", "

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

\n", "
 01: 
\n", "
+02: import cython
\n", "
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
+03: import numpy as np
\n", "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 04: cimport numpy as np
\n", "
 05: 
\n", "
+06: def parse_int_cython():
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_2d3f37e15c7a44b97af38354a036490d_1parse_int_cython(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_2d3f37e15c7a44b97af38354a036490d_1parse_int_cython = {\"parse_int_cython\", (PyCFunction)__pyx_pw_46_cython_magic_2d3f37e15c7a44b97af38354a036490d_1parse_int_cython, METH_NOARGS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_2d3f37e15c7a44b97af38354a036490d_1parse_int_cython(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"parse_int_cython (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_2d3f37e15c7a44b97af38354a036490d_parse_int_cython(__pyx_self);\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_2d3f37e15c7a44b97af38354a036490d_parse_int_cython(CYTHON_UNUSED PyObject *__pyx_self) {\n",
       "  CYTHON_UNUSED int __pyx_v_i;\n",
       "  int __pyx_v_n;\n",
       "  int __pyx_v_m;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"parse_int_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_r = Py_None; __Pyx_INCREF(Py_None);\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_2);\n",
       "  __Pyx_XDECREF(__pyx_t_3);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_2d3f37e15c7a44b97af38354a036490d.parse_int_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__8 = PyTuple_Pack(3, __pyx_n_s_i, __pyx_n_s_n, __pyx_n_s_m); if (unlikely(!__pyx_tuple__8)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple__8);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__8);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_2d3f37e15c7a44b97af38354a036490d_1parse_int_cython, NULL, __pyx_n_s_cython_magic_2d3f37e15c7a44b97a); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_parse_int_cython, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 07:     cdef int i, n, m
\n", "
+08:     for i in range(1,1000):
\n", "
  for (__pyx_t_1 = 1; __pyx_t_1 < 0x3E8; __pyx_t_1+=1) {\n",
       "    __pyx_v_i = __pyx_t_1;\n",
       "
+09:         n = np.random.randint(0,2**31-1)
\n", "
    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_random); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_randint); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    __pyx_t_4 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "    __pyx_v_n = __pyx_t_4;\n",
       "/* … */\n",
       "  __pyx_tuple_ = PyTuple_Pack(2, __pyx_int_0, __pyx_int_2147483647); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 9; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "
+10:         m = int(hex(n),16)
\n", "
    __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_n); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    __Pyx_GIVEREF(__pyx_t_3);\n",
       "    PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3);\n",
       "    __pyx_t_3 = 0;\n",
       "    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_hex, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    __Pyx_GIVEREF(__pyx_t_3);\n",
       "    PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_3);\n",
       "    __Pyx_INCREF(__pyx_int_16);\n",
       "    __Pyx_GIVEREF(__pyx_int_16);\n",
       "    PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_int_16);\n",
       "    __pyx_t_3 = 0;\n",
       "    __pyx_t_3 = __Pyx_PyObject_Call(((PyObject *)(&PyInt_Type)), __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    __pyx_t_4 = __Pyx_PyInt_As_int(__pyx_t_3); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "    __pyx_v_m = __pyx_t_4;\n",
       "
+11:         assert m == n
\n", "
    #ifndef CYTHON_WITHOUT_ASSERTIONS\n",
       "    if (unlikely(!Py_OptimizeFlag)) {\n",
       "      if (unlikely(!((__pyx_v_m == __pyx_v_n) != 0))) {\n",
       "        PyErr_SetNone(PyExc_AssertionError);\n",
       "        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "      }\n",
       "    }\n",
       "    #endif\n",
       "  }\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 169, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "import cython\n", "import numpy as np\n", "cimport numpy as np\n", "\n", "def parse_int_cython():\n", " cdef int i, n, m\n", " for i in range(1,1000):\n", " n = np.random.randint(0,2**31-1)\n", " m = int(hex(n),16)\n", " assert m == n" ] }, { "cell_type": "code", "execution_count": 170, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1000 loops, best of 3: 1.13 ms per loop\n" ] } ], "source": [ "%timeit parse_int_cython()" ] }, { "cell_type": "code", "execution_count": 175, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "parse_int: 1.0\n", "parse_int_numpy: 2.7\n", "parse_int_cython: 3.2\n" ] } ], "source": [ "report([parse_int, parse_int_numpy, parse_int_cython])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quicksort\n", "----" ] }, { "cell_type": "code", "execution_count": 171, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def qsort_kernel(a, lo, hi):\n", " i = lo\n", " j = hi\n", " while i < hi:\n", " pivot = a[(lo+hi) // 2]\n", " while i <= j:\n", " while a[i] < pivot:\n", " i += 1\n", " while a[j] > pivot:\n", " j -= 1\n", " if i <= j:\n", " a[i], a[j] = a[j], a[i]\n", " i += 1\n", " j -= 1\n", " if lo < j:\n", " qsort_kernel(a, lo, j)\n", " lo = i\n", " j = hi\n", " return a" ] }, { "cell_type": "code", "execution_count": 190, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def benchmark_qsort():\n", " lst = [ random.random() for i in range(1,5000) ]\n", " qsort_kernel(lst, 0, len(lst)-1)" ] }, { "cell_type": "code", "execution_count": 191, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10 loops, best of 3: 23.8 ms per loop\n" ] } ], "source": [ "%timeit benchmark_qsort()" ] }, { "cell_type": "code", "execution_count": 214, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_2e0923d1649b2de5c2ff7f8deca79258.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.4

\n", "

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

\n", "
 01: 
\n", "
+02: import cython
\n", "
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
+03: import numpy as np
\n", "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 04: 
\n", "
 05: @cython.boundscheck(False)
\n", "
 06: @cython.wraparound(False)
\n", "
+07: cdef double[:] qsort_kernel_cython(double[:] a, int lo, int hi):
\n", "
static __Pyx_memviewslice __pyx_f_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_qsort_kernel_cython(__Pyx_memviewslice __pyx_v_a, int __pyx_v_lo, int __pyx_v_hi) {\n",
       "  int __pyx_v_i;\n",
       "  int __pyx_v_j;\n",
       "  double __pyx_v_pivot;\n",
       "  __Pyx_memviewslice __pyx_r = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"qsort_kernel_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_t_11, 1);\n",
       "  __pyx_r.data = NULL;\n",
       "  __pyx_r.memview = NULL;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_2e0923d1649b2de5c2ff7f8deca79258.qsort_kernel_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "\n",
       "  goto __pyx_L2;\n",
       "  __pyx_L0:;\n",
       "  if (unlikely(!__pyx_r.memview)) {\n",
       "    PyErr_SetString(PyExc_TypeError,\"Memoryview return value is not initialized\");\n",
       "  }\n",
       "  __pyx_L2:;\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "
 08:     cdef int i, j
\n", "
 09:     cdef double pivot
\n", "
 10: 
\n", "
+11:     i = lo
\n", "
  __pyx_v_i = __pyx_v_lo;\n",
       "
+12:     j = hi
\n", "
  __pyx_v_j = __pyx_v_hi;\n",
       "
+13:     while i < hi:
\n", "
  while (1) {\n",
       "    __pyx_t_1 = ((__pyx_v_i < __pyx_v_hi) != 0);\n",
       "    if (!__pyx_t_1) break;\n",
       "
+14:         pivot = a[(lo+hi) // 2]
\n", "
    __pyx_t_2 = __Pyx_div_long((__pyx_v_lo + __pyx_v_hi), 2);\n",
       "    __pyx_v_pivot = (*((double *) ( /* dim=0 */ (__pyx_v_a.data + __pyx_t_2 * __pyx_v_a.strides[0]) )));\n",
       "
+15:         while i <= j:
\n", "
    while (1) {\n",
       "      __pyx_t_1 = ((__pyx_v_i <= __pyx_v_j) != 0);\n",
       "      if (!__pyx_t_1) break;\n",
       "
+16:             while a[i] < pivot:
\n", "
      while (1) {\n",
       "        __pyx_t_3 = __pyx_v_i;\n",
       "        __pyx_t_1 = (((*((double *) ( /* dim=0 */ (__pyx_v_a.data + __pyx_t_3 * __pyx_v_a.strides[0]) ))) < __pyx_v_pivot) != 0);\n",
       "        if (!__pyx_t_1) break;\n",
       "
+17:                 i += 1
\n", "
        __pyx_v_i = (__pyx_v_i + 1);\n",
       "      }\n",
       "
+18:             while a[j] > pivot:
\n", "
      while (1) {\n",
       "        __pyx_t_4 = __pyx_v_j;\n",
       "        __pyx_t_1 = (((*((double *) ( /* dim=0 */ (__pyx_v_a.data + __pyx_t_4 * __pyx_v_a.strides[0]) ))) > __pyx_v_pivot) != 0);\n",
       "        if (!__pyx_t_1) break;\n",
       "
+19:                 j -= 1
\n", "
        __pyx_v_j = (__pyx_v_j - 1);\n",
       "      }\n",
       "
+20:             if i <= j:
\n", "
      __pyx_t_1 = ((__pyx_v_i <= __pyx_v_j) != 0);\n",
       "      if (__pyx_t_1) {\n",
       "/* … */\n",
       "      }\n",
       "    }\n",
       "
+21:                 a[i], a[j] = a[j], a[i]
\n", "
        __pyx_t_5 = __pyx_v_j;\n",
       "        __pyx_t_6 = (*((double *) ( /* dim=0 */ (__pyx_v_a.data + __pyx_t_5 * __pyx_v_a.strides[0]) )));\n",
       "        __pyx_t_7 = __pyx_v_i;\n",
       "        __pyx_t_8 = (*((double *) ( /* dim=0 */ (__pyx_v_a.data + __pyx_t_7 * __pyx_v_a.strides[0]) )));\n",
       "        __pyx_t_9 = __pyx_v_i;\n",
       "        *((double *) ( /* dim=0 */ (__pyx_v_a.data + __pyx_t_9 * __pyx_v_a.strides[0]) )) = __pyx_t_6;\n",
       "        __pyx_t_10 = __pyx_v_j;\n",
       "        *((double *) ( /* dim=0 */ (__pyx_v_a.data + __pyx_t_10 * __pyx_v_a.strides[0]) )) = __pyx_t_8;\n",
       "
+22:                 i += 1
\n", "
        __pyx_v_i = (__pyx_v_i + 1);\n",
       "
+23:                 j -= 1
\n", "
        __pyx_v_j = (__pyx_v_j - 1);\n",
       "
+24:         if lo < j:
\n", "
    __pyx_t_1 = ((__pyx_v_lo < __pyx_v_j) != 0);\n",
       "    if (__pyx_t_1) {\n",
       "/* … */\n",
       "    }\n",
       "
+25:             qsort_kernel_cython(a, lo, j)
\n", "
      __pyx_t_11 = __pyx_f_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_qsort_kernel_cython(__pyx_v_a, __pyx_v_lo, __pyx_v_j); if (unlikely(!__pyx_t_11.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 25; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "      __PYX_XDEC_MEMVIEW(&__pyx_t_11, 1);\n",
       "
+26:         lo = i
\n", "
    __pyx_v_lo = __pyx_v_i;\n",
       "
+27:         j = hi
\n", "
    __pyx_v_j = __pyx_v_hi;\n",
       "  }\n",
       "
+28:     return a
\n", "
  __PYX_INC_MEMVIEW(&__pyx_v_a, 0);\n",
       "  __pyx_r = __pyx_v_a;\n",
       "  goto __pyx_L0;\n",
       "
 29: 
\n", "
+30: def benchmark_qsort_cython():
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_1benchmark_qsort_cython(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_1benchmark_qsort_cython = {\"benchmark_qsort_cython\", (PyCFunction)__pyx_pw_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_1benchmark_qsort_cython, METH_NOARGS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_1benchmark_qsort_cython(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"benchmark_qsort_cython (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_benchmark_qsort_cython(__pyx_self);\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_benchmark_qsort_cython(CYTHON_UNUSED PyObject *__pyx_self) {\n",
       "  PyObject *__pyx_v_lst = NULL;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"benchmark_qsort_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_r = Py_None; __Pyx_INCREF(Py_None);\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_1);\n",
       "  __Pyx_XDECREF(__pyx_t_2);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_t_3, 1);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 1);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_2e0923d1649b2de5c2ff7f8deca79258.benchmark_qsort_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XDECREF(__pyx_v_lst);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__15 = PyTuple_Pack(1, __pyx_n_s_lst); if (unlikely(!__pyx_tuple__15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple__15);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__15);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_1benchmark_qsort_cython, NULL, __pyx_n_s_cython_magic_2e0923d1649b2de5c2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_benchmark_qsort_cython, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_codeobj__16 = (PyObject*)__Pyx_PyCode_New(0, 0, 1, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__15, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_cliburn_ipython_cython__c, __pyx_n_s_benchmark_qsort_cython, 30, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__16)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 30; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "
+31:     lst = np.random.random(5000)
\n", "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_random); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_random); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_v_lst = __pyx_t_2;\n",
       "  __pyx_t_2 = 0;\n",
       "/* … */\n",
       "  __pyx_tuple_ = PyTuple_Pack(1, __pyx_int_5000); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 31; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "
+32:     qsort_kernel_cython(lst, 0, len(lst)-1)
\n", "
  __pyx_t_3 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_v_lst);\n",
       "  if (unlikely(!__pyx_t_3.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __pyx_t_4 = PyObject_Length(__pyx_v_lst); if (unlikely(__pyx_t_4 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __pyx_t_5 = __pyx_f_46_cython_magic_2e0923d1649b2de5c2ff7f8deca79258_qsort_kernel_cython(__pyx_t_3, 0, (__pyx_t_4 - 1)); if (unlikely(!__pyx_t_5.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 32; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_t_3, 1);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_t_5, 1);\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 214, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "import cython\n", "import numpy as np\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "cdef double[:] qsort_kernel_cython(double[:] a, int lo, int hi):\n", " cdef int i, j\n", " cdef double pivot\n", "\n", " i = lo\n", " j = hi\n", " while i < hi:\n", " pivot = a[(lo+hi) // 2]\n", " while i <= j:\n", " while a[i] < pivot:\n", " i += 1\n", " while a[j] > pivot:\n", " j -= 1\n", " if i <= j:\n", " a[i], a[j] = a[j], a[i]\n", " i += 1\n", " j -= 1\n", " if lo < j:\n", " qsort_kernel_cython(a, lo, j)\n", " lo = i\n", " j = hi\n", " return a\n", "\n", "def benchmark_qsort_cython():\n", " lst = np.random.random(5000)\n", " qsort_kernel_cython(lst, 0, len(lst)-1)" ] }, { "cell_type": "code", "execution_count": 215, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The slowest run took 4.02 times longer than the fastest. This could mean that an intermediate result is being cached \n", "1000 loops, best of 3: 735 µs per loop\n" ] } ], "source": [ "%timeit benchmark_qsort_cython()" ] }, { "cell_type": "code", "execution_count": 216, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "benchmark_qsort: 1.0\n", "benchmark_qsort_cython: 25.6\n" ] } ], "source": [ "report([benchmark_qsort, benchmark_qsort_cython])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mandel\n", "----" ] }, { "cell_type": "code", "execution_count": 217, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def mandel(z):\n", " maxiter = 80\n", " c = z\n", " for n in range(maxiter):\n", " if abs(z) > 2:\n", " return n\n", " z = z*z + c\n", " return maxiter\n", "\n", "def mandelperf():\n", " r1 = np.linspace(-2.0, 0.5, 26)\n", " r2 = np.linspace(-1.0, 1.0, 21)\n", " return [mandel(complex(r, i)) for r in r1 for i in r2]" ] }, { "cell_type": "code", "execution_count": 219, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "100 loops, best of 3: 6.9 ms per loop\n" ] } ], "source": [ "%timeit mandelperf()" ] }, { "cell_type": "code", "execution_count": 259, "metadata": { "collapsed": true }, "outputs": [], "source": [ "@jit\n", "def mandel_numba(z):\n", " maxiter = 80\n", " c = z\n", " for n in range(maxiter):\n", " if abs(z) > 2:\n", " return n\n", " z = z*z + c\n", " return maxiter\n", "\n", "@jit\n", "def mandelperf_numba():\n", " r1 = np.linspace(-2.0, 0.5, 26)\n", " r2 = np.linspace(-1.0, 1.0, 21)\n", " res = np.empty((26, 21), dtype='int')\n", " for i in range(26):\n", " for j in range(21):\n", " res[i, j] = mandel_numba(complex(r1[i], r2[j]))\n", " return res" ] }, { "cell_type": "code", "execution_count": 260, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The slowest run took 2568.37 times longer than the fastest. This could mean that an intermediate result is being cached \n", "1 loops, best of 3: 156 µs per loop\n" ] } ], "source": [ "%timeit mandelperf_numba()" ] }, { "cell_type": "code", "execution_count": 268, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_49b54927ec0b1cfc50dc062249bda68a.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.4

\n", "

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

\n", "
 01: 
\n", "
+02: cimport cython
\n", "
  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
+03: import numpy as np
\n", "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 04: cimport numpy as np
\n", "
 05: 
\n", "
 06: cdef extern from "complex.h":
\n", "
 07:     double cabs(double complex)
\n", "
 08: 
\n", "
+09: cdef int mandel_cython(double complex z):
\n", "
static int __pyx_f_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_mandel_cython(__pyx_t_double_complex __pyx_v_z) {\n",
       "  int __pyx_v_n;\n",
       "  __pyx_t_double_complex __pyx_v_c;\n",
       "  long __pyx_v_maxiter;\n",
       "  int __pyx_r;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"mandel_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L0:;\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "
 10:     cdef int n
\n", "
 11:     cdef int max_iter
\n", "
 12:     cdef double complex c
\n", "
+13:     maxiter = 80
\n", "
  __pyx_v_maxiter = 80;\n",
       "
+14:     c = z
\n", "
  __pyx_v_c = __pyx_v_z;\n",
       "
+15:     for n in range(maxiter):
\n", "
  __pyx_t_1 = __pyx_v_maxiter;\n",
       "  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {\n",
       "    __pyx_v_n = __pyx_t_2;\n",
       "
+16:         if cabs(z) > 2:
\n", "
    __pyx_t_3 = ((cabs(__pyx_v_z) > 2.0) != 0);\n",
       "    if (__pyx_t_3) {\n",
       "/* … */\n",
       "    }\n",
       "
+17:             return n
\n", "
      __pyx_r = __pyx_v_n;\n",
       "      goto __pyx_L0;\n",
       "
+18:         z = z*z + c
\n", "
    __pyx_v_z = __Pyx_c_sum(__Pyx_c_prod(__pyx_v_z, __pyx_v_z), __pyx_v_c);\n",
       "  }\n",
       "
+19:     return maxiter
\n", "
  __pyx_r = __pyx_v_maxiter;\n",
       "  goto __pyx_L0;\n",
       "
 20: 
\n", "
 21: @cython.boundscheck(False)
\n", "
 22: @cython.wraparound(False)
\n", "
+23: def mandelperf_cython():
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_1mandelperf_cython(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_1mandelperf_cython = {\"mandelperf_cython\", (PyCFunction)__pyx_pw_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_1mandelperf_cython, METH_NOARGS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_1mandelperf_cython(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"mandelperf_cython (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_mandelperf_cython(__pyx_self);\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_mandelperf_cython(CYTHON_UNUSED PyObject *__pyx_self) {\n",
       "  int __pyx_v_i;\n",
       "  int __pyx_v_j;\n",
       "  __Pyx_memviewslice __pyx_v_r1 = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  __Pyx_memviewslice __pyx_v_r2 = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  __Pyx_memviewslice __pyx_v_res = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"mandelperf_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_1);\n",
       "  __Pyx_XDECREF(__pyx_t_2);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_t_3, 1);\n",
       "  __Pyx_XDECREF(__pyx_t_4);\n",
       "  __Pyx_XDECREF(__pyx_t_5);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_t_6, 1);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_49b54927ec0b1cfc50dc062249bda68a.mandelperf_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_v_r1, 1);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_v_r2, 1);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_v_res, 1);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__24 = PyTuple_Pack(5, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_r1, __pyx_n_s_r2, __pyx_n_s_res); if (unlikely(!__pyx_tuple__24)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple__24);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__24);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_1mandelperf_cython, NULL, __pyx_n_s_cython_magic_49b54927ec0b1cfc50); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_mandelperf_cython, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_codeobj__25 = (PyObject*)__Pyx_PyCode_New(0, 0, 5, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__24, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_cliburn_ipython_cython__c, __pyx_n_s_mandelperf_cython, 23, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__25)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "
 24:     cdef int i, j
\n", "
 25: 
\n", "
+26:     cdef double[:] r1 = np.linspace(-2.0, 0.5, 26)
\n", "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_linspace); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple_, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_t_3 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_1);\n",
       "  if (unlikely(!__pyx_t_3.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_v_r1 = __pyx_t_3;\n",
       "  __pyx_t_3.memview = NULL;\n",
       "  __pyx_t_3.data = NULL;\n",
       "/* … */\n",
       "  __pyx_tuple_ = PyTuple_Pack(3, __pyx_float_neg_2_0, __pyx_float_0_5, __pyx_int_26); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 26; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "
+27:     cdef double[:] r2 = np.linspace(-1.0, 1.0, 21)
\n", "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_linspace); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__2, NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_t_3 = __Pyx_PyObject_to_MemoryviewSlice_ds_double(__pyx_t_1);\n",
       "  if (unlikely(!__pyx_t_3.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_v_r2 = __pyx_t_3;\n",
       "  __pyx_t_3.memview = NULL;\n",
       "  __pyx_t_3.data = NULL;\n",
       "/* … */\n",
       "  __pyx_tuple__2 = PyTuple_Pack(3, __pyx_float_neg_1_0, __pyx_float_1_0, __pyx_int_21); if (unlikely(!__pyx_tuple__2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple__2);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__2);\n",
       "
+28:     cdef int[:,:] res = np.empty((26,21), dtype=np.int32)
\n", "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_empty); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "/* … */\n",
       "  __pyx_tuple__3 = PyTuple_Pack(2, __pyx_int_26, __pyx_int_21); if (unlikely(!__pyx_tuple__3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple__3);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__3);\n",
       "  __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_int32); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_5) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple__4, __pyx_t_1); if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_6 = __Pyx_PyObject_to_MemoryviewSlice_dsds_int(__pyx_t_5);\n",
       "  if (unlikely(!__pyx_t_6.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_v_res = __pyx_t_6;\n",
       "  __pyx_t_6.memview = NULL;\n",
       "  __pyx_t_6.data = NULL;\n",
       "  __pyx_tuple__4 = PyTuple_Pack(1, __pyx_tuple__3); if (unlikely(!__pyx_tuple__4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 28; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple__4);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__4);\n",
       "
 29: 
\n", "
+30:     for i in range(26):
\n", "
  for (__pyx_t_7 = 0; __pyx_t_7 < 26; __pyx_t_7+=1) {\n",
       "    __pyx_v_i = __pyx_t_7;\n",
       "
+31:         for j in range(21):
\n", "
    for (__pyx_t_8 = 0; __pyx_t_8 < 21; __pyx_t_8+=1) {\n",
       "      __pyx_v_j = __pyx_t_8;\n",
       "
+32:             res[i,j] = mandel_cython(r1[i] + r2[j]*1j)
\n", "
      __pyx_t_9 = __pyx_v_i;\n",
       "      __pyx_t_10 = __pyx_v_j;\n",
       "      __pyx_t_11 = __pyx_v_i;\n",
       "      __pyx_t_12 = __pyx_v_j;\n",
       "      *((int *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_res.data + __pyx_t_11 * __pyx_v_res.strides[0]) ) + __pyx_t_12 * __pyx_v_res.strides[1]) )) = __pyx_f_46_cython_magic_49b54927ec0b1cfc50dc062249bda68a_mandel_cython(__Pyx_c_sum(__pyx_t_double_complex_from_parts((*((double *) ( /* dim=0 */ (__pyx_v_r1.data + __pyx_t_9 * __pyx_v_r1.strides[0]) ))), 0), __Pyx_c_prod(__pyx_t_double_complex_from_parts((*((double *) ( /* dim=0 */ (__pyx_v_r2.data + __pyx_t_10 * __pyx_v_r2.strides[0]) ))), 0), __pyx_t_double_complex_from_parts(0, 1.0))));\n",
       "    }\n",
       "  }\n",
       "
+33:     return res
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __pyx_t_5 = __pyx_memoryview_fromslice(__pyx_v_res, 2, (PyObject *(*)(char *)) __pyx_memview_get_int, (int (*)(char *, PyObject *)) __pyx_memview_set_int, 0);; if (unlikely(!__pyx_t_5)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 33; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __pyx_r = __pyx_t_5;\n",
       "  __pyx_t_5 = 0;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 268, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "cimport cython\n", "import numpy as np\n", "cimport numpy as np\n", "\n", "cdef extern from \"complex.h\":\n", " double cabs(double complex)\n", "\n", "cdef int mandel_cython(double complex z):\n", " cdef int n\n", " cdef int max_iter\n", " cdef double complex c\n", " maxiter = 80\n", " c = z\n", " for n in range(maxiter):\n", " if cabs(z) > 2:\n", " return n\n", " z = z*z + c\n", " return maxiter\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def mandelperf_cython():\n", " cdef int i, j\n", "\n", " cdef double[:] r1 = np.linspace(-2.0, 0.5, 26)\n", " cdef double[:] r2 = np.linspace(-1.0, 1.0, 21)\n", " cdef int[:,:] res = np.empty((26,21), dtype=np.int32)\n", "\n", " for i in range(26):\n", " for j in range(21):\n", " res[i,j] = mandel_cython(r1[i] + r2[j]*1j)\n", " return res" ] }, { "cell_type": "code", "execution_count": 269, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1000 loops, best of 3: 222 µs per loop\n" ] } ], "source": [ "%timeit mandelperf_cython()" ] }, { "cell_type": "code", "execution_count": 271, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "mandelperf: 1.0\n", "mandelperf_numba: 19.7\n", "mandelperf_cython: 15.4\n" ] } ], "source": [ "report([mandelperf, mandelperf_numba, mandelperf_cython])" ] }, { "cell_type": "code", "execution_count": 454, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 0 0 0 0 0]\n", " [ 0 0 0 0 1 1 2 2 3 3 80 3 3 2 2 1 1 0 0 0 0]\n", " [ 0 0 1 1 2 2 2 3 3 3 80 3 3 3 2 2 2 1 1 0 0]\n", " [ 1 1 2 2 2 2 2 3 3 5 80 5 3 3 2 2 2 2 2 1 1]\n", " [ 1 2 2 2 2 2 2 3 4 5 80 5 4 3 2 2 2 2 2 2 1]\n", " [ 1 2 2 2 2 2 3 4 4 6 80 6 4 4 3 2 2 2 2 2 1]\n", " [ 2 2 2 2 2 2 4 4 5 11 80 11 5 4 4 2 2 2 2 2 2]\n", " [ 2 2 2 2 2 3 6 6 7 13 80 13 7 6 6 3 2 2 2 2 2]\n", " [ 2 2 2 2 2 4 6 15 17 80 80 80 17 15 6 4 2 2 2 2 2]\n", " [ 2 2 2 2 3 4 6 11 80 80 80 80 80 11 6 4 3 2 2 2 2]\n", " [ 2 2 2 3 3 4 6 34 80 80 80 80 80 34 6 4 3 3 2 2 2]\n", " [ 2 2 3 3 4 4 6 10 80 80 80 80 80 10 6 4 4 3 3 2 2]\n", " [ 2 3 3 3 4 5 6 8 14 80 80 80 14 8 6 5 4 3 3 3 2]\n", " [ 2 3 3 4 5 7 10 23 80 80 80 80 80 23 10 7 5 4 3 3 2]\n", " [ 3 3 3 6 11 11 80 80 80 80 80 80 80 80 80 11 11 6 3 3 3]\n", " [ 3 3 4 7 80 80 80 80 80 80 80 80 80 80 80 80 80 7 4 3 3]\n", " [ 3 4 5 7 25 80 80 80 80 80 80 80 80 80 80 80 25 7 5 4 3]\n", " [ 4 5 7 9 80 80 80 80 80 80 80 80 80 80 80 80 80 9 7 5 4]\n", " [ 6 8 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 8 6]\n", " [ 8 23 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 23 8]\n", " [80 7 17 12 80 80 80 80 80 80 80 80 80 80 80 80 80 12 17 7 80]\n", " [ 3 4 5 8 80 80 80 80 80 80 80 80 80 80 80 80 80 8 5 4 3]\n", " [ 3 3 4 5 11 80 80 80 80 80 80 80 80 80 80 80 11 5 4 3 3]\n", " [ 2 3 4 5 14 80 80 80 80 80 11 80 80 80 80 80 14 5 4 3 2]\n", " [ 2 2 3 4 14 6 8 14 30 7 6 7 30 14 8 6 14 4 3 2 2]\n", " [ 1 2 2 3 3 4 4 5 4 4 4 4 4 5 4 4 3 3 2 2 1]] \n", "\n", "[[ 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 0 0 0 0 0]\n", " [ 0 0 0 0 1 1 2 2 3 3 80 3 3 2 2 1 1 0 0 0 0]\n", " [ 0 0 1 1 2 2 2 3 3 3 80 3 3 3 2 2 2 1 1 0 0]\n", " [ 1 1 2 2 2 2 2 3 3 5 80 5 3 3 2 2 2 2 2 1 1]\n", " [ 1 2 2 2 2 2 2 3 4 5 80 5 4 3 2 2 2 2 2 2 1]\n", " [ 1 2 2 2 2 2 3 4 4 6 80 6 4 4 3 2 2 2 2 2 1]\n", " [ 2 2 2 2 2 2 4 4 5 11 80 11 5 4 4 2 2 2 2 2 2]\n", " [ 2 2 2 2 2 3 6 6 7 13 80 13 7 6 6 3 2 2 2 2 2]\n", " [ 2 2 2 2 2 4 6 15 17 80 80 80 17 15 6 4 2 2 2 2 2]\n", " [ 2 2 2 2 3 4 6 11 80 80 80 80 80 11 6 4 3 2 2 2 2]\n", " [ 2 2 2 3 3 4 6 34 80 80 80 80 80 34 6 4 3 3 2 2 2]\n", " [ 2 2 3 3 4 4 6 10 80 80 80 80 80 10 6 4 4 3 3 2 2]\n", " [ 2 3 3 3 4 5 6 8 14 80 80 80 14 8 6 5 4 3 3 3 2]\n", " [ 2 3 3 4 5 7 10 23 80 80 80 80 80 23 10 7 5 4 3 3 2]\n", " [ 3 3 3 6 11 11 80 80 80 80 80 80 80 80 80 11 11 6 3 3 3]\n", " [ 3 3 4 7 80 80 80 80 80 80 80 80 80 80 80 80 80 7 4 3 3]\n", " [ 3 4 5 7 25 80 80 80 80 80 80 80 80 80 80 80 25 7 5 4 3]\n", " [ 4 5 7 9 80 80 80 80 80 80 80 80 80 80 80 80 80 9 7 5 4]\n", " [ 6 8 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 8 6]\n", " [ 8 23 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 23 8]\n", " [80 7 17 12 80 80 80 80 80 80 80 80 80 80 80 80 80 12 17 7 80]\n", " [ 3 4 5 8 80 80 80 80 80 80 80 80 80 80 80 80 80 8 5 4 3]\n", " [ 3 3 4 5 11 80 80 80 80 80 80 80 80 80 80 80 11 5 4 3 3]\n", " [ 2 3 4 5 14 80 80 80 80 80 11 80 80 80 80 80 14 5 4 3 2]\n", " [ 2 2 3 4 14 6 8 14 30 7 6 7 30 14 8 6 14 4 3 2 2]\n", " [ 1 2 2 3 3 4 4 5 4 4 4 4 4 5 4 4 3 3 2 2 1]] \n", "\n", "[[ 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 0 0 0 0 0 0]\n", " [ 0 0 0 0 1 1 2 2 3 3 80 3 3 2 2 1 1 0 0 0 0]\n", " [ 0 0 1 1 2 2 2 3 3 3 80 3 3 3 2 2 2 1 1 0 0]\n", " [ 1 1 2 2 2 2 2 3 3 5 80 5 3 3 2 2 2 2 2 1 1]\n", " [ 1 2 2 2 2 2 2 3 4 5 80 5 4 3 2 2 2 2 2 2 1]\n", " [ 1 2 2 2 2 2 3 4 4 6 80 6 4 4 3 2 2 2 2 2 1]\n", " [ 2 2 2 2 2 2 4 4 5 11 80 11 5 4 4 2 2 2 2 2 2]\n", " [ 2 2 2 2 2 3 6 6 7 13 80 13 7 6 6 3 2 2 2 2 2]\n", " [ 2 2 2 2 2 4 6 15 17 80 80 80 17 15 6 4 2 2 2 2 2]\n", " [ 2 2 2 2 3 4 6 11 80 80 80 80 80 11 6 4 3 2 2 2 2]\n", " [ 2 2 2 3 3 4 6 34 80 80 80 80 80 34 6 4 3 3 2 2 2]\n", " [ 2 2 3 3 4 4 6 10 80 80 80 80 80 10 6 4 4 3 3 2 2]\n", " [ 2 3 3 3 4 5 6 8 14 80 80 80 14 8 6 5 4 3 3 3 2]\n", " [ 2 3 3 4 5 7 10 23 80 80 80 80 80 23 10 7 5 4 3 3 2]\n", " [ 3 3 3 6 11 11 80 80 80 80 80 80 80 80 80 11 11 6 3 3 3]\n", " [ 3 3 4 7 80 80 80 80 80 80 80 80 80 80 80 80 80 7 4 3 3]\n", " [ 3 4 5 7 25 80 80 80 80 80 80 80 80 80 80 80 25 7 5 4 3]\n", " [ 4 5 7 9 80 80 80 80 80 80 80 80 80 80 80 80 80 9 7 5 4]\n", " [ 6 8 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 8 6]\n", " [ 8 23 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 23 8]\n", " [80 7 17 12 80 80 80 80 80 80 80 80 80 80 80 80 80 12 17 7 80]\n", " [ 3 4 5 8 80 80 80 80 80 80 80 80 80 80 80 80 80 8 5 4 3]\n", " [ 3 3 4 5 11 80 80 80 80 80 80 80 80 80 80 80 11 5 4 3 3]\n", " [ 2 3 4 5 14 80 80 80 80 80 11 80 80 80 80 80 14 5 4 3 2]\n", " [ 2 2 3 4 14 6 8 14 30 7 6 7 30 14 8 6 14 4 3 2 2]\n", " [ 1 2 2 3 3 4 4 5 4 4 4 4 4 5 4 4 3 3 2 2 1]] \n", "\n" ] } ], "source": [ "for f in mandelperf, mandelperf_numba, mandelperf_cython:\n", " print(np.reshape(f(), (26,21)), \"\\n\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pi_sum\n", "----" ] }, { "cell_type": "code", "execution_count": 272, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def pisum(t):\n", " sum = 0.0\n", " for j in range(1, 501):\n", " sum = 0.0\n", " for k in range(1, t+1):\n", " sum += 1.0/(k*k)\n", " return sum" ] }, { "cell_type": "code", "execution_count": 273, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 loops, best of 3: 1.33 s per loop\n" ] } ], "source": [ "%timeit pisum(10000)" ] }, { "cell_type": "code", "execution_count": 282, "metadata": { "collapsed": true }, "outputs": [], "source": [ "@jit\n", "def pisum_numba(t):\n", " sum = 0.0\n", " for j in range(1, 501):\n", " sum = 0.0\n", " for k in range(1, t+1):\n", " sum += 1.0/(k*k)\n", " return sum" ] }, { "cell_type": "code", "execution_count": 283, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10 loops, best of 3: 35.8 ms per loop\n" ] } ], "source": [ "%timeit pisum_numba(10000)" ] }, { "cell_type": "code", "execution_count": 298, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_39bd6be55fc470028b8a8a158c919aa6.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.23.4

\n", "

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

\n", "
 01: 
\n", "
 02: cimport cython
\n", "
 03: 
\n", "
 04: @cython.cdivision(True)
\n", "
+05: def pisum_cython(int t):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_39bd6be55fc470028b8a8a158c919aa6_1pisum_cython(PyObject *__pyx_self, PyObject *__pyx_arg_t); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_39bd6be55fc470028b8a8a158c919aa6_1pisum_cython = {\"pisum_cython\", (PyCFunction)__pyx_pw_46_cython_magic_39bd6be55fc470028b8a8a158c919aa6_1pisum_cython, METH_O, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_39bd6be55fc470028b8a8a158c919aa6_1pisum_cython(PyObject *__pyx_self, PyObject *__pyx_arg_t) {\n",
       "  int __pyx_v_t;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"pisum_cython (wrapper)\", 0);\n",
       "  assert(__pyx_arg_t); {\n",
       "    __pyx_v_t = __Pyx_PyInt_As_int(__pyx_arg_t); if (unlikely((__pyx_v_t == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L3_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_39bd6be55fc470028b8a8a158c919aa6.pisum_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return NULL;\n",
       "  __pyx_L4_argument_unpacking_done:;\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_39bd6be55fc470028b8a8a158c919aa6_pisum_cython(__pyx_self, ((int)__pyx_v_t));\n",
       "  int __pyx_lineno = 0;\n",
       "  const char *__pyx_filename = NULL;\n",
       "  int __pyx_clineno = 0;\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_39bd6be55fc470028b8a8a158c919aa6_pisum_cython(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_t) {\n",
       "  double __pyx_v_sum;\n",
       "  CYTHON_UNUSED int __pyx_v_j;\n",
       "  int __pyx_v_k;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"pisum_cython\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_4);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_39bd6be55fc470028b8a8a158c919aa6.pisum_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple_ = PyTuple_Pack(5, __pyx_n_s_t, __pyx_n_s_t, __pyx_n_s_sum, __pyx_n_s_j, __pyx_n_s_k); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple_);\n",
       "  __Pyx_GIVEREF(__pyx_tuple_);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_39bd6be55fc470028b8a8a158c919aa6_1pisum_cython, NULL, __pyx_n_s_cython_magic_39bd6be55fc470028b); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_pisum_cython, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 06:     cdef double sum
\n", "
 07:     cdef int j, k
\n", "
 08: 
\n", "
+09:     for j in range(1, 501):
\n", "
  for (__pyx_t_1 = 1; __pyx_t_1 < 0x1F5; __pyx_t_1+=1) {\n",
       "    __pyx_v_j = __pyx_t_1;\n",
       "
+10:         sum = 0.0
\n", "
    __pyx_v_sum = 0.0;\n",
       "
+11:         for k in range(1, t+1):
\n", "
    __pyx_t_2 = (__pyx_v_t + 1);\n",
       "    for (__pyx_t_3 = 1; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {\n",
       "      __pyx_v_k = __pyx_t_3;\n",
       "
+12:             sum += 1.0/(k*k)
\n", "
      __pyx_v_sum = (__pyx_v_sum + (1.0 / (__pyx_v_k * __pyx_v_k)));\n",
       "    }\n",
       "  }\n",
       "
+13:     return sum
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __pyx_t_4 = PyFloat_FromDouble(__pyx_v_sum); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 13; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __pyx_r = __pyx_t_4;\n",
       "  __pyx_t_4 = 0;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 298, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "cimport cython\n", "\n", "@cython.cdivision(True)\n", "def pisum_cython(int t):\n", " cdef double sum\n", " cdef int j, k\n", "\n", " for j in range(1, 501):\n", " sum = 0.0\n", " for k in range(1, t+1):\n", " sum += 1.0/(k*k)\n", " return sum" ] }, { "cell_type": "code", "execution_count": 299, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10 loops, best of 3: 35.8 ms per loop\n" ] } ], "source": [ "%timeit pisum_cython(10000)" ] }, { "cell_type": "code", "execution_count": 286, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "pisum: 1.0\n", "pisum_numba: 35.6\n", "pisum_cython: 35.6\n" ] } ], "source": [ "report([pisum, pisum_numba, pisum_cython], 10000)" ] }, { "cell_type": "code", "execution_count": 455, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.6448340718480652\n", "1.6448340718480652\n", "1.6448340718480652\n" ] } ], "source": [ "for f in pisum, pisum_numba, pisum_cython:\n", " print(f(10000))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rand_mat_stat\n", "----" ] }, { "cell_type": "code", "execution_count": 287, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def randmatstat(t):\n", " n = 5\n", " v = np.zeros(t)\n", " w = np.zeros(t)\n", " for i in range(1,t):\n", " a = np.random.randn(n, n)\n", " b = np.random.randn(n, n)\n", " c = np.random.randn(n, n)\n", " d = np.random.randn(n, n)\n", " P = np.matrix(np.hstack((a, b, c, d)))\n", " Q = np.matrix(np.vstack((np.hstack((a, b)), np.hstack((c, d)))))\n", " v[i] = np.trace(np.linalg.matrix_power(np.transpose(P)*P, 4))\n", " w[i] = np.trace(np.linalg.matrix_power(np.transpose(Q)*Q, 4))\n", " return (np.std(v)/np.mean(v), np.std(w)/np.mean(w))" ] }, { "cell_type": "code", "execution_count": 288, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 loops, best of 3: 260 ms per loop\n" ] } ], "source": [ "%timeit randmatstat(1000)" ] }, { "cell_type": "code", "execution_count": 391, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def randmatstat_numba(t):\n", " n = 5\n", " v = np.zeros(t)\n", " w = np.zeros(t)\n", " for i in range(1,t):\n", " a, b, c, d = np.random.randn(4, n, n)\n", " P = np.hstack((a, b, c, d))\n", " Q = np.vstack((np.hstack((a, b)), np.hstack((c, d))))\n", "\n", " PTP = P.T.dot(P)\n", " QTQ = Q.T.dot(Q)\n", "\n", " v[i] = np.trace(PTP @ PTP @ PTP @ PTP)\n", " w[i] = np.trace(QTQ @ QTQ @ QTQ @ QTQ)\n", " return (np.std(v)/np.mean(v), np.std(w)/np.mean(w))" ] }, { "cell_type": "code", "execution_count": 393, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def randmatstat_alt(t):\n", " n = 5\n", " v = np.zeros(t)\n", " w = np.zeros(t)\n", "\n", " for i in range(1,t):\n", " a, b, c, d = np.random.randn(4, n, n)\n", " P = np.hstack((a, b, c, d))\n", " Q = np.vstack((np.hstack((a, b)), np.hstack((c, d))))\n", "\n", " P1 = P.T @ P\n", " P2 = P1 @ P1\n", " P4 = P2 @ P2\n", "\n", " Q1 = Q.T @ Q\n", " Q2 = Q1 @ Q1\n", " Q4 = Q2 @ Q2\n", " \n", " v[i] = np.trace(P4)\n", " w[i] = np.trace(Q4)\n", "\n", " return (np.std(v)/np.mean(v), np.std(w)/np.mean(w))" ] }, { "cell_type": "code", "execution_count": 394, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10 loops, best of 3: 131 ms per loop\n" ] } ], "source": [ "%timeit randmatstat_alt(1000)" ] }, { "cell_type": "code", "execution_count": 396, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "randmatstat: 1.0\n", "randmatstat_alt: 2.1\n" ] } ], "source": [ "report([randmatstat, randmatstat_alt], 1000)" ] }, { "cell_type": "code", "execution_count": 458, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(0.72398346943567571, 0.7713214961017032)\n", "(0.72398346943567571, 0.7713214961017032)\n" ] } ], "source": [ "for f in randmatstat, randmatstat_alt:\n", " np.random.seed(123)\n", " print(f(1000))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rand_mat_mul\n", "----" ] }, { "cell_type": "code", "execution_count": 289, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def randmatmul(n):\n", " A = np.random.rand(n,n)\n", " B = np.random.rand(n,n)\n", " return np.dot(A,B)" ] }, { "cell_type": "code", "execution_count": 290, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10 loops, best of 3: 81 ms per loop\n" ] } ], "source": [ "%timeit randmatmul(1000)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comparison\n", "----\n", "\n", "These benchmarks don't mean very much - they were constructed by the Julia team presumably to show off Julia's strengths, and are used here just to illustrate basic Python optimization techniques. In some case (quicksort, mandel, pi_sum), this gives dramatic performance improvements but in other cases (parse_int, rand_mat_stat) there is less improvement. For fib, the speed depends on the algorithm used for calculation, and whether caching is enabled in the recursive case. The final test rand_mat_mul basically depends on the linear algebra library installed (blas, mkl, atlas) and is not really a comparison across languages.\n", "\n", "Julia certainly does look promising, and we might include mix in some Julia code in future courses." ] }, { "cell_type": "code", "execution_count": 459, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
JuliaPythonP2JSU
1fib2.1177.7636.851919.00
2parse_int1.4517.0211.743.20
3quicksort1.1532.8928.6025.60
4mandel0.7915.3219.3919.70
5pi_sum1.0021.9921.9935.60
6rand_mat_stat1.6617.9310.802.10
7rand_mat_mul1.021.141.121.00
\n", "
" ], "text/plain": [ " Julia Python P2J SU\n", "1 fib 2.11 77.76 36.85 1919.00\n", "2 parse_int 1.45 17.02 11.74 3.20\n", "3 quicksort 1.15 32.89 28.60 25.60\n", "4 mandel 0.79 15.32 19.39 19.70\n", "5 pi_sum 1.00 21.99 21.99 35.60\n", "6 rand_mat_stat 1.66 17.93 10.80 2.10\n", "7 rand_mat_mul 1.02 1.14 1.12 1.00" ] }, "execution_count": 459, "metadata": {}, "output_type": "execute_result" } ], "source": [ "benchmarks['P2J'] = benchmarks.Python / benchmarks.Julia\n", "benchmarks['SU'] = [1919.0, 3.2, 25.6, 19.7, 35.6, 2.1, 1.0]\n", "pd.options.display.float_format = '{:.2f}'.format\n", "benchmarks.ix[:, [0,2,3,-2,-1]]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }