{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Cython\n", "====\n", "\n", "Cython is an \"optimizing static compiler \" that combines Python with C to generate optimized code. Since Cython is a superset of Python, all valid Python programs are also valid Cython programs. However, by providing hints and static typing, we can get much faster programs. Note that while `numba` often provides similar speedups with less work,, an advantage of Cython is that it is easy to distribute optimized Cython modules since they can be built with the standard Python `setup.py` script.\n", "\n", "We have already seen how to use Cython to wrap C and C++ functions from existing libraries. Here we will see how to use Cython to speed up Python functions. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Resources\n", "\n", "- [Cython documentation](http://docs.cython.org/index.html)\n", "- [Cython: A guide for Python programmers](http://www.amazon.com/Cython-Kurt-W-Smith/dp/1491901551)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Utility function for timing functions**" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import time" ] }, { "cell_type": "code", "execution_count": 2, "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": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def report(fs, *args, **kwargs):\n", " ans, t = timer(fs[0], *args, **kwargs)\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": [ "Incremental improvements\n", "----\n", "\n", "Generally, we start with a pure Python function, run it through Cython with the annotate `-a` flag, and incrementally modify the code until the yellow parts are minimized." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How to build Cython modules\n", "----\n", "\n", "From [official docs](http://docs.cython.org/index.html)\n", "\n", "Using Cython consists of these steps:\n", "\n", "- Write a .pyx source file\n", "- Run the Cython compiler to generate a C file\n", "- Run a C compiler to generate a compiled library\n", "- Run the Python interpreter and ask it to import the module\n", "\n", "In the Jupyter notebook, we can use the `%%cython` cell magic to automate these steps." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%load_ext cython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Matrix multiplication example" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def matrix_multiply(u, v, res):\n", " m, n = u.shape\n", " n, p = v.shape\n", " for i in range(m):\n", " for j in range(p):\n", " res[i,j] = 0\n", " for k in range(n):\n", " res[i,j] += u[i,k] * v[k,j]\n", " return res" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": true }, "outputs": [], "source": [ "u = np.random.random((10,20))\n", "v = np.random.random((20,5))" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[ 6.23206064, 5.02617378, 5.24195758, 2.99169761, 3.9401661 ],\n", " [ 5.44535991, 4.27051957, 5.09974356, 3.19339314, 4.4845852 ],\n", " [ 6.52695763, 4.9649044 , 5.66479652, 3.73440473, 5.18981681],\n", " [ 5.47233217, 4.18485264, 4.34374265, 3.13801525, 4.27412098],\n", " [ 6.35742705, 5.02912642, 5.92758324, 3.56743263, 4.73902924],\n", " [ 5.57344818, 4.22251167, 4.12379554, 2.30636947, 4.08916241],\n", " [ 3.61588766, 2.28101131, 3.1266391 , 2.32380826, 3.02340269],\n", " [ 4.96325909, 3.24325894, 4.12918062, 2.34622065, 3.23494718],\n", " [ 5.561466 , 4.25910586, 4.87880398, 3.26787812, 4.11423797],\n", " [ 4.88445295, 4.11701615, 4.73502154, 3.06760703, 4.06496649]])" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "res = np.zeros((u.shape[0], v.shape[1]))\n", "matrix_multiply(u, v, res)" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3 loops, best of 3: 1.02 ms per loop\n" ] } ], "source": [ "res = np.zeros((u.shape[0], v.shape[1]))\n", "%timeit -r3 -n3 matrix_multiply(u, v, res)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using Cython annnotations to identify bottlenecks" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_dc556b01a37ea0cde5e13c6046d1e4f6.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 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 = 2; __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 = 2; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 03: 
\n", "
+04: def matrix_multiply1(u, v, res):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_dc556b01a37ea0cde5e13c6046d1e4f6_1matrix_multiply1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_dc556b01a37ea0cde5e13c6046d1e4f6_1matrix_multiply1 = {\"matrix_multiply1\", (PyCFunction)__pyx_pw_46_cython_magic_dc556b01a37ea0cde5e13c6046d1e4f6_1matrix_multiply1, METH_VARARGS|METH_KEYWORDS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_dc556b01a37ea0cde5e13c6046d1e4f6_1matrix_multiply1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
       "  PyObject *__pyx_v_u = 0;\n",
       "  PyObject *__pyx_v_v = 0;\n",
       "  PyObject *__pyx_v_res = 0;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"matrix_multiply1 (wrapper)\", 0);\n",
       "  {\n",
       "    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_u,&__pyx_n_s_v,&__pyx_n_s_res,0};\n",
       "    PyObject* values[3] = {0,0,0};\n",
       "    if (unlikely(__pyx_kwds)) {\n",
       "      Py_ssize_t kw_args;\n",
       "      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);\n",
       "      switch (pos_args) {\n",
       "        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
       "        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
       "        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
       "        case  0: break;\n",
       "        default: goto __pyx_L5_argtuple_error;\n",
       "      }\n",
       "      kw_args = PyDict_Size(__pyx_kwds);\n",
       "      switch (pos_args) {\n",
       "        case  0:\n",
       "        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_u)) != 0)) kw_args--;\n",
       "        else goto __pyx_L5_argtuple_error;\n",
       "        case  1:\n",
       "        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_v)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "        case  2:\n",
       "        if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_res)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "      }\n",
       "      if (unlikely(kw_args > 0)) {\n",
       "        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"matrix_multiply1\") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "      }\n",
       "    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {\n",
       "      goto __pyx_L5_argtuple_error;\n",
       "    } else {\n",
       "      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
       "      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
       "      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
       "    }\n",
       "    __pyx_v_u = values[0];\n",
       "    __pyx_v_v = values[1];\n",
       "    __pyx_v_res = values[2];\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L5_argtuple_error:;\n",
       "  __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "  __pyx_L3_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_dc556b01a37ea0cde5e13c6046d1e4f6.matrix_multiply1\", __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_dc556b01a37ea0cde5e13c6046d1e4f6_matrix_multiply1(__pyx_self, __pyx_v_u, __pyx_v_v, __pyx_v_res);\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_dc556b01a37ea0cde5e13c6046d1e4f6_matrix_multiply1(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_u, PyObject *__pyx_v_v, PyObject *__pyx_v_res) {\n",
       "  PyObject *__pyx_v_m = NULL;\n",
       "  PyObject *__pyx_v_n = NULL;\n",
       "  PyObject *__pyx_v_p = NULL;\n",
       "  PyObject *__pyx_v_i = NULL;\n",
       "  PyObject *__pyx_v_j = NULL;\n",
       "  PyObject *__pyx_v_k = NULL;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"matrix_multiply1\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_L1_error:;\n",
       "  __Pyx_XDECREF(__pyx_t_1);\n",
       "  __Pyx_XDECREF(__pyx_t_2);\n",
       "  __Pyx_XDECREF(__pyx_t_3);\n",
       "  __Pyx_XDECREF(__pyx_t_4);\n",
       "  __Pyx_XDECREF(__pyx_t_12);\n",
       "  __Pyx_XDECREF(__pyx_t_13);\n",
       "  __Pyx_XDECREF(__pyx_t_14);\n",
       "  __Pyx_XDECREF(__pyx_t_15);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_dc556b01a37ea0cde5e13c6046d1e4f6.matrix_multiply1\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XDECREF(__pyx_v_m);\n",
       "  __Pyx_XDECREF(__pyx_v_n);\n",
       "  __Pyx_XDECREF(__pyx_v_p);\n",
       "  __Pyx_XDECREF(__pyx_v_i);\n",
       "  __Pyx_XDECREF(__pyx_v_j);\n",
       "  __Pyx_XDECREF(__pyx_v_k);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple_ = PyTuple_Pack(9, __pyx_n_s_u, __pyx_n_s_v, __pyx_n_s_res, __pyx_n_s_m, __pyx_n_s_n, __pyx_n_s_p, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_k); if (unlikely(!__pyx_tuple_)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __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_dc556b01a37ea0cde5e13c6046d1e4f6_1matrix_multiply1, NULL, __pyx_n_s_cython_magic_dc556b01a37ea0cde5); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_matrix_multiply1, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 4; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
+05:     m, n = u.shape
\n", "
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_u, __pyx_n_s_shape); 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 ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {\n",
       "    PyObject* sequence = __pyx_t_1;\n",
       "    #if CYTHON_COMPILING_IN_CPYTHON\n",
       "    Py_ssize_t size = Py_SIZE(sequence);\n",
       "    #else\n",
       "    Py_ssize_t size = PySequence_Size(sequence);\n",
       "    #endif\n",
       "    if (unlikely(size != 2)) {\n",
       "      if (size > 2) __Pyx_RaiseTooManyValuesError(2);\n",
       "      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);\n",
       "      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    }\n",
       "    #if CYTHON_COMPILING_IN_CPYTHON\n",
       "    if (likely(PyTuple_CheckExact(sequence))) {\n",
       "      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); \n",
       "      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); \n",
       "    } else {\n",
       "      __pyx_t_2 = PyList_GET_ITEM(sequence, 0); \n",
       "      __pyx_t_3 = PyList_GET_ITEM(sequence, 1); \n",
       "    }\n",
       "    __Pyx_INCREF(__pyx_t_2);\n",
       "    __Pyx_INCREF(__pyx_t_3);\n",
       "    #else\n",
       "    __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    #endif\n",
       "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  } else {\n",
       "    Py_ssize_t index = -1;\n",
       "    __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_4);\n",
       "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "    __pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext;\n",
       "    index = 0; __pyx_t_2 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_2)) goto __pyx_L3_unpacking_failed;\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    index = 1; __pyx_t_3 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L3_unpacking_failed;\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_4), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __pyx_t_5 = NULL;\n",
       "    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    goto __pyx_L4_unpacking_done;\n",
       "    __pyx_L3_unpacking_failed:;\n",
       "    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    __pyx_t_5 = NULL;\n",
       "    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);\n",
       "    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 5; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __pyx_L4_unpacking_done:;\n",
       "  }\n",
       "  __pyx_v_m = __pyx_t_2;\n",
       "  __pyx_t_2 = 0;\n",
       "  __pyx_v_n = __pyx_t_3;\n",
       "  __pyx_t_3 = 0;\n",
       "
+06:     n, p = v.shape
\n", "
  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_v_v, __pyx_n_s_shape); 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 ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {\n",
       "    PyObject* sequence = __pyx_t_1;\n",
       "    #if CYTHON_COMPILING_IN_CPYTHON\n",
       "    Py_ssize_t size = Py_SIZE(sequence);\n",
       "    #else\n",
       "    Py_ssize_t size = PySequence_Size(sequence);\n",
       "    #endif\n",
       "    if (unlikely(size != 2)) {\n",
       "      if (size > 2) __Pyx_RaiseTooManyValuesError(2);\n",
       "      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);\n",
       "      {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    }\n",
       "    #if CYTHON_COMPILING_IN_CPYTHON\n",
       "    if (likely(PyTuple_CheckExact(sequence))) {\n",
       "      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); \n",
       "      __pyx_t_2 = PyTuple_GET_ITEM(sequence, 1); \n",
       "    } else {\n",
       "      __pyx_t_3 = PyList_GET_ITEM(sequence, 0); \n",
       "      __pyx_t_2 = PyList_GET_ITEM(sequence, 1); \n",
       "    }\n",
       "    __Pyx_INCREF(__pyx_t_3);\n",
       "    __Pyx_INCREF(__pyx_t_2);\n",
       "    #else\n",
       "    __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    __pyx_t_2 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    #endif\n",
       "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  } else {\n",
       "    Py_ssize_t index = -1;\n",
       "    __pyx_t_4 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_4);\n",
       "    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "    __pyx_t_5 = Py_TYPE(__pyx_t_4)->tp_iternext;\n",
       "    index = 0; __pyx_t_3 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_3)) goto __pyx_L5_unpacking_failed;\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    index = 1; __pyx_t_2 = __pyx_t_5(__pyx_t_4); if (unlikely(!__pyx_t_2)) goto __pyx_L5_unpacking_failed;\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    if (__Pyx_IternextUnpackEndCheck(__pyx_t_5(__pyx_t_4), 2) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __pyx_t_5 = NULL;\n",
       "    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    goto __pyx_L6_unpacking_done;\n",
       "    __pyx_L5_unpacking_failed:;\n",
       "    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    __pyx_t_5 = NULL;\n",
       "    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);\n",
       "    {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __pyx_L6_unpacking_done:;\n",
       "  }\n",
       "  __Pyx_DECREF_SET(__pyx_v_n, __pyx_t_3);\n",
       "  __pyx_t_3 = 0;\n",
       "  __pyx_v_p = __pyx_t_2;\n",
       "  __pyx_t_2 = 0;\n",
       "
+07:     for i in range(m):
\n", "
  __pyx_t_1 = PyTuple_New(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_INCREF(__pyx_v_m);\n",
       "  __Pyx_GIVEREF(__pyx_v_m);\n",
       "  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_m);\n",
       "  __pyx_t_2 = __Pyx_PyObject_Call(__pyx_builtin_range, __pyx_t_1, NULL); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {\n",
       "    __pyx_t_1 = __pyx_t_2; __Pyx_INCREF(__pyx_t_1); __pyx_t_6 = 0;\n",
       "    __pyx_t_7 = NULL;\n",
       "  } else {\n",
       "    __pyx_t_6 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_1);\n",
       "    __pyx_t_7 = Py_TYPE(__pyx_t_1)->tp_iternext; if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  for (;;) {\n",
       "    if (likely(!__pyx_t_7)) {\n",
       "      if (likely(PyList_CheckExact(__pyx_t_1))) {\n",
       "        if (__pyx_t_6 >= PyList_GET_SIZE(__pyx_t_1)) break;\n",
       "        #if CYTHON_COMPILING_IN_CPYTHON\n",
       "        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_6); __Pyx_INCREF(__pyx_t_2); __pyx_t_6++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        #else\n",
       "        __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        __Pyx_GOTREF(__pyx_t_2);\n",
       "        #endif\n",
       "      } else {\n",
       "        if (__pyx_t_6 >= PyTuple_GET_SIZE(__pyx_t_1)) break;\n",
       "        #if CYTHON_COMPILING_IN_CPYTHON\n",
       "        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_6); __Pyx_INCREF(__pyx_t_2); __pyx_t_6++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        #else\n",
       "        __pyx_t_2 = PySequence_ITEM(__pyx_t_1, __pyx_t_6); __pyx_t_6++; if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        __Pyx_GOTREF(__pyx_t_2);\n",
       "        #endif\n",
       "      }\n",
       "    } else {\n",
       "      __pyx_t_2 = __pyx_t_7(__pyx_t_1);\n",
       "      if (unlikely(!__pyx_t_2)) {\n",
       "        PyObject* exc_type = PyErr_Occurred();\n",
       "        if (exc_type) {\n",
       "          if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();\n",
       "          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        }\n",
       "        break;\n",
       "      }\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "    }\n",
       "    __Pyx_XDECREF_SET(__pyx_v_i, __pyx_t_2);\n",
       "    __pyx_t_2 = 0;\n",
       "/* … */\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
+08:         for j in range(p):
\n", "
    __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "    __Pyx_INCREF(__pyx_v_p);\n",
       "    __Pyx_GIVEREF(__pyx_v_p);\n",
       "    PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_v_p);\n",
       "    __pyx_t_3 = __Pyx_PyObject_Call(__pyx_builtin_range, __pyx_t_2, NULL); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    __Pyx_GOTREF(__pyx_t_3);\n",
       "    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) {\n",
       "      __pyx_t_2 = __pyx_t_3; __Pyx_INCREF(__pyx_t_2); __pyx_t_8 = 0;\n",
       "      __pyx_t_9 = NULL;\n",
       "    } else {\n",
       "      __pyx_t_8 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __pyx_t_9 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "    }\n",
       "    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "    for (;;) {\n",
       "      if (likely(!__pyx_t_9)) {\n",
       "        if (likely(PyList_CheckExact(__pyx_t_2))) {\n",
       "          if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_2)) break;\n",
       "          #if CYTHON_COMPILING_IN_CPYTHON\n",
       "          __pyx_t_3 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "          #else\n",
       "          __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "          __Pyx_GOTREF(__pyx_t_3);\n",
       "          #endif\n",
       "        } else {\n",
       "          if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_2)) break;\n",
       "          #if CYTHON_COMPILING_IN_CPYTHON\n",
       "          __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "          #else\n",
       "          __pyx_t_3 = PySequence_ITEM(__pyx_t_2, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "          __Pyx_GOTREF(__pyx_t_3);\n",
       "          #endif\n",
       "        }\n",
       "      } else {\n",
       "        __pyx_t_3 = __pyx_t_9(__pyx_t_2);\n",
       "        if (unlikely(!__pyx_t_3)) {\n",
       "          PyObject* exc_type = PyErr_Occurred();\n",
       "          if (exc_type) {\n",
       "            if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();\n",
       "            else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 8; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "          }\n",
       "          break;\n",
       "        }\n",
       "        __Pyx_GOTREF(__pyx_t_3);\n",
       "      }\n",
       "      __Pyx_XDECREF_SET(__pyx_v_j, __pyx_t_3);\n",
       "      __pyx_t_3 = 0;\n",
       "/* … */\n",
       "    }\n",
       "    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "
+09:             res[i,j] = 0
\n", "
      __pyx_t_3 = PyTuple_New(2); 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_INCREF(__pyx_v_i);\n",
       "      __Pyx_GIVEREF(__pyx_v_i);\n",
       "      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_i);\n",
       "      __Pyx_INCREF(__pyx_v_j);\n",
       "      __Pyx_GIVEREF(__pyx_v_j);\n",
       "      PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_j);\n",
       "      if (unlikely(PyObject_SetItem(__pyx_v_res, __pyx_t_3, __pyx_int_0) < 0)) {__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",
       "
+10:             for k in range(n):
\n", "
      __pyx_t_3 = PyTuple_New(1); 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_INCREF(__pyx_v_n);\n",
       "      __Pyx_GIVEREF(__pyx_v_n);\n",
       "      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_n);\n",
       "      __pyx_t_4 = __Pyx_PyObject_Call(__pyx_builtin_range, __pyx_t_3, NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "      __Pyx_GOTREF(__pyx_t_4);\n",
       "      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "      if (likely(PyList_CheckExact(__pyx_t_4)) || PyTuple_CheckExact(__pyx_t_4)) {\n",
       "        __pyx_t_3 = __pyx_t_4; __Pyx_INCREF(__pyx_t_3); __pyx_t_10 = 0;\n",
       "        __pyx_t_11 = NULL;\n",
       "      } else {\n",
       "        __pyx_t_10 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_4); 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_11 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "      }\n",
       "      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "      for (;;) {\n",
       "        if (likely(!__pyx_t_11)) {\n",
       "          if (likely(PyList_CheckExact(__pyx_t_3))) {\n",
       "            if (__pyx_t_10 >= PyList_GET_SIZE(__pyx_t_3)) break;\n",
       "            #if CYTHON_COMPILING_IN_CPYTHON\n",
       "            __pyx_t_4 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_10); __Pyx_INCREF(__pyx_t_4); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "            #else\n",
       "            __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "            __Pyx_GOTREF(__pyx_t_4);\n",
       "            #endif\n",
       "          } else {\n",
       "            if (__pyx_t_10 >= PyTuple_GET_SIZE(__pyx_t_3)) break;\n",
       "            #if CYTHON_COMPILING_IN_CPYTHON\n",
       "            __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_10); __Pyx_INCREF(__pyx_t_4); __pyx_t_10++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "            #else\n",
       "            __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_10); __pyx_t_10++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "            __Pyx_GOTREF(__pyx_t_4);\n",
       "            #endif\n",
       "          }\n",
       "        } else {\n",
       "          __pyx_t_4 = __pyx_t_11(__pyx_t_3);\n",
       "          if (unlikely(!__pyx_t_4)) {\n",
       "            PyObject* exc_type = PyErr_Occurred();\n",
       "            if (exc_type) {\n",
       "              if (likely(exc_type == PyExc_StopIteration || PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();\n",
       "              else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 10; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "            }\n",
       "            break;\n",
       "          }\n",
       "          __Pyx_GOTREF(__pyx_t_4);\n",
       "        }\n",
       "        __Pyx_XDECREF_SET(__pyx_v_k, __pyx_t_4);\n",
       "        __pyx_t_4 = 0;\n",
       "/* … */\n",
       "      }\n",
       "      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "
+11:                 res[i,j] += u[i,k] * v[k,j]
\n", "
        __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        __Pyx_GOTREF(__pyx_t_4);\n",
       "        __Pyx_INCREF(__pyx_v_i);\n",
       "        __Pyx_GIVEREF(__pyx_v_i);\n",
       "        PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_i);\n",
       "        __Pyx_INCREF(__pyx_v_j);\n",
       "        __Pyx_GIVEREF(__pyx_v_j);\n",
       "        PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_j);\n",
       "        __pyx_t_12 = PyObject_GetItem(__pyx_v_res, __pyx_t_4); if (unlikely(__pyx_t_12 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;};\n",
       "        __Pyx_GOTREF(__pyx_t_12);\n",
       "        __pyx_t_13 = PyTuple_New(2); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        __Pyx_GOTREF(__pyx_t_13);\n",
       "        __Pyx_INCREF(__pyx_v_i);\n",
       "        __Pyx_GIVEREF(__pyx_v_i);\n",
       "        PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_v_i);\n",
       "        __Pyx_INCREF(__pyx_v_k);\n",
       "        __Pyx_GIVEREF(__pyx_v_k);\n",
       "        PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_v_k);\n",
       "        __pyx_t_14 = PyObject_GetItem(__pyx_v_u, __pyx_t_13); if (unlikely(__pyx_t_14 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;};\n",
       "        __Pyx_GOTREF(__pyx_t_14);\n",
       "        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;\n",
       "        __pyx_t_13 = PyTuple_New(2); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        __Pyx_GOTREF(__pyx_t_13);\n",
       "        __Pyx_INCREF(__pyx_v_k);\n",
       "        __Pyx_GIVEREF(__pyx_v_k);\n",
       "        PyTuple_SET_ITEM(__pyx_t_13, 0, __pyx_v_k);\n",
       "        __Pyx_INCREF(__pyx_v_j);\n",
       "        __Pyx_GIVEREF(__pyx_v_j);\n",
       "        PyTuple_SET_ITEM(__pyx_t_13, 1, __pyx_v_j);\n",
       "        __pyx_t_15 = PyObject_GetItem(__pyx_v_v, __pyx_t_13); if (unlikely(__pyx_t_15 == NULL)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;};\n",
       "        __Pyx_GOTREF(__pyx_t_15);\n",
       "        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;\n",
       "        __pyx_t_13 = PyNumber_Multiply(__pyx_t_14, __pyx_t_15); if (unlikely(!__pyx_t_13)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        __Pyx_GOTREF(__pyx_t_13);\n",
       "        __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;\n",
       "        __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;\n",
       "        __pyx_t_15 = PyNumber_InPlaceAdd(__pyx_t_12, __pyx_t_13); if (unlikely(!__pyx_t_15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        __Pyx_GOTREF(__pyx_t_15);\n",
       "        __Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;\n",
       "        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;\n",
       "        if (unlikely(PyObject_SetItem(__pyx_v_res, __pyx_t_4, __pyx_t_15) < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 11; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "        __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;\n",
       "        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "
+12:     return res
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __Pyx_INCREF(__pyx_v_res);\n",
       "  __pyx_r = __pyx_v_res;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "import numpy as np\n", "\n", "def matrix_multiply1(u, v, res):\n", " m, n = u.shape\n", " n, p = v.shape\n", " for i in range(m):\n", " for j in range(p):\n", " res[i,j] = 0\n", " for k in range(n):\n", " res[i,j] += u[i,k] * v[k,j]\n", " return res" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Using Cython cdefs and directives" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_2eaa3f4b6feee4e8bc849d802110ebca.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: 
\n", "
 04: @cython.boundscheck(False)
\n", "
 05: @cython.wraparound(False)
\n", "
+06: def matrix_multiply1(double[:,:] u, double[:, :] v, double[:, :] res):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_2eaa3f4b6feee4e8bc849d802110ebca_1matrix_multiply1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_2eaa3f4b6feee4e8bc849d802110ebca_1matrix_multiply1 = {\"matrix_multiply1\", (PyCFunction)__pyx_pw_46_cython_magic_2eaa3f4b6feee4e8bc849d802110ebca_1matrix_multiply1, METH_VARARGS|METH_KEYWORDS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_2eaa3f4b6feee4e8bc849d802110ebca_1matrix_multiply1(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
       "  __Pyx_memviewslice __pyx_v_u = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  __Pyx_memviewslice __pyx_v_v = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  __Pyx_memviewslice __pyx_v_res = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"matrix_multiply1 (wrapper)\", 0);\n",
       "  {\n",
       "    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_u,&__pyx_n_s_v,&__pyx_n_s_res,0};\n",
       "    PyObject* values[3] = {0,0,0};\n",
       "    if (unlikely(__pyx_kwds)) {\n",
       "      Py_ssize_t kw_args;\n",
       "      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);\n",
       "      switch (pos_args) {\n",
       "        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
       "        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
       "        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
       "        case  0: break;\n",
       "        default: goto __pyx_L5_argtuple_error;\n",
       "      }\n",
       "      kw_args = PyDict_Size(__pyx_kwds);\n",
       "      switch (pos_args) {\n",
       "        case  0:\n",
       "        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_u)) != 0)) kw_args--;\n",
       "        else goto __pyx_L5_argtuple_error;\n",
       "        case  1:\n",
       "        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_v)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "        case  2:\n",
       "        if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_res)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "      }\n",
       "      if (unlikely(kw_args > 0)) {\n",
       "        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"matrix_multiply1\") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "      }\n",
       "    } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {\n",
       "      goto __pyx_L5_argtuple_error;\n",
       "    } else {\n",
       "      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
       "      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
       "      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
       "    }\n",
       "    __pyx_v_u = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[0]); if (unlikely(!__pyx_v_u.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "    __pyx_v_v = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[1]); if (unlikely(!__pyx_v_v.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "    __pyx_v_res = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[2]); if (unlikely(!__pyx_v_res.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L5_argtuple_error:;\n",
       "  __Pyx_RaiseArgtupleInvalid(\"matrix_multiply1\", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "  __pyx_L3_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_2eaa3f4b6feee4e8bc849d802110ebca.matrix_multiply1\", __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_2eaa3f4b6feee4e8bc849d802110ebca_matrix_multiply1(__pyx_self, __pyx_v_u, __pyx_v_v, __pyx_v_res);\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_2eaa3f4b6feee4e8bc849d802110ebca_matrix_multiply1(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_u, __Pyx_memviewslice __pyx_v_v, __Pyx_memviewslice __pyx_v_res) {\n",
       "  int __pyx_v_i;\n",
       "  int __pyx_v_j;\n",
       "  int __pyx_v_k;\n",
       "  int __pyx_v_m;\n",
       "  int __pyx_v_n;\n",
       "  int __pyx_v_p;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"matrix_multiply1\", 0);\n",
       "/* … */\n",
       "  /* function exit code */\n",
       "  __pyx_r = Py_None; __Pyx_INCREF(Py_None);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_v_u, 1);\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_v_v, 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__14 = PyTuple_Pack(9, __pyx_n_s_u, __pyx_n_s_v, __pyx_n_s_res, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_k, __pyx_n_s_m, __pyx_n_s_n, __pyx_n_s_p); if (unlikely(!__pyx_tuple__14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple__14);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__14);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_2eaa3f4b6feee4e8bc849d802110ebca_1matrix_multiply1, NULL, __pyx_n_s_cython_magic_2eaa3f4b6feee4e8bc); 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_matrix_multiply1, __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",
       "  __pyx_codeobj__15 = (PyObject*)__Pyx_PyCode_New(3, 0, 9, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_cliburn_ipython_cython__c, __pyx_n_s_matrix_multiply1, 6, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 6; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "
 07:     cdef int i, j, k
\n", "
 08:     cdef int m, n, p
\n", "
 09: 
\n", "
+10:     m = u.shape[0]
\n", "
  __pyx_v_m = (__pyx_v_u.shape[0]);\n",
       "
+11:     n = u.shape[1]
\n", "
  __pyx_v_n = (__pyx_v_u.shape[1]);\n",
       "
+12:     p = v.shape[1]
\n", "
  __pyx_v_p = (__pyx_v_v.shape[1]);\n",
       "
 13: 
\n", "
+14:     with cython.nogil:
\n", "
  {\n",
       "      #ifdef WITH_THREAD\n",
       "      PyThreadState *_save;\n",
       "      Py_UNBLOCK_THREADS\n",
       "      #endif\n",
       "      /*try:*/ {\n",
       "/* … */\n",
       "      /*finally:*/ {\n",
       "        /*normal exit:*/{\n",
       "          #ifdef WITH_THREAD\n",
       "          Py_BLOCK_THREADS\n",
       "          #endif\n",
       "          goto __pyx_L5;\n",
       "        }\n",
       "        __pyx_L5:;\n",
       "      }\n",
       "  }\n",
       "
+15:         for i in range(m):
\n", "
        __pyx_t_1 = __pyx_v_m;\n",
       "        for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {\n",
       "          __pyx_v_i = __pyx_t_2;\n",
       "
+16:             for j in range(p):
\n", "
          __pyx_t_3 = __pyx_v_p;\n",
       "          for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {\n",
       "            __pyx_v_j = __pyx_t_4;\n",
       "
+17:                 res[i,j] = 0
\n", "
            __pyx_t_5 = __pyx_v_i;\n",
       "            __pyx_t_6 = __pyx_v_j;\n",
       "            *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_res.data + __pyx_t_5 * __pyx_v_res.strides[0]) ) + __pyx_t_6 * __pyx_v_res.strides[1]) )) = 0.0;\n",
       "
+18:                 for k in range(n):
\n", "
            __pyx_t_7 = __pyx_v_n;\n",
       "            for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {\n",
       "              __pyx_v_k = __pyx_t_8;\n",
       "
+19:                     res[i,j] += u[i,k] * v[k,j]
\n", "
              __pyx_t_9 = __pyx_v_i;\n",
       "              __pyx_t_10 = __pyx_v_k;\n",
       "              __pyx_t_11 = __pyx_v_k;\n",
       "              __pyx_t_12 = __pyx_v_j;\n",
       "              __pyx_t_13 = __pyx_v_i;\n",
       "              __pyx_t_14 = __pyx_v_j;\n",
       "              *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_res.data + __pyx_t_13 * __pyx_v_res.strides[0]) ) + __pyx_t_14 * __pyx_v_res.strides[1]) )) += ((*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_u.data + __pyx_t_9 * __pyx_v_u.strides[0]) ) + __pyx_t_10 * __pyx_v_u.strides[1]) ))) * (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_v.data + __pyx_t_11 * __pyx_v_v.strides[0]) ) + __pyx_t_12 * __pyx_v_v.strides[1]) ))));\n",
       "            }\n",
       "          }\n",
       "        }\n",
       "      }\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "import cython\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def matrix_multiply1(double[:,:] u, double[:, :] v, double[:, :] res):\n", " cdef int i, j, k\n", " cdef int m, n, p\n", "\n", " m = u.shape[0]\n", " n = u.shape[1]\n", " p = v.shape[1]\n", "\n", " with cython.nogil:\n", " for i in range(m):\n", " for j in range(p):\n", " res[i,j] = 0\n", " for k in range(n):\n", " res[i,j] += u[i,k] * v[k,j]" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3 loops, best of 3: 13.4 µs per loop\n" ] } ], "source": [ "res = np.zeros((u.shape[0], v.shape[1]))\n", "%timeit -r3 -n3 matrix_multiply1(u, v, res)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Parallel execution with Cython\n", "\n", "Will not work unless OpenMP is installed." ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%%cython --compile-args=-fopenmp --link-args=-fopenmp --force\n", "\n", "import cython\n", "from cython.parallel import parallel, prange\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def matrix_multiply2(double[:,:] u, double[:, :] v, double[:, :] res):\n", " cdef int i, j, k\n", " cdef int m, n, p\n", "\n", " m = u.shape[0]\n", " n = u.shape[1]\n", " p = v.shape[1]\n", "\n", " with cython.nogil, parallel():\n", " for i in prange(m):\n", " for j in prange(p):\n", " res[i,j] = 0\n", " for k in range(n):\n", " res[i,j] += u[i,k] * v[k,j]" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The slowest run took 12.73 times longer than the fastest. This could mean that an intermediate result is being cached.\n", "3 loops, best of 3: 12.7 µs per loop\n" ] } ], "source": [ "res = np.zeros((u.shape[0], v.shape[1]))\n", "%timeit -r3 -n3 matrix_multiply2(u, v, res)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import time" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# color function for point at (x, y)\n", "def mandel(x, y, max_iters):\n", " c = complex(x, y)\n", " z = 0.0j\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if z.real*z.real + z.imag*z.imag >= 4:\n", " return i\n", " return max_iters\n", "\n", "def create_fractal(xmin, xmax, ymin, ymax, image, iters):\n", " height, width = image.shape\n", " \n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", " \n", " for x in range(width):\n", " real = xmin + x*pixel_size_x\n", " for y in range(height):\n", " imag = ymin + y*pixel_size_y\n", " color = mandel(real, imag, iters)\n", " image[y, x] = color " ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mandelbrot created on CPU in 30.301049 s\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "gimage = np.zeros((1024, 1536), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "\n", "start = time.clock()\n", "create_fractal(xmin, xmax, ymin, ymax, gimage, iters)\n", "dt = time.clock() - start\n", "\n", "print(\"Mandelbrot created on CPU in %f s\" % dt)\n", "plt.grid(False)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf.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: 
\n", "
 04: cdef extern from "complex.h":
\n", "
 05:     double cabs(double complex)
\n", "
 06: 
\n", "
 07: # color function for point at (x, y)
\n", "
+08: cdef unsigned char mandel_cython(double x, double y, int max_iters):
\n", "
static unsigned char __pyx_f_46_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf_mandel_cython(double __pyx_v_x, double __pyx_v_y, int __pyx_v_max_iters) {\n",
       "  __pyx_t_double_complex __pyx_v_c;\n",
       "  __pyx_t_double_complex __pyx_v_z;\n",
       "  int __pyx_v_i;\n",
       "  unsigned char __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",
       "
 09:     cdef double complex c, z
\n", "
 10: 
\n", "
+11:     c = x + y*1j
\n", "
  __pyx_v_c = __Pyx_c_sum(__pyx_t_double_complex_from_parts(__pyx_v_x, 0), __Pyx_c_prod(__pyx_t_double_complex_from_parts(__pyx_v_y, 0), __pyx_t_double_complex_from_parts(0, 1.0)));\n",
       "
+12:     z = 0.0j
\n", "
  __pyx_v_z = __pyx_t_double_complex_from_parts(0, 0.0);\n",
       "
+13:     for i in range(max_iters):
\n", "
  __pyx_t_1 = __pyx_v_max_iters;\n",
       "  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {\n",
       "    __pyx_v_i = __pyx_t_2;\n",
       "
+14:         z = z*z + c
\n", "
    __pyx_v_z = __Pyx_c_sum(__Pyx_c_prod(__pyx_v_z, __pyx_v_z), __pyx_v_c);\n",
       "
+15:         if cabs(z) >= 2:
\n", "
    __pyx_t_3 = ((cabs(__pyx_v_z) >= 2.0) != 0);\n",
       "    if (__pyx_t_3) {\n",
       "/* … */\n",
       "    }\n",
       "  }\n",
       "
+16:             return i
\n", "
      __pyx_r = __pyx_v_i;\n",
       "      goto __pyx_L0;\n",
       "
+17:     return max_iters
\n", "
  __pyx_r = __pyx_v_max_iters;\n",
       "  goto __pyx_L0;\n",
       "
 18: 
\n", "
 19: @cython.cdivision(True)
\n", "
+20: def create_fractal_cython(double xmin, double xmax, double ymin, double ymax, unsigned char[:, :] image, int iters):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf_1create_fractal_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf_1create_fractal_cython = {\"create_fractal_cython\", (PyCFunction)__pyx_pw_46_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf_1create_fractal_cython, METH_VARARGS|METH_KEYWORDS, 0};\n",
       "static PyObject *__pyx_pw_46_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf_1create_fractal_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {\n",
       "  double __pyx_v_xmin;\n",
       "  double __pyx_v_xmax;\n",
       "  double __pyx_v_ymin;\n",
       "  double __pyx_v_ymax;\n",
       "  __Pyx_memviewslice __pyx_v_image = { 0, 0, { 0 }, { 0 }, { 0 } };\n",
       "  int __pyx_v_iters;\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"create_fractal_cython (wrapper)\", 0);\n",
       "  {\n",
       "    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_xmin,&__pyx_n_s_xmax,&__pyx_n_s_ymin,&__pyx_n_s_ymax,&__pyx_n_s_image,&__pyx_n_s_iters,0};\n",
       "    PyObject* values[6] = {0,0,0,0,0,0};\n",
       "    if (unlikely(__pyx_kwds)) {\n",
       "      Py_ssize_t kw_args;\n",
       "      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);\n",
       "      switch (pos_args) {\n",
       "        case  6: values[5] = PyTuple_GET_ITEM(__pyx_args, 5);\n",
       "        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);\n",
       "        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n",
       "        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
       "        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
       "        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
       "        case  0: break;\n",
       "        default: goto __pyx_L5_argtuple_error;\n",
       "      }\n",
       "      kw_args = PyDict_Size(__pyx_kwds);\n",
       "      switch (pos_args) {\n",
       "        case  0:\n",
       "        if (likely((values[0] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_xmin)) != 0)) kw_args--;\n",
       "        else goto __pyx_L5_argtuple_error;\n",
       "        case  1:\n",
       "        if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_xmax)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "        case  2:\n",
       "        if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_ymin)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "        case  3:\n",
       "        if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_ymax)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "        case  4:\n",
       "        if (likely((values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_image)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "        case  5:\n",
       "        if (likely((values[5] = PyDict_GetItem(__pyx_kwds, __pyx_n_s_iters)) != 0)) kw_args--;\n",
       "        else {\n",
       "          __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, 5); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "        }\n",
       "      }\n",
       "      if (unlikely(kw_args > 0)) {\n",
       "        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, \"create_fractal_cython\") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "      }\n",
       "    } else if (PyTuple_GET_SIZE(__pyx_args) != 6) {\n",
       "      goto __pyx_L5_argtuple_error;\n",
       "    } else {\n",
       "      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);\n",
       "      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);\n",
       "      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);\n",
       "      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);\n",
       "      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);\n",
       "      values[5] = PyTuple_GET_ITEM(__pyx_args, 5);\n",
       "    }\n",
       "    __pyx_v_xmin = __pyx_PyFloat_AsDouble(values[0]); if (unlikely((__pyx_v_xmin == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "    __pyx_v_xmax = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_xmax == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "    __pyx_v_ymin = __pyx_PyFloat_AsDouble(values[2]); if (unlikely((__pyx_v_ymin == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "    __pyx_v_ymax = __pyx_PyFloat_AsDouble(values[3]); if (unlikely((__pyx_v_ymax == (double)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "    __pyx_v_image = __Pyx_PyObject_to_MemoryviewSlice_dsds_unsigned_char(values[4]); if (unlikely(!__pyx_v_image.memview)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "    __pyx_v_iters = __Pyx_PyInt_As_int(values[5]); if (unlikely((__pyx_v_iters == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "  }\n",
       "  goto __pyx_L4_argument_unpacking_done;\n",
       "  __pyx_L5_argtuple_error:;\n",
       "  __Pyx_RaiseArgtupleInvalid(\"create_fractal_cython\", 1, 6, 6, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L3_error;}\n",
       "  __pyx_L3_error:;\n",
       "  __Pyx_AddTraceback(\"_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf.create_fractal_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_d6a1f90b0d5f075a7376b0cd47db83bf_create_fractal_cython(__pyx_self, __pyx_v_xmin, __pyx_v_xmax, __pyx_v_ymin, __pyx_v_ymax, __pyx_v_image, __pyx_v_iters);\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_d6a1f90b0d5f075a7376b0cd47db83bf_create_fractal_cython(CYTHON_UNUSED PyObject *__pyx_self, double __pyx_v_xmin, double __pyx_v_xmax, double __pyx_v_ymin, double __pyx_v_ymax, __Pyx_memviewslice __pyx_v_image, int __pyx_v_iters) {\n",
       "  int __pyx_v_x;\n",
       "  int __pyx_v_y;\n",
       "  int __pyx_v_height;\n",
       "  int __pyx_v_width;\n",
       "  double __pyx_v_pixel_size_x;\n",
       "  double __pyx_v_pixel_size_y;\n",
       "  double __pyx_v_real;\n",
       "  double __pyx_v_imag;\n",
       "  unsigned char __pyx_v_color;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"create_fractal_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_AddTraceback(\"_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf.create_fractal_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __PYX_XDEC_MEMVIEW(&__pyx_v_image, 1);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__14 = PyTuple_Pack(15, __pyx_n_s_xmin, __pyx_n_s_xmax, __pyx_n_s_ymin, __pyx_n_s_ymax, __pyx_n_s_image, __pyx_n_s_iters, __pyx_n_s_x, __pyx_n_s_y, __pyx_n_s_height, __pyx_n_s_width, __pyx_n_s_pixel_size_x, __pyx_n_s_pixel_size_y, __pyx_n_s_real, __pyx_n_s_imag, __pyx_n_s_color); if (unlikely(!__pyx_tuple__14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_tuple__14);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__14);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf_1create_fractal_cython, NULL, __pyx_n_s_cython_magic_d6a1f90b0d5f075a73); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_create_fractal_cython, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_codeobj__15 = (PyObject*)__Pyx_PyCode_New(6, 0, 15, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_Users_cliburn_ipython_cython__c, __pyx_n_s_create_fractal_cython, 20, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "
 21: 
\n", "
 22:     cdef int x, y
\n", "
 23:     cdef int height, width
\n", "
 24:     cdef double pixel_size_x, pixel_size_y
\n", "
 25:     cdef double real, imag
\n", "
 26:     cdef unsigned char color
\n", "
 27: 
\n", "
+28:     height = image.shape[0]
\n", "
  __pyx_v_height = (__pyx_v_image.shape[0]);\n",
       "
+29:     width = image.shape[1]
\n", "
  __pyx_v_width = (__pyx_v_image.shape[1]);\n",
       "
 30: 
\n", "
+31:     pixel_size_x = (xmax - xmin)/width
\n", "
  __pyx_v_pixel_size_x = ((__pyx_v_xmax - __pyx_v_xmin) / __pyx_v_width);\n",
       "
+32:     pixel_size_y = (ymax - ymin)/height
\n", "
  __pyx_v_pixel_size_y = ((__pyx_v_ymax - __pyx_v_ymin) / __pyx_v_height);\n",
       "
 33: 
\n", "
+34:     for x in range(width):
\n", "
  __pyx_t_1 = __pyx_v_width;\n",
       "  for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {\n",
       "    __pyx_v_x = __pyx_t_2;\n",
       "
+35:         real = xmin + x*pixel_size_x
\n", "
    __pyx_v_real = (__pyx_v_xmin + (__pyx_v_x * __pyx_v_pixel_size_x));\n",
       "
+36:         for y in range(height):
\n", "
    __pyx_t_3 = __pyx_v_height;\n",
       "    for (__pyx_t_4 = 0; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {\n",
       "      __pyx_v_y = __pyx_t_4;\n",
       "
+37:             imag = ymin + y*pixel_size_y
\n", "
      __pyx_v_imag = (__pyx_v_ymin + (__pyx_v_y * __pyx_v_pixel_size_y));\n",
       "
+38:             color = mandel_cython(real, imag, iters)
\n", "
      __pyx_v_color = __pyx_f_46_cython_magic_d6a1f90b0d5f075a7376b0cd47db83bf_mandel_cython(__pyx_v_real, __pyx_v_imag, __pyx_v_iters);\n",
       "
+39:             image[y, x]  = color
\n", "
      __pyx_t_5 = __pyx_v_y;\n",
       "      __pyx_t_6 = __pyx_v_x;\n",
       "      __pyx_t_7 = -1;\n",
       "      if (__pyx_t_5 < 0) {\n",
       "        __pyx_t_5 += __pyx_v_image.shape[0];\n",
       "        if (unlikely(__pyx_t_5 < 0)) __pyx_t_7 = 0;\n",
       "      } else if (unlikely(__pyx_t_5 >= __pyx_v_image.shape[0])) __pyx_t_7 = 0;\n",
       "      if (__pyx_t_6 < 0) {\n",
       "        __pyx_t_6 += __pyx_v_image.shape[1];\n",
       "        if (unlikely(__pyx_t_6 < 0)) __pyx_t_7 = 1;\n",
       "      } else if (unlikely(__pyx_t_6 >= __pyx_v_image.shape[1])) __pyx_t_7 = 1;\n",
       "      if (unlikely(__pyx_t_7 != -1)) {\n",
       "        __Pyx_RaiseBufferIndexError(__pyx_t_7);\n",
       "        {__pyx_filename = __pyx_f[0]; __pyx_lineno = 39; __pyx_clineno = __LINE__; goto __pyx_L1_error;}\n",
       "      }\n",
       "      *((unsigned char *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_image.data + __pyx_t_5 * __pyx_v_image.strides[0]) ) + __pyx_t_6 * __pyx_v_image.strides[1]) )) = __pyx_v_color;\n",
       "    }\n",
       "  }\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "\n", "cimport cython\n", "\n", "cdef extern from \"complex.h\":\n", " double cabs(double complex)\n", "\n", "# color function for point at (x, y)\n", "cdef unsigned char mandel_cython(double x, double y, int max_iters):\n", " cdef double complex c, z\n", "\n", " c = x + y*1j\n", " z = 0.0j\n", " for i in range(max_iters):\n", " z = z*z + c\n", " if cabs(z) >= 2:\n", " return i\n", " return max_iters\n", "\n", "@cython.cdivision(True)\n", "def create_fractal_cython(double xmin, double xmax, double ymin, double ymax, unsigned char[:, :] image, int iters):\n", "\n", " cdef int x, y\n", " cdef int height, width\n", " cdef double pixel_size_x, pixel_size_y\n", " cdef double real, imag\n", " cdef unsigned char color\n", "\n", " height = image.shape[0]\n", " width = image.shape[1]\n", " \n", " pixel_size_x = (xmax - xmin)/width\n", " pixel_size_y = (ymax - ymin)/height\n", " \n", " for x in range(width):\n", " real = xmin + x*pixel_size_x\n", " for y in range(height):\n", " imag = ymin + y*pixel_size_y\n", " color = mandel_cython(real, imag, iters)\n", " image[y, x] = color " ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mandelbrot created on CPU in 0.276794 s\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "gimage = np.zeros((1024, 1536), dtype=np.uint8)\n", "xmin, xmax, ymin, ymax = np.array([-2.0, 1.0, -1.0, 1.0]).astype('float32')\n", "iters = 50\n", "\n", "start = time.clock()\n", "create_fractal_cython(xmin, xmax, ymin, ymax, gimage, iters)\n", "dt = time.clock() - start\n", "\n", "print(\"Mandelbrot created on CPU in %f s\" % dt)\n", "plt.grid(False)\n", "plt.imshow(gimage, cmap='jet')\n", "pass" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "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 }