{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "I had the pleasure of attending a [workshop](http://calcul.math.cnrs.fr/spip.php?article284) given by the [groupe calcul (CNRS)](http://calcul.math.cnrs.fr) this week. The topic was: how do you optimize the execution speed of your Python code, under the hypothesis that you already tried to make it fast using NumPy? \n", "\n", "The training was held over three days and presented three interesting ways to achieve speedups: [Cython](http://cython.readthedocs.io/en/latest/), [pythran](https://pythonhosted.org/pythran/) and [numba](http://numba.pydata.org).\n", "\n", "Overall, the workshop was great. The goal of this blog post is to summarize some of the key insights that I learnt while using these three tools on an practical application: image filtering." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This post uses the following versions of the libraries:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "WARNING: Disabling color, you really want to install colorlog.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "0.27.3\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "WARNING: Pythran support disabled for module: omp\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "0.8.4post0\n", "0.36.2\n" ] } ], "source": [ "import cython; print(cython.__version__)\n", "import pythran; print(pythran.__version__)\n", "import numba; print(numba.__version__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Introducing the discrete Laplacian " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When working with images, the [discrete Laplacian operator](https://en.wikipedia.org/wiki/Discrete_Laplace_operator) is often used for edge detection.\n", "\n", "Intuitively, if you want to find the edges of an image, you compute the Laplacian and threshold it to see the edges appear. Let's give an example using scikit-image. \n", "\n", "First, let's load a standard grayscale image that ships with scikit-image, the `astronaut`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import skimage.data\n", "import skimage.color" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(512, 512)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "image = skimage.data.astronaut()\n", "image = skimage.color.rgb2gray(image)\n", "image.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's write a function that uses the scikit-image implementation of the discrete Laplace operator and thresholds the result with a fixed threshold. " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "from skimage.filters import laplace\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def laplace_skimage(image):\n", " \"\"\"Applies Laplace operator to 2D image using skimage implementation. \n", " Then tresholds the result and returns boolean image.\"\"\"\n", " laplacian = laplace(image)\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's apply the function and check its result." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "edges = laplace_skimage(image)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(512, 512)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "edges.shape" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's display the obtained edges, along with the original image." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "def compare(left, right):\n", " \"\"\"Compares two images, left and right.\"\"\"\n", " fig, ax = plt.subplots(1, 2, figsize=(10, 5))\n", " ax[0].imshow(left, cmap='gray')\n", " ax[1].imshow(right, cmap='gray')" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nrkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "compare(left=image, right=edges)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since the topic of this post is to deal with optimization, we will now suppose that we're not using scikit-image. \n", "\n", "As is usually the case when you're working on your own problems, we'll implement the Laplacian algorithm by ourselves using NumPy." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# NumPy implementation " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So here we go: we write a function that makes use of vectorized NumPy to perform the same operation than the scikit-image implementation. " ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def laplace_numpy(image):\n", " \"\"\"Applies Laplace operator to 2D image using our own NumPy implementation. \n", " Then tresholds the result and returns boolean image.\"\"\"\n", " laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you're paying attention closely, we're not actually implementing exactly the same function as scikit-image, since we're excluding all border pixels of the image from our calculation. \n", "\n", "Let's check the result is qualitatively correct." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(510, 510)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "laplace_numpy(image).shape" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/png": "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\nAOVyGblcDrlcDpubmwgEAohEIhgcHEQqlYLb7cbq6ip8Ph+bjEg50rm1Wg3ZbBbJZJJLzTgcDpjN\nZvZ1Il8o0ZeIFK/InPT09OCXv/wllpaWsHfvXh4TcK3eI42XCkWTSZPAAbE/ogmL5qOjo4Oj8jY2\nNlAoFJp82ciZnurrFQoFuFwudHZ2sg8btU2sGZn1bDYbYrEYj5uSmEajUa4FaTabkUqlOBXC0NAQ\n+vr6UCgUEIvFcOHCBR5rNBplxosyvRuNRk7NQUERkiSxT1W1WmXGLh6PIx6Po9FooLu7G/39/VxH\nUQTGlJKBQJaYN436QkqK1onmlTLdU5oIj8cDk8mEfD7PCU6JTaR5ElmtOyDrgyU3qqREpadmDhP3\nlR6L0sr8p3ZdvbEoFb2W2UytPS3w1w4Ibae/Wv1TXrNdM5l4fismi45VtiteW4up0wN97bJ57YxB\n77rtrMnNspV35JrcdkDLYDDA7/djbGwMk5OTOH369HWKUXnDjI6OIhKJAAAn9zQajVhfX4fP50Ox\nWEQ4HEatVsPevXu5QPDa2hp6e3uxubmJVCqFUqnEvlvkIE2ldQigGAwGBi9Op5P9m8iXi8xjIktF\n/lrkB/ThD38YU1NT8Pl8sNvtDLDIFAhcy/FELJ7oDybWVKTCy5IksWL//9n78jA5qnL9t2Z6X2Z6\nZnq2TGZJQiYLWSZhArKrSAgKXJSIiBdFUfByAR9B8KKi8IiI+uAPRRHccXkuLlxRQNZAQAgBTMie\nmEkmyexbr9PrzHTX74/Je3K6qOquniQ6wnzPkyfT1VWnTp1TXd9b7/ed9yP4rKurw/DwMOLxuGCb\nJiYm4HA4UF5ejlQqJVgyAAKEsC35/Kqq5qx6JEBiuLW/v1+wP5RE6Onpgdvtxo4dO/Df//3f2LNn\nD1KpFHw+HxwOB2pqaoRmlczgybUuGa4bHR1FMplEJBLBxMQEQqEQRkdHha7YySefDIvFIubRYrGI\nEC9BEOeGQHp8fFyEfRlm5Xc2mw2pVErUNSQjx3uACx64SEJOppfHTu9+nbG3r+kxGfnMDHuix9aY\nZc20wKMY52nkeGUQMhXAZOb8hfo7VWBgBGp4vPx/vt+tto1if+PaUKLclhE7p+2z0X2hx8oZmRGr\nNgOwjq1NG6BFJ8twXE1NDRYuXIienh50dXUJlgE4kohO59nb24t58+bB6/WirKxMrOLzer2IxWII\nh8NIJpPw+/3w+/1CRbyrqwtLliwRCvIUNiV4YC1D1umT85wIppjzJOsoEbwQlLHPDDuR9YrFYqLU\nDlknAhuKihJ0EIzIgI79ACD6zuR4udB0OBwWoERedUcQwx+n0+kUwJJMEvPHCB4AiHIzlEogy8hV\ngD6fT+w7MDCA2tpa3HnnnVCUybDr4OAglixZApfLJcKlZP9kgCWDvLGxMQSDk6vsyVhxbFauXIma\nmhrEYjFEo1HBwjE/iwBTZvaYb0dgJzOl1O4CJgGvz+fLWQVK5oqrWi0WiwgrasfXbChixt4+ls8Z\nFnNsPoCiZbYKsSjyZyMnr91e6DoKgb1ixsHM9RQKpen1pxigp712PfbQLGgpBBSNAI7edZgZX+3n\nYkHoDLA6vlaUjtbxMjo7JiOr6mT9v/r6eixbtgwVFRVvuSHlzytWrEBFRQXKysrgcDgE88KE5FAo\nhGw2C7/fL1gOhoa0PyaGetgfl8slbkIqwtNh00HLRYXZFvN7FEUR4T8ZmFgsFnR0dIikbQINrYAp\nz8VzyPX5CA6YKC6X6uE2h8OByspKERJNp9OYmJgQGmLAkZBlaWkpXC6XACiUryCw4Ao9rhIkAGK/\neM0sB+RwONDc3Iy6ujq8733vAwDBDlGTioCW7BhBJkENJS3IaBHcEAjOmzcPLS0tGBsbQzweF+FO\nqrfLCfByDhoBFcEv50++ByYmJkQifkNDgyjBw3uBjKfD4UAoFMp5EeB45Xs7nbG3t+mxC1Nth2YU\nPjRiwvT+1zpkPVbGDDjJxzbluwY9k/uQD1gUGksjMFjItKFCI9ZQHksjn6QdX6MwZD4wVQiUmjWj\nc+fbZwZ0HXubFowWbzjmDhGoeDwezJ8/HxMTE3juuedygIF8M/j9fpEvIyc4U517fHwc5eXlaGxs\nRDgcRn19vZB+oBOXaw/KoSs5SZqK6XSoZNTo0BlKIsAiqwFAOHb+393dLWoukg1iXT+tw2c/KK8g\ng1HKQ8hlgdh3JsDbbDbU1NQgHA4Ldo/5X8lkUuSZyVplFOok4OSYkgUjOCLTw5Dh6OgoSktLsWDB\nAtGHuXPnorOzE2vWrIHL5cLQ0BACgQD6+vqwaNEicR0ErQRvFotFsGTsA8GYxWJBRUUFmpubRf5W\nJBIRuVPyYgUAApgBuYBZVs/ntRA4ZrNZUSOS+XzMl2PoNh6Pw+v1IhKJCADHuWedSb3QwIy9M6xY\nRkvvWD22R88xas+VjxEpxLTk61O+PhZ7vkLnyscMFQIHZsOb8j56DF++l3y9Nsx8ZzR/Zvo7FebM\naH/5f725PJr7d8aO2LRgtIDcUA4ZCABoamrCwoULReK4HO6yWCyYN2+eSGR3Op0iMT2dTiORSAjw\nUl5eDp/Ph6GhIVRWViIej+esSGPiNcEUgJz8oUwmA7fbnaNcz9Iw8XgciURC5HbJoT6G68gayQwY\n6y4CEIrxzOWSmTNZ6kEup0OAQGCmBaIMXRI8UW/LYrEglUohFAohmUyKUJkMCqkZxQLaXHXH3DV5\nzhhizWazWLx4MRYvXgy3242DBw9iaGgImzdvRjgcxtq1a9Hd3Q2v14v6+no0NDQgFAohEokIxk9m\nA5nzxbHjCkUuCGhqahJhSvYNgGDkyOBxZSZNyxzK4I7GnC0KxCaTyRyldy4ckBciEMDyHpHZUJ53\nxt5ZVojRKHSs/H++feRzsW0tk2V0nF5/pgIm8lkxx+mxdkahMJkB0/ZZj1HMN+Z6QDbfOBwtADEC\nzFNtS7ZCTJbRc2kGZB0fmzZAS/uDIZhwuVyYPXs2Fi1ahLq6uhwHqSgKli1bJkAFE8MJcMh+cIWg\nw+FAIBBAOp1GNBoViuOUcGAYj4nnBFoMITJ0xvPz2NHRUeHQVTW3BiNDlMCRxHgCGn4nSy/Iulp0\n9mxTzkvimJG5IeDSSkIwAZ8MmN1uh9/vF0Kf8Xgc0WhUJMLz2hk2dLvdAgDLTBmvh/uXl5dj7ty5\ngt3zeDzo7u7OmY/vfOc78Hq9GBwcFKFOgt9oNCrCd3a7XQitEsiQcSSY9Pv9qKysFAnukUgEwCSY\n5Dxxf7JlWiBFUM554fXxGjknnOdUKoV0Oo1wOCxWMBKk2u32HDkSJuNrbQZsvbNMBgSFwIvZeyMf\naNMDZ2YAm7Yf/0oHawRi8oXhtQBB+73cthkAojd+ep+NQomFANRUQoaymZkjLWDUA/1asKp3nhk7\neps2oUPgyI3BEBtr63m9XjQ3N6OtrQ3PPfecWB1ms9nQ0NCAiooKAZLGxsaElhK3Me/I4/GIPK1Q\nKAS/3y8KTjOJmuBKfjgSAMgr1xjGYyK3HFYku8NjCBYICBVFgdfrRSgUEgAoHo+L88qr78i6sQ8U\n3iSbRRBG4AJA/M3tTMBnOJZyDlarFeFwWOhVsTYi2S1qRdXU1ODgwYOCDZNDiTIYIsgg2AmFQqiu\nrobb7YbD4YDX6xWr9CgCy/7t27cPc+fORWVlpQDa8hyQlUsmk/D5fKiqqoLD4UAymRRiqxMTEygr\nKxPjQm0wWX+NDxwq7MtCuNqHEQFbOp0WwCqZTMLr9Qr2kXNis9nQ3d2NhoYGVFZWQlGUt7BkM/b2\nN6PwnfZvvWOMWJt8AM2Mw9U61kLH5PuumPu5mNCd2b4YjVU+9kvbl2JBnNymHrjTG89Cc6kX0ptK\nqLPQ90b/F7oHCt17M1acTQugxQmnMyXQkpPLfT4f5syZIyQfAKCurg59fX0YGxtDbW2tKJvCGnNc\n1Ud9rkQiIWQNwuEw5s2bh2w2KxLoGaJiWEhmntgvrmhk0jlVxhOJRA4g4LFy3pOcRM7Eajkhn8YE\nbofDIRy8nLBO8VKuyNMygQQ/MhBgOwQ2BDwWiwWhUAjxeFysnuNCAuBIEe2qqioBWnkunpf9dDqd\nIreLbBYlHhhmzGazqKmpQVdXF+bMmYOqqips2LABo6OjiEQi8Pl8om2XyyXGnqsmVVVFbW0tysrK\nRAg3EAhAVVWhzC6Lu3K8GWqWVzLKOVwErnIeHYEzSxYRzBFEyQKnJSUlGBwcxJYtW7B8+XLBFOrd\n5zMPr7ev6TlYbtf7W97PiCkxw4blc+za++5ogU+hUKQRGNIzves2Oq5YoGqWyZP3MQJYRvvpzZMW\nzOQD3/n6MdV5MrqXzPbhWIUzZ+yITZvQoXxTyqvEyMxYrVb4/X7MnTsXfr8fJSUlqKurw6FDh+Dx\neHDgwAE88MAD2LJlC9xuN+x2u2BxKioqoCiKKDHDOoAyWJFFK7liTU66J8ix2+3weDzw+XxCSoL9\nlbWWWI+Q7BbDTMx9IhBgH2V5CAAi9AUcSUJngrYMnuTwpqxYLofBGMJkKJKSEw6HA36/XxSllkvx\nEIjIoIyr+tg2i1PLiwImJiaQSqWwZcsWAU4SiQQ+9KEPIRaLYWxsDEuXLsUNN9yA+fPnY/v27Rge\nHhYJ58wbY8iR80ZtLq5GZfFr9lVRFHGNwBEdMplJ5PjJgJjzL5s2D1DWxEomk0ICBEDOC4Hb7Ybf\n74fT6UQkEkF/f79h2GDmAfb2tnwMihFo0gt5TfU+0QMZ+Zges2Zm/2LOc6x+B2b6ZRTay9cfstty\nyC3f/JkBSnrhO+25zYJUM2b2eaM9/8wL4bGzaQO0yCIQtJBdAI7k5TidTlRXV2PRokUoLS3Fqaee\nipNPPhnRaBTbtm2D1WpFIBDAoUOHMDg4CACC/Vi5ciUGBgbgcrmQTCbR0tIiEqaBI4nvBA0ABINC\noKKqqsi7Ibvj9/sFeBofH0c8HkcsFhPJ7cwbk0ONVDKnLpfdbhdhQ16vDLzo+OUQJkNbHDc6fLnw\ns5xDRUZMVntnqFVVVVEYWhaHZf4SNb38fr9YbUiNL86drK1FYVK32y2U1B9++GHR5r59+9DV1YUL\nLrgA119/PYaHhzE6Ooq///3viEajiMViOeCQ32ezWSxbtgxVVVVIpVKIx+NisQPV6hkWdDqdYlwJ\n2DmOMpMlM5BksQjQ5LEig0XxV+qoyeMLAHPmzEE2m0UkEhF5Y1P5LWg/6/2bselles5Tu81o7oy2\naZ2y2fPrfdZ+lw846H1XCCDmM7P3az5wYnSuQsfobSsEJGTwUwzDlo89KgZAmx3TfOOR7/r1Ph8L\nxnPG9G3aAC1ZlkCrks68oGw2K1astbW1we12C0HJtrY2zJ07F/PmzcPOnTvh9/tRW1sLj8eDdDqN\nzZs3o6+vDx6PB3v27EFZWZlwunLOER08b2KZwWHNO4aZXC4XXC6XUDqnsVAzE/KZ9J5IJPD000+j\nv79fME/cnwyWDJAURclZaSgzbGSP+MDkMQQVDOERBLBWIJP6CZII/JiAzlWIBJ5sj2CLc0XRVeY5\nEbDE43EMDAzAZrNh1qxZKCsrw3nnnZeT6L937178/ve/R319PZYsWYIXXngB9913H9asWYPh4WGM\njIyIWoZjY2MYHBxEKpVCU1OTUPrnIgTm68n5arJEhaIc0bPids47t8kyGlxskEgkcthCeRGDPK8c\nY4JSj8cj9LdYVqiQmQFO+ZixmQfj9LCpzIMei2AmxFwoNGSmP/lCa/lYFr3zHAv2wyzw0dtfL6Rn\n9MJSKIQr7y8DUu3+ZkCfXijSDMg6mt80+6zXFzNzVwy4nzFzNi1ytIDcXCYyCsCRG1cO57Cunaxf\n5HA4UF9fj71796KpqQl1dXVIp9NwOp1obW1FIBAQScuhUEgwHPKPSQZXstilnJwvl2Ah++V0OgFM\n3qDJZFKAM+pzUf18ZGQEIyMjWLFiBcLhMIBJlfOqqioRKpNXEFJcVZZz0I6JLPRKlkV7TTLwIDhg\nsWjuT00v5pGRkZNZPIpzyv9zjAhG9+/fDwBwuVwCfJ522ml4/vnn4XA4BFN07bXXoqenB/X19fD5\nfFiyZAnuuusufOQjH8kpyD06OoqhoSFUVVXh1ltvRSAQwO7du7F3716hyk5gabFY4HA4chYVkP0j\no0dwJQuxch4J1Agiqa4vVwnQCsfyeFVVhX5aIpEQIrmy89Q+ZGWAJ8+r3sNYPl4+Lp8jmLF/vRmx\nHvnCRHpgK9/cmg0zGYEmMyGvYgHGVKwYAFLoPj8aBi0fQ6YFatrv9RhMub96wEvb3lTGMt89dbTA\nbcaO3qYN0KLJuVHaUB5vFgpwsk4gGabe3l4hlskkasouULRUVVU0NjYKLSku4yfzI4MPOZRGB8q8\nIwKMVColcpiAI2E/WSCT10CdJzJoBEd05ARWZKAIOLg/GSEZlMor6vjDlkOvzEOTZTEInuRkfI67\n2+0GAAE22KYsGMoQpLza0Wq1IpFIIBKJIJvNoqysDHa7Hel0GrW1tW95SHV1dWHZsmVC2JOlja64\n4go89NBDCIfDsNvt2LdvH0pKSnDaaafB5XIhlUrh3e9+N6644gqR3B+JRPDqq69iYGAgh0ViHhuv\nQQas8qIEOcldluPgqkUyZ2yPchGyKClBPIte9/b26r4BywwbTQuwtIK18u+B88d7ihImssOcAVvT\n2/Scqx6roHXURzO3+RxtPtBntH+hMNNUnHs+FqYQOC20XW5rKkDSbH/lPphpx+x5CwFhvbHRXu/R\ngM8ZOzqbNkBLTiqXnaPsIPmZTj2ZTKKurg6BQADAZNjK6XQKFoJv/8FgEJs3b0ZtbS3Gx8exePFi\nZDIZsZqMDA6ZJIbWGNLj6jM6QIIXOudUKgWn04mysjIAQDAYFAyHDG4IlIAj4Suek0nl3C+TyYja\ng3qsnuyQCer4QCI4INvDdth3+e2K/ZFV6ungWedRlkuwWCw5oIPtpNNp9PX1AZjMlyL4Ys7Y3Llz\n0d3djebmZnR3d+Pll1/Gxz/+ccEikZVbu3Yt7rjjDlRXV2NwcBAWiwWnnHIKhoeH4XK58NGPfhR+\nvx/ZbBaVlZVobW3FokWL0NjYiJNOOgk1NTXweDwChAQCAcTjcRw4cACDg4NCvT4Wi4lwrsfjyUno\nJ+Ci4jyBLIEXr5nabKqqivshEokgGAxiaGjoLWwWF3XIjCjvK4rJnnjiiaipqRGrMLkIIJ1Oi34n\nEglxb7NWJnPnCjmRGTv+VizIyAda9BxxIac71T6ZYbOMvtOCISMwqWVa5O/1vjPbdzNmFkTq9cFs\n+8cr7DYVIGgGdE71+2L7ks/eCcBu2gAtmXGRgRYA4cj4ubKyUoCd0tJS+P1+jI2NYf78+QgGgwJY\nWK1WkaM1PDyMhQsXYsOGDTj55JNzdLFkpkA+l8yoMUTI3CsCGjq4ZDIpNL8I7gDksE2yyjidOVk2\nOl3qZnFMZDkHghZZ7XxsbEwwPQRsMjsTCoXECkwCSwCCrSPAk0EW89CcTqf4IZFxIjAgGOT/VqtV\nsFlutxtOp1OIglosFrzrXe/CyMgI1qxZg8ceewzJZBJdXV2YP38+AAj2y2KxoLm5GfF4HIqiCKDX\n398PYDIkqaqTqzV7e3sRCASwadMmocgPAEuXLsXKlSsxOjqK/fv3w+PxYPbs2TjllFNQU1ODiooK\nMTexWAzd3d3YsmWLYMMIYuS3aYJLrW6Y/JDIZrN4/fXXMT4+LhL6gSOMFFlBn8+Hiy++GB//+MdR\nX18vKhvQtCESeU74AjA+Po5wOIx9+/bhu9/9LjZs2CBeCnifyNfAtmbs+FshB8Z99Oaj0HwVyz5N\nZV+jY7Xskh7I0oItoz7I+xuFLuVtemDU6DgjtrDQGOj1V49pNGNm5/BY/CaPBoDna6/Y72jFXp8e\nu/92s2kDtORVhgBEGE0GXARgDAP29/cjnU6jrq4OFRUVGBoaQm1tLVKpFKqqqqCqKqLRKPbs2YNT\nTjlFMAf84TLBmcCJgIvgiCvrCOgYVpQT0Qk0ZKbK7XYjFosJWQdKDXAVnCyeSSkJ1tTj+VmImowW\n+0iWjGCAcgoEAAQ7ZKHk/ZifJctMpNNpAEfYKyB3BSjDcwQVDCfKIKukpAT9/f0ijMpag2zLZrNh\n6dKleOSRR/CDH/wAbW1tcLlcCIfDImTK8QeAG264AXfffTdqa2sxa9YsPPnkk2hoaMgBxVwtSV0w\njtv4+Di+9rWv4YEHHsCsWbOwatUq/OxnP8PExAR+97vf5exXWVmJOXPmYOXKlbjgggvwwgsvoKen\nRzBdFotF5LKxGLcsysr5BJAzp3IFAEVRUFZWhk9/+tP44he/KIA17yGCr3wPdIZrWXvS6/VCVSf1\nxObPn49zzz0XqqpicHAQ3/rWt/DnP/8Z8XhcsJgy8zhj/zrTY2mMmBsjB53PiWqPKdZpmQUxev02\nOmchECVfl1Gftdett69Re0ZtGl27HmAsdIxeX+V+FtOG0TFm7gtt/436aKbvZvpvdlzNzIXRmL1d\ngNe0AVoEEsCRMCIBBlcD0tmzcDAFNjs6OmCz2TB37lzhYGKxGDKZDCoqKnJU1+mk6Nzp7GRHSUfI\nFXlybhS/IzBkKI2ABYBg0tgHOSTl9/sRDodzkrYJhOigCVKSySTcbrcIRt/ACAAAIABJREFUH7Gf\nVqsVIyMjQqqCq/QYGiMz5PF4sHDhQrFaU1ZOZ+isrKxMXOfY2Bi8Xq9gyLi6jiFIghsmyvNHFIvF\nMDQ0BIvFArfbnROC5VhlMhl8+tOfxqZNmxAKhfDhD39YACUyfQRul1xyCb7yla8IMHbBBRdgZGQE\nZ511FioqKsTYpVIpwYTJq/5+8pOfoK6uDlu3bkV9fT3q6+vR3d2dw/RRmHbz5s3YuXMnli9fjuHh\nYXR1dWH27NmifY4DgTTnV16FmE6nhV4Y8/3e9773Yc2aNbjiiive8vAmUJXDuEbGHELuxxCrLOnB\ne7mpqQn33Xcfvv/972NwcBD3338/fvWrXyEQCOiyAzN2fMzISWuBTD6nqOdYCzn/Y+mU8jFnZp25\n1nnqXZMMvLT3ptHLh3bfQmNtps/ybzPfNeldo96+RsylmXHTO07ens/MgsR8beqd+2jvrWJAq949\n8O8OuKYN0AKOhDrkJOCSkpIcFoc/MFm5nEntvb29sFqtIqxGQU0Cq4mJCQE46HQZLpPDYkyUB/AW\nxoTnJfhjvwgSWBuPDlCrJN7c3IyBgQE0NzcDOJLoLrMbBF42mw19fX0ibMikbb/fj+7ubhw4cADV\n1dWiP6lUCj6fT4CJiYkJ7NixI6eGY3t7O1RVRWVlJex2u8hBcjqdAoBwxR1wJGzL62Q+Fdsno0bQ\nQ+aOgMBut4t5aGpqgtfrFaFFhn8BiLYZhrXZbIjFYnA4HAK4/uhHP8Jjjz2GP/3pTwiFQnA6nTjh\nhBPEOPO+qa6uxpIlS3DSSSfhqaeewpIlS3Dw4MGce4xAijlTjz76KBobG8XCAfna+Fl+ADHES9BD\nIPye97wHp59+ulhscOjQIYyMjMDr9cJut6OyslKAXTNGECWb1inQFOVIeHLWrFn46le/ittuuw1v\nvvkmbrrpJmzevPktjOqMHXsrhkHJt3+h+TFii4o17YuAXlt6TJZRX7SWj+UpxE7pnW8qzrcYAJUP\nKBsBqHzn1LatPY/e9RQz94XaL9TOVLfRpsL8md3fCKz/u9m0AVryD0FWNeeqNq6u4kq6qqoqDAwM\n5OxPvSMmKTPBm+KVQ0NDsNvtb3mY0DlRxiCTycDtdgu2haEmVVVFuI2rz2gEH9yPLAQdNZ1gWVkZ\ntm/fjrq6OgH6mNtFZy07b+ZcMV9r79692LVrF1wuFyorK5HNZrFgwQLY7Xa0t7dj/fr16OzsxCOP\nPIIrr7wSP//5z3HzzTfjwIEDUBQFHR0d6O7uxoc+9CEEg0F4vV5RXJmgiiFWRTmyKpLAQQalBJCx\nWCxHLZ7gVJZzIPtTXl6OcDiMxsZGDA8PCyAthxoVRcGHP/xh/PGPfxQLHEKhEPbv34958+ahrq4O\ns2bNwte//nX4fD7cfffd+OIXv4iHHnoIbW1tWLlyJUZGRrBw4UIMDAygtbVVAHIycuyX1+vF+Pg4\nXn/9dbS1tYn5isfjQiSV9558n5Hx3Lt3L3p7e9Hc3IxsNoutW7diz5494p4hqJEZSwBiIYTT6cSK\nFSvQ3t6OqqoqETIHigNCMsgCILTRAGDVqlV4/vnnMTAwgJtvvhlPP/10jhjvDOD655rWWRdiIfRC\nOjLQngrgMgrjac+nZZz0rsGo3XzHa7eZCVkZjYMZJ1xojLSMs1E/5Jf9YoCl3hwXYvDy9T/fdRXq\nn1G/jMbTCHhr+6DHVB6t5RuvfyfQNW2Alqz/xP/JUNDRcb9sNotoNCqS1slAsbQMQ190rmSXwuEw\namtrkU6nEY1GRckaWZlddqgEObJYKNkQho7kXCUmLZMNcrvd4jPzfux2uwjJMSlbURQkk0nBnGmT\n7JlYvXv3bvh8PoyOjmL58uVYv3491q5di/e///3YvXs3rFYrTjrpJOzfvx/r16/HNddcg+eeew4u\nlws33XQTfve732Hu3Ll444038OabbyKdTmPFihUid0tRJpPPeW4yigAEqOSDyGaziZAdGUeGGOVc\nN4ItjhFZHQJTPT2zTCaDyy+/HH/84x8Fu5bJZDA4OIjFixeL++D3v/89rrrqKnzlK19BSUkJbrjh\nBoyPj+Ohhx7CJZdcgvvvvx+f+MQnEIlEcMkll+DZZ5/FggUL8NRTT2F8fBwVFRUoKSkRJXVaWloE\nsIrH4znzqqqquF8OHTqE4eFh1NbWimoFBGiDg4M5gJvXSckO3osUNk2lUnj55Zexbdu2nCLeCxYs\nwAknnICKioopASE5NM5QZ319PR566CH09fXh1ltvxZ///OccgdcZwHX8zQiI6H0nbzfaZ6rtGTE2\nen/L24yYLS2g4nOiEHjQtp3P9NgkI1CQb1zyASS969U7Xj6/WWCr199iWDIjZjvfPoW2y+fV9inf\nvVaI8TO6P47GtEDT7NhPB5s2QIuJ17IQKB0dwQeZHjpnp9Mp8oU8Ho8IWQGT5Xo8Ho/IPwIg2BMm\nYTOPqby8XOR88TzAJAtBQCcn6xNIKIoiwBj7S8aLkg8ul0sAEobRmpubRXkWMiMMyVHzK5lMClau\np6cnR4l83rx5mD17Ns455xysWbMGDz30EPbv3y9EUFVVxQMPPCDqMra0tAAAvvzlL6O0tBTNzc34\n6U9/Crvdjl27duG0007DwMAAqqurBasmjy3ng2wVw26KogggK4uAkknRjhmBMYtWywsI+OPh+FdW\nVoqQJksY7d69G//xH/8h9t++fTu6urrQ1tYminoTJA4NDaGtrQ2hUAhbt27Feeedhw996EPo6urC\nFVdcAafTidHRUfzyl7/Eq6++KkKyo6OjOT/eTCaD8vJylJaWCrkJAqZAIIDm5mZRxJznp7QGV3uy\nALYsE5HJZHDSSSehpaUF9fX18Hq9ooxTMplEOBzGww8/LOpzXnzxxUKPzIxxP5nlIuCaPXs2Hnjg\nAdx444244IILRH9mgNbRm5HzM3JYWhaF22TTczDcns/RmAUUZq5B+32+7YXYK73+6DEVUwEN2jby\nmRHLVSx4KtS+WfBkxCzJZsQsFupDIdMCPiMAaPYZodd/M8yj2bbZ3rFq83jbtABaHCStlhEf/syR\n4b7JZFIwUYqiCIaopKQEjY2NKC0txfDwMIaHh0UBaoKCOXPmoLq6GhMTEwgGgyJ5vLy8HHa7HS6X\nS4QQk8kkksmkcICsfccl9LIOlqqqOdIM4+PjGBoaQnV1tQjNUci0vLwcHR0dACD6LYfgyKDE43Hs\n27cPDocDsVgMN998M2w2G1atWoXe3l584xvfwGc/+9kcJon5UizBMzAwgL6+Prz++uuYN28eLr30\nUrS0tOCSSy7BM888A5vNhr/97W9YtWoV+vr6UFlZCZ/PJxLxGQKjUVOM4Vy9BQNcSchx55xynEpL\nS/HKK6+gtbUVyWRSAGT5AWOz2VBfXy/GKJPJwOVyoaamBmVlZSKk+e1vfxt33XUX5syZg2AwiGg0\nissvvxw9PT2ipmI2m0VPT4/I32tubkYqlUJFRYVg1xwOhwBI8XgcqVQKHo8HNptNlBRyOBwIhUKw\nWq2YNWsWSkpK0N3djUgkgkAggFgsJkKmBFUulwsLFy6E3+/HJz7xCaxevTpHiyuf+f1+/PrXv8bg\n4CC2bt2KiYkJnH766bjkkkvg8XhMPYjleeNLgKJMFsBesmQJdu7cid/85je4/fbbc+pkztjUzAxT\nZMbx6oV09PY1Gx7KZ9rzFOu09ECSETgsZMWCLm0fjMYtXx/z/V1MX4+FFRqvfAxevraMGD+j483M\nWzHjxP+PBTgyYt+Ops3jbdMCaMlsBh0BB0/Wz6LTZ/iNEggEWpQtiEQiYhWgrEXl8/nEajMmb7vd\nbvT29iISiYjvCQ740NGqtlOziQnzZLIURclJzCY74XQ6kUwmRaK8z+cTyucMM5IlYQhqbGxMaEf1\n9/fjsssuQ2trKzo7O3HdddeJ5G4mjXs8HtF3OlU6fo5vV1cX7r//fqFxdeWVV2Lfvn3YuHEj3njj\nDSxcuBCRSEQonsvFsgkSqVEmi6sSBBMkygBZ/p9AK5PJ4Nlnn0VbW5vYrq3lqCgKGhoaMDw8jEQi\nIdhO+YdE3bAvfelLcDqduPPOO1FRUYFDhw7BarUK9pBj2tnZiZqaGlGMuqqqCps2bRLiqk888QTq\n6+vR0dEBq9WKgYEBIWgaDocFe+lwONDZ2YlIJJJTSQCAKHZNYFZWVoZzzjkH1113HVwuV1EP55qa\nGnR3dwv2L5vNYt26dXjhhRdQX1+Pyy67DMuXLzf9hksAy7AvAHi9Xlx55ZU455xzcPnll6Ozs9NU\n32ZsapZvrswwPvmYr3zHyfvrhcj0tudzXoXAY7HAqhDAMvu7MQKfeoDraENPx+oatW2ZZQSNjtE7\nnwyi9UCU0T1xtGOk7e+xYKOM7lftOaaTTaui0nKRZJkpkmvRlZSUiFWFIyMjAICqqirMmjULiUQC\nu3btQigUEuwKmRWew2azCQmDSCQCVVXR0NAARVEQDocxOjqKeDwOIDfpWc5RYnkcVVUF2xKNRkVu\njsvlgtPpFCxJaWlpTn6OXNiZIIbhTGBS4Z7yEIlEAm1tbXjxxRcxMjKCb33rWznOMJlMoqWlJWfV\nncwueb3enET1733ve/jZz36GX/ziF1izZg1uu+02nHzyybjpppswPDyck2MUiUTgcDjgdDrFIgTq\nesm5PTIYk4s7y+KZ8rwqioLh4WFUVVUhEAjksF0cY0VRcOKJJ4rx5zVFIhG0HM6lkld5ptNp3Hrr\nrdi5cyccDgd27dqFVatWibEkYLZYLNi2bRvWr1+Pq666SoQcR0dHsW7dOuzZswdbt27FwMCAAHYj\nIyOIx+Po6+vD4OAgDhw4gHA4LAClNuRNti+bzaK2thZXXnllTpK7WWN4k5IlY2NjSKVSSKfT2L9/\nP+655x5cffXVeOWVV4pumwtGKMkxZ84cPPXUU7j88svFPtPxgTVdrVhmQ8/x0fI5Eu359JymGQdq\n1I52Xy0Y0HOURn0rZHpOX/7f7AtEvvMbja3276kyU0ZzpDfuZtkhI3bKbH+1jI/efSZvz9dOoXNN\n1eRz57uXimmPdjz6e7Q2LRgtLXrmijY5SVcOX9ntduEgmbzN8iRMcKaTYphRVnWnurjNZkM8Hkdt\nbS0ymQyGh4cF+0GtJofDIcKGZLTkJG/2nflVdL4MR5HV8ng8SCaTiMfjKCsrE8wb9ZR43tHRUbhc\nLrz44ouoq6vD0NAQXn31VVxzzTX4/ve/D7/fj9LSUthsNnR1deHJJ59EIpFAZWUl/vGPfwCYZJbu\nvPNO+P1+vP/978eaNWuEZtTAwABKSkpw2223IRwOw+/345RTTsHo6Ciam5tRWlqKbdu2CZAzNDQk\nwqq8XuZkyewVdbOYR0bglEgkBKsoF+QeHR1FMBjEnj17xIo9zj2B1/z587F+/XqxICGVSuGll15C\ne3s7tm7dKu4HAuLx8XH88Ic/xLXXXou5c+eip6cHtbW1SCaTIqz44x//WIAmhgap0B+LxXDw4EF4\nPB5EIhEBNnmtvD8JLPmDZqiQ48PQ6kknnYQHH3xQCN8SZJq1dDqNgYEBuN1uIRRLgM8k+1gshh/+\n8Ie47777cNttt2HJkiWm3/yBybwtqv5XVFTgrrvuQlNTE775zW+a7ueMTf2tXMs86AEbIxBUiLUo\nBLK05zHbZ73jp2LH0yHmGzszY2PEHuntV0wITQtWjeZKz/LdB3Lf8jGjetdg9lxHY2aYxmPFcLGt\n6fSiOC2AFlkr/i8XXZbBDBkMhtzIJBHQUGgyFouhvLxcSCzIK8foQL1er3Bc4+PjIsxDYEBwxPwq\nCnzKavI2my1H0R2AAExUR+fxMmhTVRUejwfDw8MisZ4hQIKuqqoqjIyMCEapq6sLixYtwoEDB5BO\np2G321FTU4ONGzcK1u61117DBRdcAKvVigULFuCss87CX/7yFzz//PPw+/0444wzsH79elRXV+O2\n227D+vXrsXfvXjz88MMYGxuD2+3GxMQEFixYgEOHDqG1tVUkpI+Pj4uwLo0sFtk0zo+qHikzJINk\nsmAM395xxx248sorxfw4HA4xT5lMBk1NTWKOOC7PPvssvvKVr+AXv/gFzj33XGSzWaxfvx6LFi3C\nyMgI+vv7ce+992JsbAwXX3wxli1bhueffx6RSAT9/f0CBMllaqqrq8VKQuZ+RaPRnFWiNJmlozir\nqqqC5SSYb2lpwa233orx8XFxTzHpXA5R53uA9/b2oqurSwA/j8cDj8eDTCYjRHipsWa1WnH77bej\nuroa119/PRYvXqzrLLQLOwAIBo7yI9dddx0aGxtx7bXXFhXqnLHiTQuY8jEXRk61UGhPa1rGQz5P\nsc5JG67SuzYzZnbffKBUr2/a8S3E4sjn0bZbCMjomR7gK8TU5RsLvfvFqO/y+Y36Ju9vFoCaYcGM\njjmegEv7ojGdwNa0AFoAhEAkB4iJu7IeEZ2DoihiRVw8HkcikYDb7RYr/IaHhxEMBuFyueD1ekVi\nMleMEUTRgaXTabhcLrhcLsFejY6OCtaK7FQikRDMFnOwGCpiKJD5VVRdpyinzL6VlpbC6/WKnDQm\nelssFoyMjGDTpk1C2NPj8WDu3LnYuHGjuGlYVBiASIg/dOgQVq1ahWAwiHA4jIsuugixWAznn38+\n5s2bh5deegm7d+/G7t27sWrVKvzlL39Be3s7SkpKcPbZZ+OBBx7A4OAg3G434vE4AoEAUqkU3G43\nAoGAAAdkrzgPdN6cQ7I/BFOy/IOcz0UwSzDMsB5NVVU0NjaK70pLS5FIJFBRUYHW1lZMTEwI8dfS\n0lIsXboUb775JiorK/H666/j7LPPRkVFBe6//37EYjHRP4Y0yZydffbZWLduHQYHB8V89vf3Q1Un\nSylRMkRRlJx6kwxpUgaCCyHGx8dRW1uLG264QYT9GKKjxAfb7u/vxxtvvIHNmzfjwIEDIkRYUlKC\nAwcOIBQKIZlMCnAXCoWgKAp8Pp9Q9Gf5Ja70HBsbw+23346ysjLce++9cLvdYkx5LzMfjvc6r1tm\ney+55BLU19fjgx/84AzYOsaWz5nlCzmZZakKORgjR2zkDPO1p+27HojQY9+MrrGQGTFNem1p2y2G\nSdJ+Zxa4TtWMwJfemBqBWvlYvevLd01m5k0GMVO9xnwvl9rrMAu49Po73cDWtAFacrIzc4oURckp\nd6Oqk7pAjY2N6OrqEgNIVoqgippFLpcLIyMjGBkZgcfjESEmu90Oq9WK8vJyJBIJpNNpOJ1OkUvF\nHK10Oi1UzNnHZDIpAB//l5fGOxwOpNNp4QTJSLH4s3wcGRGyJmRb5syZg3A4LIRW9+zZA6/Xi6am\nJpx77rk477zzkM1m0dXVha997WsoKytDX1+fEPasq6sTyu+LFy+GxWLBq6++io0bN6K1tRV79uxB\nSUkJgsEg+vr64HK5UF9fL667o6MD9fX1CIfDIp+M7AmZFAIqQP/NiICBWmFyIruqHinjA0CEHdmG\noihC54qAjInvDocDIyMjOPPMM8Uihuuuuw5jY2Noa2sToHDevHlwOp1IJBK4+OKL0dPTA5/PJ8KP\nS5YswcqVK/H3v/8dBw8eFAB6aGgIwJGKAzRZLZ+hWwJMAtBYLCZCrKxSkEqlhDBsOp3G008/jXXr\n1iEajcLr9YrFCnIZKJ6X987ExIQYT75YDAwMCJV5gn4yU7FYDMlkEldccQXe/e534/rrr8952HCs\n+b+s+yUzZaeeeir++te/4oILLhAvF7LZbDYxJjNm3sywUDK40h4r728EvvQAhp7JIEvL+JhhgPIx\nWoWuJd81yX0z+r7QufMBBu1+hcZQz6bC2BULVMwwakaspBHIynf/mW3D6NryXYMRoNcDVMUALu31\nT0ewNS2AFlkRmS1hzov89s39AoFATviDopPJZBIVFRUIBAKIRqNCz4oK6lyNJydsc6VfPB5HeXm5\nmBCuZCQjwJVpdHrZbFbUFGQSNPtCsBUOh+Hz+USIEZjMLwsGg5iYmMCiRYtyChdbLBa89tpraG5u\nht/vxw033ACHwyGOqa6uRjqdxtVXX43Ozk60trbi6quvhsViwamnnopt27ahtbUVf/rTn9DV1YXb\nb78dwCTI+djHPoYrr7wShw4dwq9+9SvMmTNHgIK2tjZs374dFRUVePPNN+F0OlFbW4stW7Zg1qxZ\nAIDBwUF4vV6hEA9MMmsEhwQZrM1XWlqKdDqNxsZGALk/Yo4hALFyVJbv4NwQPIRCIcFGZjIZPPTQ\nQ2hvb8cpp5wCv9+PiYkJBAIBsVrwrLPOQldXFwYGBjB37ly8+OKL+PjHP46RkRHs3LkT8+bNg8fj\nwRNPPIH9+/cL0BSJRMQPVGZQ5XBhRUUFrFarqGNJlotsbCqVwsDAAN544w0hFrp+/XocOHBA3Hse\nj0ewmel0WrBjZHWZjyaHpOX/GYokW1ZeXo7KykrRFuVAHA4H1q1bh1dffRVf+MIXRPklmnbBgsw8\ncvHDihUr8Oc//xkXXnjhsfipz5iBaR1qPvbH6LMeO2V0LjPf67Vt5BynAiLynVt2kEZO1wjA5QNe\nhYCCdgzNsF6FrvlYsEFsR6/f2m16pgfS9O4XIzBX6BxmwLzR9nwAUDv3em3le6mYLmBrWgAt4Ej+\nlcxoAZMDJRd0JqPkdDoRDoehqqrI7wkGg1AURTh+JoxTU4rCkbJWl9VqFSFBudYfgV8kEkFZWdlb\nZB/IQsh1E+lIuZIrHo8jHA4jFouhrKxMMAChUAjRaBTz588XTpahSa/Xi7Vr1yIajWLz5s2wWCxo\na2uD3W7HzTffjNWrV6OtrQ0ejwcHDx7Et7/9bVx44YU49dRT0dXVhcWLF+M73/kOTjrpJLS2toqb\nkOCS+Vm7du3CL37xC2zbtg2JRAJnnXUWysrKsGvXLkQiEXR3d8Nut2NkZESUI6qoqMiRbuA8McdN\nzl8jkKitrYXVahXMlDzfqjqZq8bwFfXLOOeKoggtL+qPZbNZ7Ny5E4899hhuueUWkQ/X3NyMZcuW\nYcmSJWhvb0draytqamoEqxiLxdDR0SGkIu68807Mnz9fSEhEo1HRNy1zIwutkj1NJpNiHGQHQPvb\n3/6Gl19+OSdMzPtldHRUtMl7kSwWAV4mk0FlZaXQeZOBKPcjSIrFYohGo/B4PEJjjOwW77m77roL\nLS0t+O53v/uWvno8HiEKy1W9zJez2Wxob2/H73//e1x66aU5x82wWUes2Ae5URhHey+ZYWsKnT8f\nSyGbkbPV66fedZgFPIX20YIB7pcPXOkdq9eG9tzavwuBq0J91/teyxYeLRilmQVZen0yu7/eccVY\nMb+LfGOfDzAVYr+mA9iaNkBLTpgm2KIT499kGtLpNHw+H2KxmABIDMFQdLKqqkoMLpPQa2trBUtC\np8eBp14Sv2O+FwABqvi2T1AlO1mCDjofMhehUEgUvXa5XIIJo0NlPUMm9jc0NODHP/4xFi5ciDPP\nPBNjY2PYtm0b1qxZgxUrVqC6ulrkg+3atQuKouC1116D0+nEvn37cO+996KhoQF79+7F+9//fiQS\nCTQ2NmLt2rWYM2cOGhoahNhreXk5zjzzTDz33HNYu3YtEomEADvDw8MiSXzJkiWwWCxiRSRDo3Jx\nYlniQE70pugoACEYyu8BCG0phm9pBDH19fXYvn07wuEwqqurhbo5QV8mk0EsFsPAwAACgQCeffZZ\nkRumqpN5cU6nEy0tLWhvb0c8HseGDRswZ84cVFRUoK+vTwB2nlfPyFYB+d+m5f0ZEo3H47BYLCLf\niy8NvKc4jrK+laqqIleMDwgZAPK3wH3D4TCi0ShCoZBQkGfOFc958OBBrF27Vtwjcl9ZFog5Zyxq\nriiThcHPPvts3Hfffbj++ut1r/edbsU6E7PfF3pb1x6nB7wKMTJmvisWnGn/znes9hr0Ph+NkywW\nJOQDk0ZWbP/05qkYVrAYQGh07mL3MXOc0T14tH3TA/RG948emPxXg61pAbToVGXGiJ9VVRVOk9vT\n6TRCoZDQUJJzhcgUJJNJ+Hw+RKNR1NbWore3VzAi2rdG5thQjJKOnwwN97XZbCIRXSvCKTNiVGYv\nLS2Fz+dDMBgUIJDL9HksgV0sFhPXYrPZEAwG8de//hVdXV2YmJjAySefjNdffx0+nw/Dw8O48MIL\n8X//938YHx/Hvn370NnZKZg+v9+Prq4uUR5ncHAQpaWl2LNnD2688UaUlZVh9uzZmD17NhobG/HU\nU0+hsrISjz/+uEiAdzgcaGhowK5du0SyfiKREEnfTFzn2DM0yjAcx6O+vl6EVYHcHCyHw4FAIICa\nmhoxf/wRMBx7wgkn4JlnnhGK99zucrkEeyPnClmtVhHiJQuUTqexc+dOdHR0iBJBixYtQjAYRDAY\nFMeafRibodW5D0PeZIsIymXWjuBf1pKTc9q0AIvb5AcGWTBqirndbhEyJ2MITOZ93XLLLbjoootw\n2WWX5VyLw+GA1WrF0NCQeHmRS0ytXbsWe/fuxX333WdqnN5JZvYBXohNMOt4CznCQo6cv0OjPpkB\nG0fjULXn1WPy5O/k/QuZ9rrMgDXt2BTTf7mf+cCwdty13+fbpr0XjhUrdjztWAIaswxVPqD6rwRb\n0wpo6Tlk5ovwDZ617yjcCAA+n0+8gXNfv9+PUCiEWbNmiaRzOt6xsbGcVVoERnSEiqIIqQPmalHG\nAThSP46aWjKjRXkAtuF0OlFWViaYFwBCYZ2hH153KpWC1+uFw+EAcITlGxsbE8xSf38/WltbUVZW\nJvoyNjYm6joCk6BHvtmy2Sy8Xi9OPPFEOBwOfP/734fNZsPixYuxY8cOIS2xf/9+ZDIZJBIJVFVV\niVWSDCcxh4dzJSvyM5mcbB2BK1cOyvlGnMuysjIcOHAAVVVVAI6sWmTiucPhwAknnCC+Gx0dhc/n\nE3lzFN1k6E3WXyPgZuFmMjIrV67E9u3b0dfXJxgmMkPs29E8xORSjmGKAAAgAElEQVRj5aoG/Mx8\nNK2TksFevge+ljHgfrwGRVHEWKTTadTU1IjzcVGBx+PBunXrsG/fPnz5y1/Oab+0tBSVlZUYGRkR\nwI+hX4vFgltuuQX79u3DU0899Zb+vJOtGJAl/53PMesdo/e2bqZfRgxXPqYgn0PS+50YAUIzDJ4e\nG3E0pm1DjynUAzzasZnKefWuSW7baFzzgUBtf47VOB1rO54ARjuW+cBWMW39M2xaKMOTHSLAkIsN\nywM6PDyc44zJRAWDQfT09IiyKMwPisVi8Hq9IvmaS+QDgQBGRkZgs9lEcWe+zTNBmCyC1WoVEgTy\nKjSGhbi6keCLLBhFOZlgzTARa+VxxRlDoaqqilV/mUwGra2tGB0dxcTEBHw+H+677z4cOHAAo6Oj\niEajcDqd+MxnPoPPfvazOP3001FbW5sTLmUOEYHI3XffjXA4jMrKSlx66aVYunQpli5disHBQZSU\nlKC3tzcHDNbX1+PQoUMIh8MitMbi1wDE4gM6YFm8lDpVXEAg61AR/Ph8PpFvJQMdeRzHx8fR2toq\nfhDhcFiACIZ5HQ4HbDYbfD4fKioq4PV6UVVVhYaGBtTX16O+vh7Lly/HY489hvr6euzYsQNutxtj\nY2MigZxms9mO+cOL88F25RCrnO/GffM5Wm17eg9gtsfcrc7OTvT09GBkZATBYBCRSERoyfX29uLz\nn/88fvOb3+Sc1263o6GhQbx8UITW4XDA7Xbjl7/8Ja644goAx/fB+nYymc2Q/+WbRwA5+8rtFGv5\nAJP8txHbYnRfytdh9px67Wg/67FbRlaIISp0jFnLx5TIf5thzrTtGbVd6Hk0HcHW8bBCjKqZcdC2\n8c8cu2kBtAAILSq90B7DQNTTAo5IOjAnqK6uDo2NjSK5WlEUkXdF6Qe2PTY2hmg0imAwiAULFqC8\nvBwABPihlIDNZsupFUgHKde34w9L1tNiaIhyEDJgImhjuzwH6yHG43EEg0G0tLTA6/WKlYE2mw2p\nVAodHR14/PHHsW3bNmzZsgXve9/7sG/fPnzyk59EKpWCzWYT0hDsNxXJb7zxRjz66KOora3Fc889\nhzvuuANbt26FokzKERB0sc5iVVWVYEIIppgfNjo6miO5we9kjSrKWnAOZYaOIFN+uDPniitNs9ls\nTvFkzjnHu6KiAi6XS9RldDqdsNlsKCsrE4xkR0eHyMNKp9M4//zzAUwCuYGBgZx7sLq6+rjc2zQ9\np6oHmowcb74Hg3yM1ilTCT8YDCIWiyEYDGJoaEiA5W3btuGOO+7IOQdZUL448HfHhSU33XQTrFYr\ngBmwZcbyAR1tSEjPActAjceZdTDFmvaeNLJC4E/LOOS7T4wYKDP90N7zZn8nZs0MSNVuN7qeYtsq\npm9vZ9BVCOjL2wq18a94Xk0LoEW1aj7Mmd8DQISmRkdHRWhQDvFRFZ0gjCvCuFKL7JfMOqVSKSQS\nCYRCIcTjcTQ0NKClpUWESsbHx3PYJYplsk8EPXIekMx4sV8EE6lUCsPDw0gmkwI4EWwxr4tgJpVK\noba2Fp2dnTjxxBNF+C4UCgl1cQDo6+sTADEajSKTyeDee+/F6tWrcc899yCdTsPv94u8JgA44YQT\nUFJSgtHRUdjtdiHJcOedd6Knp0cU22bfGZItLy9HKpVCMpkUgpsy0OU4k00h48TVfizCzX4MDw+L\nvC8yg2TB2JacbC/nWsXjcRHOYp4WAazb7Ybf7xfgiwsj3nzzTbjdbgGyqKyvtd7e3mN2T5uxQpR3\nsQ8EPfDG30smk8Hg4KAAnclkEpFIBKlUSrC8N910kziG5+YqXIa3+XubO3cufvrTn76tH+7HysyC\nFi2jxO3HitXQ28+IidLrC/c369DkY47WyRUCKHrARtsHvf6YtXxjp/dypAVAesyd0dwaAUztGL5T\nQJaeFQqzmj3+nzVu0yJHi0rsZWVlObXuyJYwzyYYDMLj8QjmBDiSXyPLCjBU+I9//EOsNHS73VBV\nVWgxxePxnPCa3W7PeXtnyIvJ9wQsBBIEbWRfCOwSiUROQWwm0LOWotfrRXV1Nfx+PzKZjKi1R1aO\nNRvXrVuH//mf/8H+/fsxMDCAn//850gkEnjggQewbds2NDc345xzzhHJ4Bs3bkQ2m8WnP/1pDAwM\n4Mtf/jJee+01XHjhhejo6MCSJUvg8Xiwe/dunHnmmbDb7Vi+fDkeeeQRvPe978XcuXPFWC1duhRv\nvPGGCBdxgQCFOiORiND+IoDinHHFJkN6DC/KiwAo5snVoNSl4sIAGplDslgEYCx2rSiKyOfinGQy\nGYyMjGDDhg1ixV95eTk+/OEPY3h4GM8++6xg5f7VDyejsIn289H2U5bi4CISecUj2V6r1Yqbb74Z\n99xzjwDFvH/ZD4Lc8fFxfPCDH0R7ezs2bdo0bXNGppOZdfBGjIjeftq29cIj+c5ZLOAwE8YzC+jM\ntpHv3tLbzyw4NRPeM9MHfp/PjECRmbkxYrinEjJ9O5gea69lNPOB/WMB/Iu1acFosWwOAYfMcGUy\nGQFgWCuODAdwZHUaHQNXC5JJItNER0MldiqeM58lHo8LtoR1CQm8CNxknS+5dAlrABJsRaNRRCIR\nUVKFJVjGxsYQDAYRCATgdrvFCkVFmUzgrqmpgdvtRmtrK7797W/jxRdfxIUXXoi5c+fic5/7HJ57\n7jlcccUVePbZZzExMYGrrroK6XQa1157LZYtW4ZFixbh0KFDCAaDOHToED7zmc9g/vz5WLVqFRob\nG1FWVoZTTz0VTz/9NNauXYvq6mosXboUAFBeXg6Xy4Xq6mqEw2EAQHd3t2DbCDJZoFkeDzpfgiSH\nwyEkJFRVFRpNDJd2dnbC7XbD7XYLZklRFDGesngtGS7+IOLxOMbHxxGNRsV2WXrDarXiqaeeEiyc\nx+PBRz/6UcRiMTz++OMAIPKX3kkm54FFo1F0d3cjEAhgYGAAsVhMFGCPRqP4/Oc/n1NOiQXZZeO4\n/+AHPzhuIay3i+VjiAodpzWjcdYDGWadsdH8GTl47T7acxY6X6FxMDqHGTMCRNqwazEgS26jmD7n\n66OZ6zHDar2TTGYL9VhEfqfdpne8XjvH00wDLUVRShVFeVNRlMcPf56jKMpriqJ0KIryO0VRbIe3\n2w9/3nf4+5ZCbSeTSXR1dSEQCEBVJ1fwyerriqIgEAgI9ogDw8RiMk901GQ6Zs+eLcKJFotFhD2c\nTie8Xi+8Xq8oBsxwI8GWvLydKwflECVDKsCRBG7Z4auqKoQkyZxx5SKT5CkMCRwJR5ItePTRR2Gz\n2fDII4/gzDPPREVFBZ544gncfvvtePDBB7F06VI8/vjj6O/vx89+9jO0t7dj3rx5WLZsGdrb27F6\n9WqxmjAUCmFkZAQHDx7Exo0bcd555+GXv/wlzj//fPznf/4n2tvbhUTCypUrMTw8DJ/PJwRUWT6G\noIq5PbxGRVFEaaO6ujqxcpJglTczmZH9+/ejqqoqJ0Qst0vWEEDOSke2wbAlV4MS5KVSKfzlL39B\ndXW1ECC9+uqrkUql8Otf/xrxeFy09U4x+WFE1k9RFIRCIfT39yMajQrBVoaOQ6EQ7rjjDgG0stms\nkEYBINiv8fFxLFu2DGecccY78sEvWz7GpdgHeT4m0wwDUsgZ6wGnfKE2eZueczICJ2ZYKCPTXoMZ\nsJUPmBSaB6NxMOpvof2m8nvIB6LN7vt2NiNW14jBLTQfWuB2PK0YRutzAHZLn78F4P+pqjofQAjA\nVYe3XwUgpKrqCQD+3+H98trExAS2b9+O3t5eEdrgwFB8ksKeAHJWstHJ83/qJLEUjKzpRIAEIEcL\nSitdQKaLx1qtVlRWVmL27Nmor6+Hx+PJWT3GcxMIso8Mp5EtGxsbg6JMLr8/ePCg2A+YnPShoSEE\nAgFEIhFcfvnlaGlpQTqdxkMPPYSLLroIZ555JkpLS7Fs2TLs2rULVVVVeM973oMbbrgB1dXVCAQC\n6OzsFCKpmzZtwubNm0UZoKamJlitVnzpS1/CjTfeCIfDgXPPPRdjY2M4/fTT0djYiB07dsBisWDB\nggWIRqPw+/2Ix+NCTDQSiSAWi4lrZ46V0+mEx+MR4NRisYjkdDnBPZPJoKenBw0NDSJ0xRAh8+O4\nEpCsGR28ohwRrM1mszl1KNPptGBoPB4PwuEwrrnmGiQSCbzwwgti7o3e9t/ORiejqqp4gSktLUUs\nFsPIyIgA4iMjIwLA9vb24qtf/aoYc74AAbmrhFVVxfe+971p/+A/ni+Kh48ryKQAU3OQZtmPfO3n\nY7kKOTAtA6AHfo7F70l7Hu31FBN61R5TaA6K7bsZtnAqc60HFPVA4Dvl2WVknFMtgC70wqDd958B\nsgCTQEtRlNkAPgDgp4c/KwDeC+CPh3d5CMDFh//+j8Ofcfj7c5QCd4WqqtixYwf27Nkj9HtkBXUm\nhDM3S5YDkPN/AAg5A+oFyasBOajcXzkcsmPJHJvNJpb4y4V3Ga4sKSmB2+1GeXk56uvrRfiRwJDy\nEEyCJ1slgztgEkAMDw8jEAiIciyqqmLWrFmidMyOHTvQ1taG888/H+Pj4/j1r3+NF154AWeccQZW\nrFiB9773vSKpX1EUdHZ2YtOmTejs7AQAVFZWoqmpCU6nEw8++CDWrFmDefPm4Zvf/CZUVcV//dd/\n4fzzz8ell16Kd7/73Xj11VcRCAQQCoUQi8XQ1dUlVv3Z7XaRCzY6OpqTCM+xc7lc8Hq9IhzIY6lM\nrqqqAMejo6MoLy+HzWYTeVrMwyMgo0DpxMSEaAM4sjKR4Iv5dJlMBps3b8aZZ56JAwcO4JOf/CRK\nSkqwe/du7N+/X9wfDA0z3+ydZnyZ4ItENBpFf38/wuGwWI3InMSuri7cfffdAhBzUYhcVFxRFCxZ\nsgQf+MAHpvvD/7i9KJ500kkApp6cnC80V4yZCXvlC5cY9SMfSJOBTDGMjN72QmCx0HeFjP00w/QV\n6mM+y8eOafeRX4Km2tY72YxAtLxdb5u8/Z9hZpPh7wVwCwDv4c9VAMKqqjJZqgcAa3o0AOgGAFVV\nJxRFiRzefyTfCVRVxcaNG4UWUmVlpRBYJFCSWShZZVubx8MB5Xa5QDVX7imKIpgYMlJMYmcIUGbC\n2C7PoyiKWMk4MTEhVinK/ZLzyWQ5A+afdXd3o6qqSiTF2+129PT0iET92tpaPPnkk0LvqaysDK++\n+qqQXnjve9+LsbExrFmzBuPj46iqqsLOnTvx/PPP43vf+x7C4bAAiC0tLWhoaEBXVxd6e3uFcvgL\nL7wAVVXxjW98A7fccgvi8TgaGxuxa9cukbc1MTEhpCfC4bAAO0xeZx1JymOQOSkrKxOhWY5tJpMR\nQIwFteWSOXTiHPdsdrKOJUEYQStr8fEhxTl68803cdJJJ8Hn8+HQoUN48cUXhdyHLHyrKEqOhta/\no8m5iWZM++Cx2WwYHx9HIpFAIBCAoigCfFZUVIgVm0888QTOP/98wWKFw2GUl5fnzMcXvvAFPPHE\nE/+0N8RiTHpR/AaAG6UXxcsP7/IQgNsB/AiTL4q3H97+RwA/UBRFUfNc1KZNm94ShtBjVcwAEe0c\nGb2t64U98p3b6Bj5eyPGxKjvZhmmowkhHq1pGTczYFS2Ypm6YkCzUZjLTL9mrPDc5LvvtIwt/cjx\nGuuCjJaiKBcAGFJVdZO8WWdX1cR3crtXK4ryd0VR/k5AlEqlsHPnTiGUSTZLZqnkHz21nQAI3StV\nPbIyignZTqczR3ne6XTmLFkvKSkRkgbApPxDLBYTgCeRSCCdTiOZTIrQiraWXkVFBSKRSE6CNvOG\n4vE4otFoTk4R+8FjKWLa2NiI9vZ2lJaWIhKJ4Ec/+hEuueQSAU7sdju6u7vh9/tht9tx+umn49FH\nH8X999+PcDiM0047DbNnz8aePXtQU1MjCicnEgkMDg6ioqICDQ0N8Hq9SKVSCAQCaGpqQjabxWmn\nnSbGO5vNoqmpCTabDaWlpejr6xPlXQjeAAgmi5pLBDTULpNLyoyPjyMYDGLp0qUiVEhAS3FTbuP4\njY+P56wIlceXiuWKoojVhaqq4uyzz0YgEMDLL78sQsLAEfaL4//vblPNNeNDRQaaBFtDQ0MIBoMI\nhUJCjuR///d/RSkmgi2+nBCwtre3CxX/aWh8UeSAmX5RBMAXxRyTn1+HP8vf6XYiH5tiZHogSK8t\nvf30QntasCF/b8Qo6YXf5O/MsC6F2KRCZnSsUZ/43VTZwkJO12hezB4vHzvdXkz+XazQ/SDfc4XG\n+GjuTTNmJnR4OoCLFEU5COBhTL4J3gvApygKGbHZAPoO/90DoBEADn9fDiCobVRV1R+rqtquqmo7\n34oVRUFfXx86OjrQ29ubU29QZooAiNV+THL3er0iyd3tdotQFzWTmATMBG06csoQqOrk6sTR0VEE\nAgHE43FEIhGMjo4KsMRyPcwRktkxh8OBgYEBhEIhsd/Y2JhQcueKPVkratOmTSJXhon2drsdr7zy\nCoaHh/HYY4/hd7/7HSorK1FbWyvaTSaTePzxx/HNb34TW7ZswTPPPINPfepT8Pl86O/vx3XXXYf3\nvOc9yGQyCIVCOUWCqblFtuj+++/HF7/4Rbz44ovYvn07TjjhBPz9739HVVUVampqBChJJBJCdwmY\nBLkc88rKSlEfke2m02lUVVVhYGBAsFPj4+PYuXOnyM+yWq1iNWk6nYbVahV/M7drbGwsJ6SrKIrQ\nIistLYXdbkcqlUIkEkFXVxeuv/56JBIJHDp0SNTs0zKQiqIIluvtaLJEhtbxym/2fPhks1m4XC6M\njo4iGAwilUoJgVe+VHz9618XoVzWQ+TCEN4jV1111bRzGsfrRVF+fumdVwta9MCL0XHa7wqFr/Qc\nSTEMiVGYUK99ozd/s3024/DMbDM6r/Y7LeNn9jc/VWbWLKDUA8AyeDMCctPt9zWdTA7D6r04GAFw\n7fHHwwoCLVVVb1VVdbaqqi0ALgPwvKqqHwPwAoC1h3f7BIA/H/77L4c/4/D3z+ej3bWWyWSwfft2\ndHR0IBAIiARpslp02HyjVlVVhLXo0Cnn0NPTk8N6cdUh5RbImITDYQwNDaGrqwuHDh1Cd3c39u7d\ni4MHD+LgwYPYu3cvOjs70dHRgc7OTgwNDWF4eBjBYBCjo6NiJZyqTpYJonPiCjoAomg0gQqTuQkE\n5BqBra2tqK2thapOJsi3tLTg9ttvFyxOVVUVHA4HhoaGsGjRIrS1tSEej2P9+vX42Mc+hrq6OrFK\nkzXvCDCcTidisRgSiQQWLFiAbdu2wePx4KWXXkJJSQn27NkDAGhpaRHK7qFQSOh9MbTK/CvWRLTb\n7SIHK5VKIRqNwuVyCaDF3Kienh643W6hQM8VnwwtcmxisRiSySSsVquoVUmQLRtz90ZGRnD22Wdj\nfHwcg4ODeO2118R9QrkOuXYlw45vR5PlT7Rsg9YJMDGemmiZTAaBQADRaBShUEjc25lMBjfeeKMI\nxXs8nhx2JJvN4rLLLssBedPEjsuLop5pnbr2f6MwoLYNLTjW26eYbcWGLvVYAHmu84EXs6GwfExQ\nvn2KATGFtpkxs8cVAtba/fTa1wLeY3kdbzcz+l1on3Pa3+NUGc6jtaN5Kn4RwMOKotwJ4E0APzu8\n/WcAfq0oyj5MPqAuM9MYHXg2m0U0GsUbb7whWBLWFOSqMbIdDDsx7McHPnWcCKzC4fBbEp8JkOLx\nOEKhkBAKlVe6kXHhJBGcDQ8Pi9wkj8cjwmbLly/H5s2bEQqF4PP5MD4+DpfLBavVKkAXUTMTyqmi\nzny0VCoFl8uF7du3o6mpCf39/diyZQv6+vpw//3345ZbbhH7ulwu3Hrrrfj617+Oa665BlarFeXl\n5YjH44jFYkI4lHpSAFBWVob+/n7cc889aGxsxIEDB/CpT30KiUQCdrsdAwMDqKurQ01NDVRVFasE\nyYLZbDZR37GiokIkyzMPi4nULH80MDAAn88nQo7AkYc2w7FkB8leEnRS/JShXVmni/Mpi5guX74c\n/f392Ldvn5CSoLYW548rHN+uIIsyHfKDhXlv3Ma/md/IseT4h0IhWCwWseLUbrfDZrNhaGgIv/3t\nb3H55ZejpKQEQ0NDqK+vF/l2NTU1WLBgAXbu3Pkvu36tqap6K4BbAUBRlHcD+IKqqh9TFOUPmHwR\nfBj6L4qvYgovitrQnNSPKTvJQu0VAlL52isEiLTnzgfWCp1f7qcRAOU2o/4W6rP2PMX+zrVjaTS2\nRtu1x2pN7x4oho2csUkrhpkE9EFsPjB8rAFtUUBLVdX1ANYf/rsTwMk6+6QAfLjYjsj5UsBkWZkd\nO3aIXCqCqB07dmDv3r1YuHChWPlnt9tFuRWLxYJoNIry8nJs3boVVVVVInxmsVhEqIplcZg7RRZK\nTrhXVVU4GbneoqzxxJAa84hWrVqF/fv3I5VKweFwoLKyUoCdYDCIdDqN2tpa7N27Fw6HQ0gnkK2j\nntbChQvxyiuvYN68eXj++efFvg8++CDuu+8+bNiwAR/84Afxhz/8AatXr0ZjY6MIW/IayGix/xaL\nBWVlZVi9ejX27t2L3t5evPLKK0gkEli8eDGeeeYZ1NbW4owzzkBpaanI04nFYjmaYszjcrvdAuAy\nPJlKpTA+Pi6uX1GUHP0zJstTBFYue8QQrKzfFAgExApB5oDJOXXJZBLr1q0TqzBTqRS2bNkiHrJs\nj7lfWsHbt5ORsSTQ4kuJnFMny5HwbzKeHDOXy4WhoSEoigK/3w+fzyfC948//jguuugieDwe+Hy+\nHOmHdDqNz372s7jhhhv+HZzFMX1RlE0GE/neoAu9ccv7yVaI7dALlWj/l9kpuV1t23r7FgJbRk7M\nCLAY9V8PXB1PRsdoXAvNmxnQZXQOo+ufYa7ym9HLB6A/jmaYw2JeVoq1acXza5mGAwcOiDAfnWpL\nSwvefPNNbNy4EStWrBA5WZFIRAAtKqOvXr0afX19iEajwtEkk0mEw2FEIhHBnLAsDuvzyaVgmNDO\n0BdzpJjLwjytaDQqQFJtbS3C4TBGR0dz8sGYc9TV1YVkMommpiYkEgkB3pxOJyYmJgQwe9e73oW9\ne/fC7XZjaGgIf/jDH9De3g6fzweLxYKBgQE0NjYKWQYyguwXHWQqlcLq1atx8sknY2xsDG63G93d\n3fjJT36CZDKJc845Bw8//DCamppEojpX5g0ODuaUuyHL5PP5RDkkRVEEcJLzsWSGimwShS85D8Fg\nUDB8LADOcefiAubS8W8ZdBFc1tTUYGhoKIdNoTI9jaDg7Qq0gMkXFPnhL4uM8l4k6AQmHzTcRtFZ\n5suFQiHxe2A+XCaTwec+9zn8/Oc/RyaTwdDQEKqrq0Wu1kc+8hFcf/31uisii10leazteL4oaq0Q\n6NA5b1EhQT2HrXUqZsNX2nb12DLteaYCtsw6sXwgwwyA0x5fLPthtD0fKDRy6mbOaQSMZ6w40Gk0\n7/kYYb35Ox427YCW7AQymQy2bdsGp9OJuXPnAoAIVTFEWF9fL6QELBYLuru7cejQIcyZMwcdHR05\ntQ0ptjkxMSFW+FVVVYlkebkPLCJNB0NhTI/Hg4mJCdTU1IjCvCMjIzkaWaFQCBUVFbDb7RgcHBTh\nl2g0KhgwhkMZaqPMBIEdc4rmzJmDnTt34rzzzsOGDRvwj3/8A9FoFG1tbfjEJz6BJ554Aueeey62\nbNmCnTt3IpPJYN++fTjnnHNw6qmn4je/+Q0GBgbw1FNPYdWqVXjyySdRUlKCbdu2oaamBkuWLMFv\nf/tb1NbWYvHixYIdZIkhJqZzZSDBqFxWSAbIBFrJZFKEp4BJR8+C1KlUCv39/di2bRsaGhpELUMC\nNuDIQ0eWZiBgZdh2bGwMHR0d+MAHPoBEIoFEIoH9+/eLkJjVahX9V9V3hiI8x5x6bgwJM4dQURT4\nfD6Ew2EBnsmkcr75G/B6vYIpZrg2m80iHA7jpZdewumnnw6bzfaW0DpfFLT2Thh/rWmdcz6gcjSM\nlwyQjNgquR2zoKIQyDICOFrGp9C1Gm0zY0ZjPFXL1w8zIUyzADsfczdjk2YEkIxeMviZx2p/E/J2\nuf3jzWpNG6AlO2uGmwi6tm/fjvLycng8HqiqijPOOAOvvfYaNmzYgC1btiCZTGJgYEA4g//P3psH\nx3Fd56PfncHsC2aAwTIASICruEqgREqidilWZMnLL1X2i/RzWVZSimU7i5UqJy+Ok7IrL07FdiUV\nOYkdRWVbcVx+/sm2ZMmxXmLJEUNbkq2FFEXSIimCJABim8Hs+97vj8E5vNPq7hlsJAjhVKEwSy/3\n3r7T9+vvnPOdG264AX19fXC73RgdHcXIyAjWr18PAOjp6UF3dzeX1KEAYFlrixYecg3KIqm0DxVc\n9ng86OnpwezsLJLJJGdiRaNR+Hw+DA0N4eTJk+w2jMVi7MajP7q4xOZQLUWz2QyXy4UdO3bghRde\nwJYtWzA6OgpFUfDmm2/i1VdfxVVXXYVarYb+/n7s3r0bExMTCIfDePDBB/HNb34Tt912G7761a+i\nvb0dTzzxBKanp+FwOPCe97wHzzzzDI4dO4ZNmzZh3bp1zBoS+xYKheDz+TiLkNyFPp+P2Q0CR3J5\nIvohEJvldDo5wL1cLuPMmTM4fvw4i5FS5iAt+tlsFna7HQ6HA6lUqgGsyWV95Li3VCqFt956i8fR\n6XRy5if1BwCP8WozAun0O5KLmitzLluKe0ulUiylAVzI4JXdjCaTiYuht7e3c9Fvmrtf/OIX8Z//\n+Z/sCqbzVyoV3Hvvvfj2t799iUfk4puR242+l7drdSFWm56bSv16KdwiWkyNFoOkBxKbbbeUZgTq\n9Bbs+RyH9qNt9M5jBPKauSbX2CzjMdZ7ENCbZ0bXXQuEaW23FLYigBbdpGlw5IwwIQRKpRLOnTuH\nzZs3w2QyYWBggBeMqakpTE5Owu/3w2w249prr4XVasXZs1krDygAACAASURBVGfh8XgwNDSEgYEB\njumhxYRYDwosp3MRc0KLejabZQBGbjhicugiWa1WDAwMoLe3F6FQiNW1a7UarFYrdu/ejVdeeYVL\nnBBYo4zDQqEAl8uFUqkEAA21+8xmMzweD3bv3o1QKITp6Wlcf/31sNls+M53vsOCoD09PUgmk6hU\nKvjABz6Ab3zjGzh37hyeeuoppFIpeDwelMtl7N+/H7/61a/wne98B263G/v27WPgROCOwFBXVxe7\nIYUQ8Pv9DFApY5PaTACH4rM8Hg9nqAH1TMRwOIw333wTR48eRa1Ww5YtW+D1emG1WrlYNHAhay4e\nj/OxiTmjItSKoiAUCmH37t0oFovIZDI4f/48Xz9i1iigmz7XYlqWch5T2y6WEYNF4Mrr9QK4oBlG\n8iOdnZ0IhUIMWhWlHr9GTJcco0XzmjTfIpEI2tvb0dbWxkKlbrcb3/rWt/DAAw8wI0vX7w//8A/f\ndUDLyPWnXoDVAETeTsu0WKRWFgE9V4oeS6UH1pqxAnr7ah1nOUyL0ZM/N1qw5fbrAWC9hVg+h9bn\n6vYZMYxa51Qf591gRkyq3vZGDxbN/huBraW0FQG0gAtB8LQw0yBQLM6ZM2dY8kAIgY6ODi4KbbFY\ncOLECQhRD6Zev349hKiLWJIrhLSwKG5IDrIHLoA7uW4iBWHLMT3EQKmLHVOMUV9fH4LBICqVCmZn\nZ2G327Fp0yaUy2U888wzfFFpYSOXYkdHB7MwBBJkSYZsNotAIID9+/djenoao6Oj6Ovrw8aNG3H6\n9GmMjIxwnNcPfvADAPVg/e3btyMYDCKZTOL555/HL3/5SzidTmzZsgUDAwNwuVwwm83s6ovFYqhW\nq7jyyitZS6lWq8Hj8cDtdnOGGrWRABYFttMYkVFtQpPJhLNnz+JXv/oV7HY79uzZg82bN3OmJDGS\nNBdIf4wyTGm8HA4HXC4XJzMMDAwgFoshFArxdSLFeYp5o7bSHFtqo/mi/tEv5+Iin5syM8mdS0wh\nZc86nU5kMpkGtpaYPrmAN31XqVTg9XqRzWZhMpk4GYJ0yIg5+8lPfoKPf/zjDLCBumu9p6dnWfu8\nEq2Vm7QMuIyYnlYWb6PjL6Tdeuyb3rFbOZcR+6AFiBZjWqyh/LlsesDQiOFq1k4joKb+XqstenNg\nuQHASjM9hkr9GX3eyjyVP18KlnchtmKAlvqHISuA0/tEIsHMBoEdeiK3WCzwer1IpVKoVCpwuVzw\neDzs/qAFhQQwaWEgpoPaQAs6xVA5HA5umyz9IGdCEjjMZDINxwwEAlwfjtgYmdEipgwAstks+vr6\neNEi9o20t+S6iZs3b8bQ0BDGx8dx8OBBjhGjuoFutxvZbBbpdBpjY2O8GHs8HgwMDGBwcLABDBFz\nRoyPHNxMQdSBQIC1zMiVSNIK9J8kFTKZDI8NuakAYHx8HIqi4Oabb4bX62V3FIFeYvjy+Ty7CCcn\nJyHEBYFRkiqIRCLYtm0bJyacO3eOAQ+NQV9fH9d+pPmylEZzlWL4CMCT+5Pmizy/l9JINFauGuDx\neBAOh3nuCyE4aUFR6hmFpPgus39yW9va2lg7jaozkGQHzYG2tjZkMhl89atfxUMPPcRtonnkcDiQ\nz+eXvM+Xo2mxP3qMipEtZtGdDzBSv24VOLTqltFq20JNDdjU36nbpbWdur1GbdQ7ptECrnXNjc7f\nKqu21KYFbi6mNRt72bTGSAan8mfyMZrNW71jL9ZWDNACwCBGK2i2VqthfHwcO3fuhMfjYVBEWXBd\nXV1c8uXw4cPo7e1FT08POjs7OUaoVCpxWR0CO3JMi6wnRD8MIQQDJdqWFjUS3UwkEg3xVTJLUKlU\nmBnatWsXDh06xMeiIHDKsOvp6YHP52N9L8qKBBqDnKle4MaNGzE4OMiK3oqisJI9AHg8HgSDQXi9\nXhY5pZgaOiYBKbPZjLfeegvbt2+HxWJhAEXFud1uNy/KlCxAgf21Wo2LY8slikgrjFySiUQCV111\nFTweD0wmE2KxGMbHx+H1elktH6hnhlJB8GQyyT8eWfojHo+jr68PqVSKkxwIIOfzeWZkiHGTXdNL\naTabDf/2b/8Gj8eDp59+GgcOHOCxpxg/ik1baiP3s6IonAxiNpvR1dUFq9UKt9vNbj+57JPNZkM+\nn2e3r8zSFovFhkWBtiUh4HQ6DZvNxvP72Wefxac+9akGd7/dbse+ffvw85//fMn7vNpM64lbawGR\ntzda4PVsKRZOvQVJDSTl8xm5ddRta8YW6W1r9FmzfmiBoGaLuB5o0uq71rn0+qbV7lau7WJNbywv\nNthqxgrK29BrwNhdq3cMI1P/JpfCVhTQUhvFkxDYINV1AAxm2tra4HK50NXVxfsJITAzM4Pp6Wm0\nt7ejr68PfX19sFqt8Pl8rExOIIPAnVxrj5gqOrfsPqQSMNTG8fHxhtI08gUi5odUzgcHBzE1NcX9\nogXYbrcjGo0iEAjA4/EgkUjwecrlMrdVCMGMHIEvr9cLv9/PbB/1iYBHLpeDy+XiQHViC0lxP5/P\n4/Tp0xgeHm4ook1j63K5OCONQE44HGb9MXJ3Eqih8xOjQYHW+Xweu3btQjKZRDQaRSwWw8zMDH/n\n8Xh4jKnt2WyW3Y8E/OgclL0YiUQamCOr1YrBwUHEYrF3uKQXa/QDJlZn48aNuPvuu2Gz2XDnnXdy\nEsHf//3f48CBAw3xYkuZdUfZfW63GxaLBT6fDwAQDAYRi8XQ3d2N6elpbNiwgWt9jo+PIxgMIp/P\n49y5c8xSUVxXrVbjWCvSNiOJEiouXq1WWfVfUeq6ZC+99BJuvPFGFAoFWK1WOBwO7N+/fw1oSdYK\ny6HHzBiBqfksBItZOPQWLi2mSMvlpQcw9BgHrXMaMVZa32uxGK20q5lptXs++8vbarVdrz/LYVrM\n2cU0NbDSmufq3438f77MlN42yw0sVwTQkietvBjRIBEQEkIgkUiw6julsLe3t3OGGj29k9hlPB5n\nl9XWrVtZwJOAFjEpiqKwpAMtIOReI6arWq1yPT9io2TgR8ekbDcKRBZCsCuuq6sLs7OzvC+xVlQC\npb29HVarFX19fVxYW24vUGd0CCwSgCOAJ2dHklFgutxeAqkzMzPweDzYu3cvu1kVRWHZCaBe5zCR\nSGBmZgaJRILrEcpG56VsQQK2dC4StKQahMT2uFyuhtg5YuwocxAAZzNSHzOZDLZs2YJ0Os1/BMwK\nhQL8fj9LXVB/lgrk0A/SYrHA7XbjM5/5DJejAeoAaP369XjkkUdgMpnw3HPP4fOf/zwOHTq0ZG2g\na0sMJZVDIkarr68PJpMJw8PDGB8fh8PhQDKZZIX+VCqFzs5OdmfbbDZEo1G4XC4kEglmd4WoJ2rQ\n+UgqQgjBemalUgmPPPIIrrvuOghxIQN1586dS9LX1WpaN3UjZkgLKLSyODRjCObTVr3z64GYVoCO\nVj/0AJPWts3cTeoxbRVIGZleP+Rz6F1f9fFbYc+Wy/RArBGYWe52NBsb+XMtIK43lheDGTSyFQG0\nADDbQgNFMVDEBNBgTU1Nobe3l91TlE1nsVhYcqBYLKKjowM2mw1+v5/ZKmJYhBAck0IxXnQOWkhc\nLhcURWGXi/pGQC6qUqnECx61leQfSPiTgBeBJWK1qtUq0uk07HY7crkcl7Ah9oBcnsSgkPuTwEip\nVGqIbwLA4BNAAzNB+xB4mZmZwebNm1lRnhTyi8Vig+YYvZeD3QkUySwblT0aGBhgNyVdRwKcuVwO\n586da6iXd+uttyKVSjVcA5mFIvBXLpfhcDhQLBaRSCSQz+cRjUZ5bNU3MQJeclbkYk1mMS0WC3p6\nevDbv/3bhovmbbfdhs997nP46Ec/yu7NxRoBcnLpkgZbV1cXcrkcPB4Pstksstks+vv7OUu2q6sL\nZ86c4RgsYsRCoRBcLhdLkuTzebhcroZak+SGJekNyr4F6tmhBITp9zA0NLTofq5GM3oCNwIheu6R\nVs9ntO18F3Q1mND7r3V8LcZKCzjK59BbKI2AgBGzYdRfPWCqxbi0AgqM7GIyV0ZmxOotF+DTGyut\nhw2t743GuxkTqm7HUlzLZrZigJYcb0JGiy8xE2azGdPT00in01wHMZfLweFw8GJMWVPJZBLt7e0N\nxagpzV8uaEwLu8ViYSFOMmLGiMUisCJEPWCb3FkEdux2e4MAKVB3m5Hadi6X420JTCSTSc4aS6fT\niMfjXJdQBnAAODNPUeqxWMRI0BjRsdPpNLMu2WyW450URcH4+Dg2b96Mq6++GuVyGeFwGIlEgkFL\nKpVCNpvlwHaZqZOLOhO4stvt8Pv96OjogN/vZ5kKGmOv14t4PM7HIcZjYGAAW7duRUdHB1KpVIP7\nFgDrOBUKBZ4TJEfQ09MDIQQXBCf3K13LQCCAkZGRhgQEAokL/RHJN1iTyYSOjg7ccsstrO2mZ1ar\nFf/xH/8x7/MZtYNkF9xuN6rVKrxeL9cC7e3thcvlQl9fX4PLmEop9fX1IZ1Ow+PxIBQKIRKJwGKx\noFwuo7u7GwD44UAIwcHzNP8rlQpSqVSDyC8A/Mu//At+//d/n+PySLduzRrNiNnRu+G3CgwWuhjO\nhyGTtzdqg3oB0wMVRoBIq03NGAv1PloMU7P2t8oC6m1jBNJaAQArBYBRG5YadNBxAf15ot6GzAiE\nyfvIvx29Y6nnxXIyiCsGaMnxUASw6LU8OJlMhl1atCjHYjEO6CZ2Q5ZwkAO0qR4eLVZer5cXL2LE\n5MB44MIFIfclMVqk6dTZ2cnMi91u59IvFNtCGlG0MFqtVni93obYpr6+PmSzWcRiMY65okByk8kE\nj8eDDRs2oFAoNACuWCzGLBwFKlNdwmKxyHFOfr8fW7ZswZYtW1AqlTg+ampqCvF4vIF1I5P1xYi5\nIjbH7Xajvb0dPp8PXq+Xx1+eqKlUCl1dXQiHwwykqtUqgsEgNm7cCK/Xi6GhIcTjcQaGlUqF3VoE\nzMh1SIze5s2bGSDK7k7SLevo6OCafzKrRfNpIUY/QgLUJpMJH/rQh1o6HsU2LcVNS1EUjs8rFoss\n0UGlqIjZFaKuAE/Xnlgn4EJZKapMQMfM5/MNunF2ux2ZTIZd1xRvRg8McjbsM888gz/6oz+CotRd\n8OQCl8f+3W56zBTZfFkrLaZoMQtFK4uO1nnUC6UW2yUfdyGmBbCM2qnerpVjtrKPvG+zsde7nkZj\n0Crztlhr9djq67rUbSBrNi5aTKj8Wms+6AH9Vh5yltpWDNAik7OX1G5DoL5opdNpvoH7fD5mWggM\nKYrCauMkbEpP5ZRF53Q6mTGS5R0sFgunwpOLDMA71OHJXUOfU+YcxT7RfyEEszyzs7PsznO5XA3y\nBrVaDevWrUM4HGYgZbPZuP4fsTYU6C1PGMoUI4aOWC7Z7Vkul5FKpRCJRDA9PY3x8XFmkqh/1G/5\nRkmZnRQT53a7GQhSnBhJUVDwNLkgJycncf311+PYsWMNY0L6Z21tbdi8eTNGRkZYSoCOR0aLPsW+\nySVlKL5ODnQn5iabzTZkTy7WaDxIT2rz5s14z3ve0/THOTU1xdUF9J5s52Mmkwnt7e0wm81cg7JQ\nKMDr9fIxaS5SyaRMJsO/k1Qqxe713t5eKIqC2dlZuFwuxONxZlDJPUjtJkaLfmskHSGDa3ooIBaX\nxHTX7IIZgZlWGCy9Y2m9n6+pF6lWv6PPmgGIZuBSj83S20YPBLQKTtXbzhdgyW1SMyZGfVW/12Nb\nltuWE8jNtx1A6/dFre1bAVtG81dvri3VGK0IoKVGncR+0B9lsQlxoRZguVzmIOqOjg4GSwQ68vk8\nCzVSLBMt8BSwTe4soJG9UWtIEXgjsEBtlIUeFUVhFXViXoilIwBE4qBUAJsCvgk0EAAcHR1FIpFA\nV1dXw3nVNftoESTgQUwaMS/kTk2n05iYmMD4+DhrkZFRLJwMrEgLiZgxj8cDh8MBu93OCuEAGATS\nYk+xU5lMBul0GufOncM999zDbM7g4CCDNQJwAwMDGBkZYVerHI/lcDiYOSHtLhKoJfcWzRshBGcv\nZrNZvpZXXHEFjh49uug5SgwbuZhbDfZ+5ZVXMDY2xiBSfpBYiFksFmZgyZVHQrLkxqW5ViwW4XK5\neK52dXWx+KjP58PMzAwr+dODA7l6Ozs7MTExwW11u90NiRRyWSag/gBw7NgxDA8P8/WW3fBrVrdm\ni6nRIrDUbZiP26RVZkgGHlrgTI9JUJ9fa7FcCrZHDyRp/TfaXwscaS3oaiCgx8wZbX+pwdByMll0\nfL05IH8vvza6ZurXrbbfCCQv1lYE0ALALjT6k+O1ZIFQeponAJNIJDi1vVgscvwJaV1ZrVZ4PB5e\niOV6cDIoIaMFlbanjDkCYBQET3E/lIWXy+W4FAwxMsSOUTyLxWJBOBxGJpNBe3s7B6lv3LgRuVyO\n9Z+GhoYwNjbG2kgU7E+uMAAceEyvqY2VSgXFYpGZq8nJSaTTaXYjyuwPAQdqG0kGEJtG4IqYP3If\nEeAl1i+XyyEajXIAPbn6zpw5gzNnzvD4btmyhbPgiH0sl8twuVzMzFmtVrhcLmYHvV5vQ3YosX4T\nExOYnp6G3W5nQEzjnc1mGQzKIOuDH/wgfvzjH897blJbSYjT7Xbjve99b1PAJITA6dOnEQqFGIAv\nlp6mQHiHw8GsItX4pHEk0GW1WrkotBACs7OzDMotFgvS6TQ6Ozs5hs/r9WJiYgIulwvT09MM3E0m\nE6v0E2ulKAo/zNDcfOONN7Br1y4AF+pSrtk7TYuZ0XrylrdfrLXCSGnto7edFmBUL5ZGLI8es2QE\nXPTaOV/TYzzk92rQY3QMdVu1QFUrfWi20C8V6GoVUOgxhkthrbCORnNCr43N7q/NANty2YoBWsAF\nt6GWq4fATyAQ4EXXarWyZpBcOocy3WgRJoBACwSBNCpZQoHbVLKFFlZyvxCgoTiWdDrN7jcSiFy/\nfj2zBzabDblcjl1+BDyAus5RMBhEuVyG1+vF0aNH2R1Hit4AONOLArqpXQSWCBwBFyZtKpXC6Ogo\nTpw4wXFPBMxkdyixDdR/cgESi0SFnmnRJnaM2ChZ7DKdTiObzSIcDjMoJe2tWq2G0dFR9PT0IJFI\nMGvlcrkaxE+JPSyVSvB4PMjn83ys9vZ2Fj81m83YsWMHTp48yUkH6lJKXV1dGBsba2DqFEVBZ2cn\nvvjFL+Lo0aMYHR2d17wkVpHkJ3p7e1sCWuVyGfF4fMnESqmP1Wq1QRBXjociPTkCWhTnpigKAoEA\nZmZmeG4NDAxgYmICHo8Hk5OTHFNYLBb52sgLEiUyyDe3XC6Hjo4OVCoVLuqtKPXsxA0bNsx7rFez\naS3o9Fr+vxTn0QNrrTI2RnNbj1Gg/bUWM6P2tXLOhYyNeny1FnB1u/UYEDWrptf+VhbvZqymEVhd\nCQzXYkzvAUNrfmp9pz6OEQuoNWZa163Vh4zF2IoCWgSytJ785UEhVx0tCpFIhGOIaIElTSUqoUMs\nGYExKpkiuyRl0U0hBLvdQqEQZmZmkMlk4Ha7YbfbccUVV2Dv3r3MbOVyOUxPT+P8+fMoFArsfqQ+\nkQuuVqshk8kwyxMMBjE1NYWNGzc2lAYKBAI4f/48p+oTgCwWi+w6o8WvWq3irbfewpEjRxomILE6\ntC+p6Pv9fg6apzEgMVcCXxTwTGwaZV4SyKL4nXQ6jWQyyWwjubFIRmJ4eBhCCDz//PMwmUzYvn07\nrr76apw9exalUgmhUAgOhwOxWAyFQgH9/f2sUUZuyFAoxICV5DwIyKkZFirZQz+0nTt34vjx47jl\nlluwadMm/r6zsxORSKSleUlzj4AWMajNLBKJIBaLNcTYLcbkMkuULCEL9dKYU7wbAJbD6OrqQjwe\nZzBrs9lYYmRycpKLe8fj8QaQSpIa9LuUM3yBOuiLRqNwu904e/Ys/9ZKpRKGh4dZKX/N6qYFTGTT\nW0ibLbBGi7PWtkbH0WqX3r5a75uxA1ogU+9+32ob9UCV0THnC3C1mEitc+kxYVrgQO88Wn1aDdYq\n4Je3oddaxzKaj3qArdV2LiXYWjFAS84ypP90s5cDbgkAURkam82GWCwGv98Pj8fDriO5xA491ZML\nRRb/pAWJgqpJGiIcDmNkZIRB1c0339zACBEIS6VSGBsbw5kzZ7gWHDE2xISQkewCnYfcipVKBbFY\nDB6Ph+UMKKA8lUo1MG2UGUjfRaNRnDx58h1CpQSYPB4Pq3V7PB5mzBKJBLNaxH4QOCUQRRlsBGiI\n0aPU/3w+j1QqBSEEent7G+LdhKjH+/h8Phw7dgxOpxP33Xcfrr32Wr7GP/zhD1m/i8aAgJ2iKJzM\nQLFulPFG1xeos0Yk4eD3+1GtVlkRXlEUHD9+HEA9aeJrX/saH18OuDcyrSej97///S39CA8dOoSz\nZ89yP5YiMJxYKnpNDwXkNqTYNXK/FgoF9Pb2Mihet24dTpw4wXGNLpeLZTSoXiTJaHR3dyMajXK/\nKcuWxoIkU4h1DIVCDQ8127dvX3R/V6Np3fi1nurV+2iZFgvTyoK+kIVEi4nSWtiMWAmt9rUKeIzG\nTH3uVhdXPYCqBYC1TAsItMLQydu10iattiwFy9fMlgPkqUGWFmun3p62k/fVAmJazKPRPLhYYHZF\nAC15YNW1DtUDQBl7iUSCNaIAsBuJMqPU9QYBNAS5CyEalM+TySRmZ2cxNjaGUqmEa6+9FnfffTfM\nZnNDHUMKHiYmbXR0FJFIBHa7Hddddx1qtRort5O7TVEUBn5qvS5y0ciFfemPJB/IXVipVJDP55HP\n5xEKhTA1NdUAOgjg2O12jr3x+XxIpVLo6+vj4PLJyUn4fD6OySIw2NbWBr/f3+B+pSxCRVHYHSoD\nHwrAplI+1A5itd544w288MIL+PCHP4y9e/cik8lwxtyWLVtw6NAhluQgsEvgTgjR4MoaHBxkSYdk\nMgkArJ0GANFolMecYqroh/b44483gLOZmZl5zU06ntVqxe233950PyEEjhw5gnA4zGO12CckivUj\nlzhQV/0vlUrIZDLo7+/nz0imob29HQC4AHsul4Pf78fMzAyEEPybyeVy2LlzJ6anp5mxikQiDN5I\nJoX6QECWaieS+520u2q1Gq688spF9Xc1mhYwAuZ3o9dbiI0WqFZNaxHTOqZ6H/VrI7BgBE70zieP\nmRGI03utdVwZkMnbq89j1Hat8dA6trx/qwDMaI4sJdtiZPNlglo5jt7cVV9PPTBF+xrNUyO2S+th\nYan6qWcrAmgB+oyWLO4p1z70+/1IJBIcqzQ+Po4dO3Ygk8mgo6OD3YskvCmLZRYKBWSzWaTTaczO\nziISiSCdTiMQCOCuu+7i+CTZrUjALZ/PIxaLYXp6GolEAslkEhs3bsSOHTu4WHKpVOIacSaTCU6n\nk5kHagO563K5HKxWK5+T2AA6VyKR4MB5cgOFQiGEw2EeE0W5IEvR2dmJ9evXs2J4uVzmkizhcBjp\ndBoOhwNer5eDoKlNQgjWVSIBzGg0yteH2kXlWajcEZ2b3JqU3QnUWZ2NGzcikUhAUZSGAOkXX3wR\nqVSKwTOxeLVajePEnE4ns3X79u3D5OQkt4XGi66T7E5Vx2jJc0yeZ60YzUNqZ29vb0v7JRIJFlRd\nCokJYkCJKSUXodVqhdVq5QeP6elpdgUmEgkAQHt7OwOybDbLzGYkEuGHAnLfUn9pbGm+ykkj1J98\nPs+/ESEE4vE4C/B+7GMfQ39/PyYnJxfd99Vkek/yMpjQWhRafTJvtp0RkCBTA5CFul6M9pkvuJT3\naWVcjJg1I0CmB1BbAUnNtjMCv/MZq+VmYJYLyGkxt1oASv1eD2Sqt1cD4FYZU6Pf3VLYigFawDt1\ns+iGLxvJAphMJk5hJwZjdnYWQggGNalUijPySJCT1NdDoRBn41155ZV43/vex8wIMVBy3FY0GkU+\nn0c4HEYymWStoNtvv52zA6nNlIlFYID6QWybzLSRi1FmFgg4FItFjI6OMlMRCoWQTCaZzSGmgeQq\n3G43BgYG2KUK1ON2AoEAisUiK+UrioKxsTH4fD44HA5etIm5I9cnqdkDYPdjqVRiEEUMHY2x0+lk\n0Uy5jM5NN92EQ4cO8T5ke/fuxY9+9CM4HA6WFKCxILaR2JtKpYKBgQEcPnwYPp8P4XC4AWhR0gAt\n/IqiMNherNExyuUyAoFAS27HeDyOWCyGTCaz6POTtbW1IZ/Po6Ojg8c3nU431MLMZDJcJFpRlIaK\nCyaTCX6/Hz6fD2NjY3w9SUyXMgsp01UuhC2DLUrGoP/EQlutVkxMTCAYDAIAbr75Zvz7v//7kvV/\ntZjWYiJbq661Zu6sZt81279VdqgVmw9Qa7atnmtPD+C0stAaMWNax6J95M9a7eNygyQtW27GplWT\n53SrzJ0W6Je/1zqH3nda42C0vd4+87UVBbSIwpNdbUBjYDf9F0JwFlupVILb7UahUGBJBkVRkEql\nGvSdEokEUqkUMpkM7HY7ent7sW3bNvT19TFQktXfy+UykskkcrkcpqamWIPKZrNh69atGBgYYFBB\nsVt0QQhAEXAktkUO9KfsSdJEomBj4EJ6/Pr16zE6OsoxYeQao/PY7XYEAgFO+aeAd8qqdDqdDS5A\nt9sNj8eD/v5+KEpdrJK0yWq1Grq6uphFJBdfPp9n4EmsihD12DmKHzObzSyjIbuXzGYzZmZmsGXL\nFr5u9P369euRzWZhs9kwOTmJcrmMPXv2sIuWACP11WQyIZlMsiuVgBW5Dwl4EgigObUURiBj+/bt\nHOdlZD/72c+4rJHscluo0RiQYC/FpdF8IbctSWKQej0Fz8/OzsLn82F2dhapVAqpVApmsxnd3d1I\nJBKYmJjg8UsmkzwX3W43IpEIgza1PIgQ9Vg9ylg9efIkrrrqKsRiMXzgAx/A97///SXLulwN1gw0\nqb9XLzLq7dXHpe+aMWN6+2rZQhcaPTai2bGaAcxmoKFm/QAAIABJREFU7MNCAN1iQKUaOMjH0XIx\nXgrQ0yobt9ymBZz0tmtlfzqGFlOmZc2YXq3rtRS24oCWXFiYbuRy9hwZuUwoYJvYIbvdzsHQs7Oz\n7GqLRqMMogKBAK655hp0d3fDbrejUqkgHo+jo6ODta1SqRSXqaFiwO3t7ejr60MgEOBsrHw+j7a2\ntgZAQIsRMWsUe0UxSMVisSFmi0AepehTVqGiKOjo6MDbb7+NVCqFYrHYICja3t4Ov9/P6f0Ub0UM\nlRzgTjIK5FKifgaDQZw9exbFYhEbN25syJQksJdKpVhRn7I1hRAcm0PvZZBKbkabzYbDhw/j05/+\nNADgwIEDuP322xl81mo1TE9PY2RkhDWfKJauWq3yoi+EYHZoZmaGt6EMTxkEUDyVDAoWa8TsvPji\ni3jyySdxww03cBwczV3ZfvnLX+Ltt99mZm6xpij1rErSNKOkDYph8/l8yGQy8Pv9yGQyDOATiQQD\n5vPnz7MOHFCPa6TqBPRbAuqgrb29HdlsFvF4nM8vyzvQmJNAMAG6J598EuFwGK+88grC4TA++tGP\nYseOHejs7MT999+/pNdkNRnd5LUWIq0nbi0QI38nb9+M6dEzPQAxX9MDNEaMkPq/FgNo1HejNjTb\nVr1Nq4u4kUtrpVmrgHc5zmn0IKB1ndXjaPTeaMyNQP9yPWyQrQigpX6akONr5LIfiqI0FGyWQQnF\nhVCGXKVSQSKRwOnTpznuiLLwhoeHMTg4yMCEFg1iUeLxOCYnJ5FMJqEoCjZv3oze3l5mr6rVKguU\nku4UxSpRjAuxanKpEmqbXCZITpcnNwy5cwgc7dixA6+++iqPD7FXVFaFwBGNnaIoDLxkRo0kGihT\nUFHq2Y0UzE5ipwRuCShRvygejuKESKmeABOBHXXZIlLx9/l8DLIAoLe3F4lEAul0mmUxCEjmcrmG\nJAGPx4OJiQlWfydGS5boUCc9FIvFJZ2ntVoN586dw1/+5V8iEAjA5/Ohp6cHW7duxbZt27Br1y4M\nDg5ywsHk5CQvnos1+drKbjug/juIRCIIBoMMmEhktK+vD+Pj4zy3qFKC3W5HMpnkEkXkKk6lUizr\nIbsNqf+0rXyDbGtrQzweh8PhwOjoKAqFAkKhEAqFAh599FE4HA5ceeWVsNvtrNq/Zu80IxeJ1mfN\nXCzNvmu2eCzFQjufxVyL5dMDaEbb6tliFksj1oq+V3+mZXoA7GKwXFrnNppjS9km+UFC7zv1Q4XR\nmKp/J+r/6r5oHUMPqOv9hhYzHisCaAF4x4Kt9QOjWB1yYxBwsdvtcLvdLMtQrVZx9OhRdrUB9Rij\nQCCAnp4e9PT0NIAmmSmLRqOIRCIwmUwYGBhAd3c3PB4PZ9oRK1Wr1TjmiSYILUyk8k5MmRCCRUGp\nbAnJLhATRyKqmUwGxWKRQYKiKPB4PNi0aRPefvttZpJ8Ph9sNltDvA7JS5DbiCYHgRK/39/gYqLg\nbgJPqVSKXXm0oFOsF7FpxODI2ZKy25Ti54ALMWQEhKk/dF0tFgsSiQTi8TgURUEkEmE3FB2TAOzQ\n0BBGRkbgdDpZJoP0yQiMERNKoGI5LJPJIJ/Pc9ZpIpHA2NgYXnjhBVb2d7lcGB8fRzabXbKnWiEu\n6MfRuNvt9oZkD2L3nE4nIpEIenp6cOLECXR3d2N2dpYzXqlqACVq5PN5RKNRWK1WDAwMIBQK8TwB\n3hlYSu0gkEtZo7lcDoqiwO12IxwOw2w2Y2hoCKOjo5iYmFgDWdAPBm4GJGQzYnLUC5rewqH1frkW\nez2A14wtMmqLFkDQOpfeZ1rnWyozYhovNculxxKRLWf71CBKfa1bYQtbBap613y+bV0qW1FAi27e\n5FaTS8tQjEw6nYbP52vIfqPC0cViEVNTU+wyJJBlsVjQ2dmJYDCIdevWcaafXIhX1pDq6OiA0+nk\nzDvahkAWsUqyOjuBI3J10WJM/SEXo9Pp5OB5YhaohE82m20QtyTQIIRAX18fJicn4XA4uO2dnZ2c\nAZnNZuFyubB+/XquTZjP55kN9Pl8DFy8Xi/y+TzXKiRmiwLayQjEEvvh9/s5qcBkMnEAP10DGgc6\nJulzEXunKAqLv7711lv4yEc+gnw+j4GBAczMzDA4ymazcDqdzBbWajX4/X4cOXIEN9xwA2ZnZ6Eo\njRUE6LrQa0psWGojwB2NRmGxWJBMJhtcvQ6HA5lMBqlUaklvWvT7oGxUEm4lYVk5sJ2uYyQSYabK\n4/FgdHSUGWK/38+MFmW2VioVdi9SWR2thU/+PcjtA4Bdu3ZhaGgIkUgEvb29mJ6ehsPhwMTExJKN\nxeVu6qd3PXAxH/AlbyfvOx8wYQREFsoi0XHlxVWPnZCPqcVYaLVTqw1a7+XzL5bZUr/XO78aFBjd\nD5abzWp2vmbsz1KZfA3U16MZuyn/12LI1AzoYu6/Sw04VwTQkhdNIRozDQlkkQtMZrQIOJCSeSqV\n4pR6Ol5bWxsCgQDWrVuHrq4ueL1eVlPP5/NcpJfAg9/v55gWOeuQ4lMsFgtnZgHg42SzWQ6+J9cW\nuRaJBfL5fAwAhKgH8xcKBaRSKYTD4YYgcwJYANiFt2vXLpw9exZOpxNHjhxBLBaDoij4jd/4DVxz\nzTUIBAIol8s4d+4cnnvuOUQiEdx0000YHBzkeCtyEZKcArGEsto+9YdYLafTyUwaBWHTdaI2RqNR\n1rHq6Ohg0cvJyUlce+21fD0DgQAOHjyI9evXA6i7vU6ePMnFjOVi3uQeE0LA7/czy0dzQh4jaitd\nq+UOwCZtLwKzBOrpmizHkyEBeNm1R2xpLpeDyWRidzJpmVmtVkSjUc6SJXc41en0er1c/1BW2Sem\nVc40pN+KkUs2EAggkUhgcHAQQgj81V/9FTO2n/jEJ5Z8TC5Hm88iNh+AowVOFgLWWm3nfI+ltyiq\nTQ94NQNd8nmMjq0FcPVAZSu/YzVAaXWfiw2utKwZSF3O8+nN4VbYQCNGzugaNBt3rf2WgolcEUCL\nTC4eTU/e6klMMVDEwhBYyeVymJ2dRSaTaUjrdzqdLOooB5/TfpSxZrPZWONJrhEHXMieI+aAFiIS\noozH40gkErzA0+LX2dnJ2VikDSVnKJbLZcRiMSSTSQ5SJwAjAzybzcYxToVCAa+88gpuuOEGvP76\n66wILo8RtatYLGJkZASf/vSnsW3bNqxfvx6FQgFOp5NZIxJYJdmGTCbDmZokeDozM8MJB5RpCIDB\nZzgcxtGjR9HW1oa+vj6YzWZEIhG8//3vx759+3Dw4EFun9lsxr333svXhxgvp9OJcDjM2YOlUolB\nsqIo6OrqQrVaxWuvvdZQ41FmV4hZozFYbpNdeXIc03IZMagk79Hb28sSIqQAT9eVskyB+s0jFotx\nAWo5gSAcDvODCo2lnFRArlnqp1H/du3axXUod+7ciT/5kz9BIpFgwPfNb34TDz744LKNz0o3rRu2\n1qKutRipwYbe8dWvWwEWetYKA9QK6NNqk/y/VTNqj9Z3Rm0w2ldrjLWYEr3rqe6r1rGW40FssXYx\ngJ/6AUALOKs/m89YaR1L/nyhfVSzcPM1U/NNLo7JgykzJeptaLEnZom2o+LG8mIgC4ESgCFGgDK4\ngHoxZsp4U8sJUEaWXBuR4lIIzAB1NW5yT/b29iIQCHCavdPpREdHByt7U+kSYhq8Xi86Ojrg8/l4\nMaQgdHIVkivtuuuuw5e//GX88z//8ztAFo0RuSstFgs2b96MJ598Eh//+Mfx4osv8lhRTE8sFuM2\nOBwOdkUNDAzA5XLx8YA6SKIYMgLDiUQCIyMjLBNBgPaP//iP8dhjj+Guu+5iN5ocd0bmcDhYtwsA\na3ERo0i6X263m8EUJRgQs6WeQxfjRqa+gaorGiyl0TWmpAJyVRKDOjIygkwmw6CJBHmpnFOtVmN3\nMdXZpALhQtTlGeT6iCQLAYBBVitj6na7WXri5ptvRrlcxk9/+lNm/4htWzPjuCW97eVrYPTELpve\n8Zo91eu5kVpla/X6otU+oz/1PlqLsBbr1SqQpDao951v3/QWeK191du/m0xvbNTjTu/1GCY90wJW\nrY51MzZrPsdS24oBWupafXKmoaw9RWBLURQWcIxEIpiZmWnIlBJCMDiqVCro6+tDb28vSxQQK2I2\nm9He3s4LFzEE1BbZRUguFGJcyJ1COlakiG6z2TjLj4Q06YLJTJgQdZdYIBDgeDC73Q6z2cwsAMk1\nuFwuOBwOdHR04MyZM1wQWM8ovo360d/fj8ceewwAmEkj7ayBgQF4vV6USiX09vay648y92Qmj1L6\nTSYTotEopqencebMGZRKJUxNTeHuu++G0+nE/fffz3UGA4EAAODXv/51w0SdmZlhsHf+/HkI0Rj7\nRhIWQtQlOcilKNepVAMtig+71DeypTy/zDQRyyuXmOrs7OT4wkgkgrGxMc4wJeaUkjYikQjHkFE5\nJ3pAsVqtnBxB7mLqS7P+WK1W+P1+7Nu3D1dddRVuuOEGVKtVvPTSSxgdHUWtVkOhUMAtt9yyZONy\nOZreQtvKfNFiA1oBVvN96NBib+TvmjFERudsZV+j8+kdW4u5a3YfaOW46u+13FeX+l5zOZoRmNf7\nTAt4q79v5WGkVdM6VqsPGmpbMUCLfhQyuJFBlvxHA06xJel0mgGMzGbZ7XZ4vV4GQdFoFNlsluNU\nCNRQ8DQxW/S/VCohm81yRlu5XEY8Hkc0GuVMNwAs7kgB9O3t7RyPRaVOSK6hVCpxkLHJZILH42HB\nUgJ/sto6ZYpRMLmiKMhkMjh58iSXV9EzYujouNVqFQ888AA8Hg9qtRqSySS6u7u5b5TBKGd3ptNp\nuN1u1tOiGLNisYiZmRkcOXIE2WwWiUQC99xzD1544QU8++yzvH8mk8HRo0chhMDVV1/Nk7RWq+ET\nn/gEvvGNb+DRRx/F1VdfzW2kMaAfDl0f0mqSyxh1dXVxf+U6l5falppRo3lPEg1U75FcgXStgHrc\nWzKZRCKR4AeQI0eOwG63o6Ojg7XlcrkcvF4vs5jFYpFj82huEXPZ7AZTqVTw6quvIh6PIxgMcjKI\nw+FAf38/M807d+5c0nG53M1oXPVcTq0+SCwGCCw38zJf1lkNuORx0/qumetJvYBqLerNmCuj4xsB\nUC2w9m4yLcZSCxxpPVjQ/ur/eg8F8rGMbL6gfL62IoCW2m0IXAh4lm8s9Bm5kEjpneQB6I/cZhSL\nFQgEkE6n8etf/xoHDhxgFxbV/SPGiZTGydVBGXaUmTU7O8vvacGn2oeU9p/NZjExMYF4PM4Aipg2\nSssnQOh2uzkeTHb5yWOhlkqgPh4+fBinTp16B6hQPzFSYL2cIXjvvfeiWCyyuGU2m2W3H7FVFMxv\nsVjgdrvhdruRy+UYBJMoZSQSQTab5RizkZERZsroej311FN4+umnWcrh2WefxR133IEvfOEL+Pa3\nv43PfvazOHjwIMeB0RjLmk1C1AVdKauR3nd3d/MckhMg1KWbjKyVkjorxSqVChwOR8N8pYcDAszk\n0i4UCgzEKNuWXOxDQ0NckJyurcfjaYjJAsBzodmNipIVRkZGsH//fpTLZRw9ehRjY2M4ceIEj/G6\ndeuWfYxWsjVjiNTfGS1CeseU959Pm7RA30Kf4I0WucUsWq2yYPS/mdtHiyXRc1nSfy1wtpAxejeC\nLKD5b8AIUMv7a10TWivmO+e09pHPu9hrtSKAFrE7akZL/l5RLuhskR4PZfzJNQWJBSKdLMqai0aj\nHOBN8UQWi4XVxslFJ9fWk4PdKeCestlIVZu0lMbHx3H69GmcOHGCCznTdjI4E0KwK44Ct2W2Qg6W\nB8DtICPwmEql8Oqrr3JxaSHqgp3nzp3DxMREA6ijcZCFJh9++GG89tprzFCR9hct1iQT4PV6USwW\nOUaKstGIUUun08hkMvj617+OV199FT6fD8PDw9ixYwcLigoh8JnPfAZXX3017rnnHlx//fVwuVx4\n7bXX8L73vQ/33XcfbDYbcrlcQ+wbLfhdXV0olUrYt28f8vk8uxC9Xm9DmSb5BzcfoHW5lIihvhGj\nV61W4fF4OL6PZDioSDSxqdlsFtPT05xsYLfbMTY2hnXr1jGwHhgYaHjSpLGUQZeW0TwNBoPo7u7G\n9u3b4XA4cPjwYWzduhWf/OQncfDgQRw9ehTFYrFBPuTdagtlcvTYlYUCFy2GQL72akZhoabHAukt\nbs3GZz7t0WJEmh2jFdawGaPWrE2ttOPdYEYMoZ5r12jey+vpfMzomi0FIF4RWYcySCIWR1Y0V8dr\nZTIZdHR0MMhSx1URmCG9qUKhgJmZGVQqFc78S6fT8Hg8DC7a29s5SF6IutwDZWeZTKaGenr0l0ql\nGsAXBZGTdAF9TtmRFAhP6t1ak4Lek5uMlNDpOMTkrFu3DhMTEzh48CAGBgYwOjrK2Y/VahXBYBA3\n3ngjhoaGGoCWzWbjsjCf+tSn8P3vf59rNlLs2uzsLIA6qEun01AUhWUdCIglk0mk02k4nU7s3bsX\nTz31FPbv34+enh4uSnzkyBFm9eg6hUIhDA8PQ4h6huDw8DB27drFmW/kBqOxKRaLuOKKK3h8161b\nh/HxcSiKwu2jcZP/LieWaj5GrlRio+gm4HK54PP5MDk5iVqtho6ODo497OrqQjabhdvtxsmTJznm\nj+ZjPp/neawoCv8OieU0Mjq/1WrF8ePH4fV6MTo6iieffBKdnZ3YtWsXarUa7r//fvzO7/wO9u/f\nv+xjtNJtPouAlitFfaxmAELvHqO3kM23jXrtbnYMPbDVSlvk/eTjNOu/FtPRjM3SGif5fEbtb8aG\nLAQUXO6mBUplkK9+aJb3k0GwevwXCrK0zqE1LxYDuFYE0HK73Q31DNXaTjKjQ4HouVyOFwl5cAlQ\n0ELucDiQTqdRKBTeUT+RxEllOQViwshFlc/nuZA0DXY8Hmf2hRghEkOVi0LLDBCV05HjiNSFqKl/\ncjkeck9S6RTKuKNyQY8//jja29vR09PDAdB2ux2nTp1CLpfDnj17MDw8zG44cquZTCZs27YNp06d\nwsaNG/n8FJNFwdA0FtlslmN1SCAWqC+wt956K3bt2sVB/VarFePj4wzEqIYjASdiJl9++WXkcjm4\nXC50dHSgu7ub3ZhyTcXrrruOx3VgYIBrWdIxZSMWhvZdbfS8LGNhs9kQi8XQ0dGBZDLJLJbsYm1v\nb2d9s1OnTvFxXC4Xu7wBMKCy2WzMcs2H6aN4xw0bNiAUCmFychJjY2O4/vrrceTIEezevRvDw8N4\n++23l3ZAVoBdc801OHToUMvbz2cxaOWJvxm40GPCjI65kLbO5xzNFtP5mhpMqRddrWM2A0l6fW/G\nXrUCMNesblpjqeUqNLpWagC2FLaUIAtYIUDLZrNhz549eOONN3ghAS50lhZ4yrKKxWIcc0KLAgEA\n+Wnc7XajWq0inU6jVqs1BFRToWRKOU+lUrDZbMxaEcgh1otclrlcDolEguPAhBBYv349+vv7GUiR\nm5BYOYqTUgf6k9GNhzK/SJWbtMGohEksFmPXmsvlwrp161i7ixiN/fv3o7+/H2NjYzh16hTOnDkD\np9PJYIqELKmu4Ac/+EH813/9F2699VbW2KK2EqAjSQ3qD2WsEXAaGhpCrVZDZ2cnM1dUuqhQKMBq\ntfJ1lceF2Eq6jg8++CAH6JMb1WKx4Morr0QikcCbb77Jav7E6hBTSHODjOpgXi5uwfkaFY2mZA6f\nzweTyYSOjg4AdSBFGZ0nTpzgjNtoNIq2tjZMTExgamoKPp+PQbPMYLXiwpHt7NmzzDgWi0Vs2rQJ\nJ0+e5OuyefNm3H333QgGg3j++effcb0ud5vvTb5VxoesmbtJfTytJ335tXoR0zvucjFbemyE1gI3\nn7HVY/3U26hNb7yaWTMAsNBt3w2mBe61WCktlklrG/m4Cx3PZuzqQm1FAK22tjZs3boVuVwOp0+f\n5tgo4MINX9YponiiYrHIizaxLwRmbDYbPB4PM0LAhRI6JpMJ09PTzGD19/ezrhQxX+fPn0dnZydr\ndZ0/f54zEe12OwYHB1lQk4KI5YWd2kJ/FPtF39FrAhT0n+odjo2N4eWXX8bU1BSDSGLhKObL4/Gg\nra0Nvb29uO2222C1WnHnnXeyOvstt9yCn/70pxgZGUFXVxfrJgHgdP+PfOQjePTRR3HPPfcwCyIz\ndZQ4QIKrQgjMzs4y0KpUKqwfdvToUS4cHAwGsXPnTvzyl7/kskTEHMquYCEE/u7v/g5/8Rd/wXpe\n9B2NUW9vL+LxOPx+PzZu3IhMJoNEIoFiscgq/Fq22hZzAA1yIcQWUvmoSCTCFQbOnTvHrvKbbroJ\nMzMzGBsbQzabRTab5d8BsYOyXAQwv5uLyWRCKBTijNt4PI5QKAQAeOmllwAAp06dwj/90z/hX//1\nX/Fbv/Vb+OEPf7i0A3OJbT4MVTPGhL7TOnYzN4ne038zpmqpF3r5/Hpzqdk26u+bAZfFLL5qNkW9\nf7P91J9pXR89luTdCLIAY2ZQax43A1tax13Kdjabj0a2IoCWyWRCX18fFEXB7OwsYrEYf6e+GLRg\nk3uNFgmZMaLFiBgieVtyK1JB6mKxCEWpC2KaTCZEIhFMTEzAarVy8elEIgGbzYauri6WbaDjuVwu\n1r2SwQGxVLSdHGsmZwpSnAxlOR4/fhwvv/xyg2QFMTgUW+VwOBqKZXd1deHrX/86Hn74YVgsFgZX\ng4ODuPXWW/H8889jZGQEO3fuZMBG/acss9nZWbjdbhQKBfh8Po5Do9ItBDBzuRzC4TADpmq1CpfL\nBavVihtvvJHbK4TAnXfeiV/84hfcbnlcFKUe9/U///M/mJqaQn9/P958803+Tj5fPp9HuVzGzp07\ncejQIR4zrZujbKuRoqcyPAAwMjLCDwukpUWJEEB9rHO5HJ5++mndY8n/F2rkqnS73RwbRyyZbOl0\nGq+99hq+8pWv4Itf/CK2bdu2qPOuFJuP25Cs2U1aD0gZAaZm7g41e7UcTEozgKdun7qdWgBksYyW\nHoO3kGNp9UHvc6O+a71+N5nWvG3GJC73uGnNRXVbF2orAmgR0Onq6sLVV1+Nl19+GZlM5h0XQ14Q\nzp49i56eHgZPcu1DIQSDIT3a2OVycewWgSA654YNG1h9u1Ao4O2338aWLVu4TiBQXzQ6OzvZNUgA\nkNpJLBS9J3BDZU3IVVir1VAsFnH27Fn8/Oc/ZwmJfD7PmVy1Wg3nz5/Hnj17sGfPHjz++OPw+XxI\nJBLIZDI4ePAg9u3bh2PHjiEcDiOdTmNychJmsxm/+tWvYLfbEQqFsHv37gbARgyT1+vF2bNnsXv3\nbgZxpB5PWWKU6UhSF3INPLmIMzGQJpMJH/jAB/Dnf/7nEKIuzLpnzx4Olqf4un/4h3/AI488gmKx\n2MD6UTFkedxyuRzHqBHQm0924WozGqtSqYTp6el3fH+xgCZVECCGeWxsDB6Ph13sVMS6UqngxRdf\nxN13392gf7aarNWbcisMixHbJT+wyKblclFvb+QqXKgZPexoAUG5fVrbq92IrYyrHuCU+90K+JHP\n2QwMzqctrZzz3WJG81RvO6PPlsL0WDQtm28bVgTQIoaJQIXZbMZPf/rTd3wv//jIxQVcyDQklyHF\nYsmK8nIgPAAua0NFjPP5PCYnJxGLxTAwMIC+vj6USiWMjY2hu7sbnZ2dXF6GQAFpYFFclgwGCeRR\nfBJl4gHgLMlarYapqSm89NJLKBQKCIfDcLlcrK7e1taGcDiMVCoFt9uN0dFR2Gw27N27F0ePHsWe\nPXvw0ksvoaOjA3feeSfMZjO+9a1vYXJyEvv27UMqlcLhw4cxODjI6t8UjE9xZFQjb3p6GsPDw+yK\n83g8PN60vdlsRjKZRDQahRAXhCwPHToEj8fDmZsUP0ULLFAPGB4YGGCB2cnJSZw+fRoHDhzA+Pg4\nXnjhBVx33XUMnuh60s0xlUqhWq0iHo9zXB6BsDW7tGYymeD1evGnf/qnmJ2dxYsvvtjgzgeAZDIJ\np9OJSqXCDPFqsvmwJvNZqLXOMR9GRv1a3calYIv02t8K46znlmn1/Fp9MOqXnrtuIeOhtmZjozU/\nloNVvBxtpYyB0Txs5XerZysCaFF8iN1ux8aNG2E2mzE+Po7jx49rutsI3MjfUZC3LHhKmX5yTFSp\nVOJYJXIxFgoFTE1NMaAh9WxyX/X39yOZTLIIal9fH2c9Ut1D4MITEAE+md0iFyUBrFqthvHxcbz4\n4otcFqW3txff/e53ceWVV+Ls2bN49NFHUSqVcPjwYc4qGxkZYVfl66+/jo0bN+LUqVN4/vnn4ff7\n8eCDD2Lbtm145JFHWOfq9OnT2L59O7v65FgscqtSDTxZ54jKppDUBQFSdQ29V155BYFAAJs2bYLV\namWJiVKphL/927/FZz/7WVgsFqRSKSQSCZw/fx6ZTAYejwfnz5/H7OwsTp06he3bt3NsnQxkTSYT\nL85erxexWIzBK8WQrdmls7a2NszMzODP/uzP8LnPfQ633XYbhoeH8dd//dcALhTfvuOOO/DGG29w\nfN9qMrUrbDkWUPU5ZNCl9+Svbofe4tEKyFBvY+Q2a7ZItbqdkRm5n5q5LI2Op7d/s+upBfjkthlt\ns2aXzrSYLD1bKNhqCWgJIUYBpAFUAVQURdkrhOgA8ASAIQCjAH5bUZS4qM+crwK4B0AOwO8oinK4\n2TnMZjMXGO7s7MTWrVsRjUYxMzMD4J0/JCohQ3FSNpsNLper3qk5VyK5BClOC6gLiMq1EqkECQXB\ne71eXsBnZmbQ3d3NteIUReHCy+Qqy2azDU/uFJNFGlgy60av0+k0Dh06hLGxMUxNTaFcLuM3f/M3\ncdNNN2F8fBzZbBZHjhzB9773PS76TEBRUS7USxRCsMvoueeew/3334/+/n643W5cccUVePLJJ/Hc\nc8+hu7sbAwMDDUHjJAhaLpfZxUPnIZZPHnPoo+R5AAAUWUlEQVSr1Yp0Oo10Os0xZbVaDT6fD4VC\nAaFQCG+88QYURWFJjFgshomJCdhsNiQSCWSzWcRiMS4f88ADD2BqagqlUgkPPvggvvCFL+AP/uAP\nmNGia0hB2+SOoiBvSm5Ys0trJL1ht9sRiUTQ19fH9TUpkzWfz+Ptt9/GTTfdBEVRVmU26HwYkWYA\npxl7JN/wm+1rtLjP15Wo5640Yq/0jt+qS87oc7U1G7dWXLZa+7Syr3qbZiB3zVaONXuAUG8zX5sP\no3W7oigR6f1nAfy3oihfEkJ8du79nwG4G8CWub/rAPzL3H9dE0Jw5h4Vau7v78c111yDgwcPIpVK\nMZghgEFuK7leYTqdhsvlQq1Wg8vlQiaTaYglIjBUKBQQCAQYsBDQokLOpDy/YcMG+P1+dqXJ2VlU\n35CCf0lJXX5SI3cixXVls1lEIhH87Gc/g91uRzgchtvtxq233orOzk5Eo1Hkcjl8+ctf5qxK9UWX\nAR0xaj09PZidnUU6ncZDDz2EbDaLc+fOoVQqoaurC8VisaH9hUIBqVSK2aDp6WkMDg6iWq2yfhVw\ngYmgv0KhgLGxsQb1+nw+j1OnTuF973sfPv/5z/NkdDqdCAaDCAQCePjhh/GVr3yFSw6FQiF87GMf\nQ7VaRSQSQW9vL0qlEv7mb/4GP/nJT/DUU0/h4YcfbpgXMzMz2LFjB1wuFwtrEgOXzWbXXIiX0JLJ\nJILBIKampjAzM8Nq9ULUNdC2b9+Op59+Goqi4Mc//jHuuuuui5oRejEeFGWb7w15Pk/TzY6vBRSM\njj/fhUPrOIs5ditARP25HsDU6qee+24hpseeqV/LbKO6rVrtW2O1VoYZ/WaMHiRascW4Dv8XgNvm\nXn8bwP+gDrT+F4B/V+ot+pUQwieECCqK8s5o3Tkj4EQaV4qiwOv1Yt26ddi2bRteeeWVhm3leCuK\nd3K73QyeyNVFIEeOB6lUKizKSa5HSnd3Op3sturt7WVmTJY4MJvNDaAFAAuKyi5JuUZcLpdDLBbD\nmTNncODAAQwODmJ6ehptbW14z3veA7PZjNnZWZhMJjzyyCMcT6U1TiQjQbFoLpeL9cDcbjfeeust\nXHvttahWq4jFYkilUujo6MBtt93GgJTGmLSm8vk8uru7WTiW3H6y+zWfzyMej3OgvhACg4OD2LBh\nA06cOIHTp0/juuuuQ1tbG7q6ulAul5HNZuHz+fC9730Ps7OzrEW2f/9+zgiVhVur1So++clP4vjx\n4zx+VD9yfHwcV199NTZs2IBjx46hXC4zIKTsxDW7NBaPx3lhefnll7F3714MDQ2xW11+0PD7/awT\nd5Ft2R4UZdMCDkZuLK3X8r7N9tP6Ts+lJh97IYu7EaBaCKDRAinq91qMXzNXqPydPA56AMmob1qm\ndnvqAbxWxnwNZF16M7p+S8VutQq0FADPCSEUAP+qKMpjAHoIPCmKMi2E6J7bth/AeWnfibnPGoCW\nEOIhAA8BQCAQYFccuaWoJEx/fz+uuOIKvP3228xKycWWyX3k9XphsVh4YCgWyWq1wu12I5lMstuw\nvb0dxWIR7e3tKBQKiMfjsNvt7F47efIktm/fzgHsFouFA+DJbUl1EskNabfbkc/nuVSNEALZbBbF\nYhFjY2N49dVXMT09jQ0bNiAej6O7uxsPPfQQTp8+zQKiX/va1xriV9QXU1Y7J9X6eDwOq9WK3t5e\nVCoVZDIZHD16lItW9/b2Yv/+/dixYwdrismSCefPn4eiKNi+fXtDDT1yH9I4l8tljI+PI5lMYuvW\nrdixYwdnAPb29mLHjh3o7e3FE088wQH8mUwG1WoVnZ2dKJfLLC5K5WAAMGtHNSqtViv6+/tRqVQa\nah9OTk4CqBcvlgtWU6bnQn3na7Z4+9CHPoQf/OAHEKKusVYul9mlSww0gXZios+cOXOJW710D4qA\ncbxQq+4qI+DVyrlbZUuMwEWr7jh5e/X5W227Ecujfj1ft51WO9TXQwZLrbRNDQbpMyOGS4vpWrOV\nZXqgeynXlVaB1o2KokzNgannhRAnDbbVmknvaOkcWHsMADZt2qQIUa8vWCwWWRWdBCyvuOIKVKtV\nnD59mm/aAJiRIsAQDAY5iJqeoklB2+fzIRKJcBwSxV2FQiFYrVbs3LkTiUQChw8fRigUgtfrhd/v\n58GmWnxy8elisciFch0OB2w2G6anp3lRCYfDOHfuHI4cOYJarQa/349CoYBbbrkF9913H86cOYNg\nMIgvfelLyGaz73jKV4MsAiPE1JnNZgYss7Oz+PnPf47NmzfD5/PBZrMhGAzijjvuwE033YRkMsmK\n+HIpn+9973vcPwK7MlgEwItme3s7fD4f9u3bx0HrVObnmWeewczMDE6ePAm73Y7u7m5cddVV6Orq\nwnPPPQcAmJqagt/vZ9Vyp9PJOlzUN6DOUJGaP2VmEsClAHliMokVk2s4rtnFs66uLgwODiIYDPLc\nj0QiKJVKHK9otVqxbds2Fpk1m814/PHHL2Yzl/VBce49jF63usi2AspaeQLXO44R+GrmdltMu/X2\noXOrz6fFcjWzZqygFvvVzF1p1A4jRkvvnPTZGuBaWdbqb2Kh1hLQUhRlau5/WAjxIwDXAgjRk54Q\nIgggPLf5BIB10u4DAKaMjk8dksvcZDIZZqQouDafz2NiYkLz5pXL5ZBOpxu0mGw2G+s8yTUIqb4e\nqWpv374d8XgcExMTGBsbw9DQEIC66KKiKByMnU6nMTs7yyBh//79nKVXLBaRTCaRTCYRCoWQTqdx\n6tQpRCIR2Gw2zmbcvXs3vv3tb2N0dBTVahW/+7u/y8WxVWPOfaNSNHa7HW63m7MhSYm7ra2Ng82d\nTic2bdqEe++9FwMDAxCiLlpZq9UQjUa5GDS55Q4dOoQPf/jDDRmJpP9F14XaVi6XccMNN/AYl8tl\nTE9Po1AoYHR0FIlEAna7HVu3bmXNsfHxcbjdbi4TRAkKFosFuVwOwWCQ3aHEUpFbkIpRJxIJBpQd\nHR3MNMpyFaTgTy7jNVt+8/l8cDgcOHnyJIaHhxGJRFCpVHDs2DFs2LCBk0KEEBgbG0MwGERvby9y\nuRzefPPNi9nUZX1QnANwC7b5MFlarInRdnpuNj3XlhaQ03MNzpfBUp9Xr23NwE2r7j6jMaDPmx1L\nq4/yvmqGTA9ka/Wz2XnWbPlNng9Aa3F/C7GmQEsI4QJgUhQlPff6NwH8PwB+DOABAF+a+//M3C4/\nBvCHQoj/g3psQ7IZ7T53HqTTaQZaFEdE7BGBn0wmg1Qq1VCShwLUKe6JNKCowHI+n4fFYoHb7UYm\nk+EgeSEENmzYwBlyJ06cAAAMDQ0hlUphYmICyWSSQYwQgrMcfT4fkskkM1yhUAgTExNQFAXZbBbH\njx9HOp3menSbN29Ge3s7vvrVr6JSqcDhcODJJ5/kQG6tGxlwoUg2MUhCCGbaqIi0EAL9/f0M+t54\n4w0cOHAAX//61zEwMIBisYjJyUlEIhEkk0l2aX73u9+FzWZDX19fg8K9EIK1qmixbG9vx44dOzjz\nj4CexWKB3++H1+tFd3c3Tpw4wYApk8lACMHfAfV4NgJeBD4JzLlcLnYlElCrVquYmpqC1WrFyMgI\nlzySSwB5vV4IcUGsdi1e6+LYww8/jB/96Ed47bXXsGPHDvT392NmZga9vb04dOgQ/y5NJhM2bNiA\nrq4unDhxAs8+++xFbedyPyi2YloLsaqNvJ2RGQEhI/akmTtO/q/FNOkdY6Fm5OYzYrJaYfvUx9Fq\nq9710GMBmzGBeufSGlctU4O2NVt+03t4MGKhFwq8WmG0egD8aO6EbQD+X0VR/ksI8RqA7wshHgQw\nDuD/mtv+/0M9Y2cE9ayd322lIYVCAcVikdW/yYQQsNvtsFgsCAaDGB4exuuvv/4OdXO6qedyOfh8\nPpZXqFQqLGxJpWTkYHmr1YqJiQnMzs4ik8nAbDbj5MmTmJ2d5SB5AmmBQADr1q3Dhg0bODsvEokg\nFothamqKC/aePXsWiUQCDocD5XIZe/fuRalUwmc+8xmUy2WEQiE89thjeOaZZzTlCWR3JQXkU6kc\nm83GwMtiscDpdLK4KbltxsfHEQ6H8dhjj+FTn/oUUqkUQqEQCoUCa1xNTEzgpZdewu/93u9xyR1y\n3VL2Jck0UOFnGguKpapUKohGowgEAqjVauzapZqPFNsG1MGf1WqFzWZDOp3m2ooEiulaE8DOZrNQ\nlLqcRiQSweDgIOLxOIvJplIpZhapLeSuIlkNAoqrsebhpbYPfehDaGtrQ39/Pz+ktLW1NZSHogcT\nur6bN29Gd3c3nnjiiYvWzovxoHjNNdfg9ddfp/M1fKcFiPQWbNreCIwZsTNqQGQEwPSOr26r1nfq\nNs/H9FgzvWPqjYceoFHv08zVpzdWWiBTzWSpgaIR09gKkF4DWBfP9OaC3jVV7zdfawq0FEU5C+Aq\njc+jAH5D43MFwB/MpxGKorC7kOq4KYrCYqMAuIjypk2bYLFY8Itf/AIAmPWgm/vMzAxnvSlzbj8S\nGiUGhBZgKrYcjUYRiUS4PlsikYAQ9UzIzs5O7NixAz09PfB4PKzfRExPKBRiBi6dTmN8fJwz6gqF\nAu666y4cO3YM9913H4rFIo4fP46pqSn84z/+I/dVbaR6TiCLAv0pPqlaraKtrQ1+v58Xs1KphGQy\nifHxccTjcWaUXnzxRW4rBSlnMhl8+ctfxnXXXccaR+VyGTabjUVci8UiUqkUgy4CXBaLBclkkksY\nhcNhBINBpFIp2O12BrKKUg9wb2trY5BKAqq5XA5HjhzBVVddxWrh5CYkYETaZ8Ra9vf3I5fLob29\nHcFgECdPnkRXVxcLqtJYqX8IJGy6BraWzlwuF7Zs2cKspM/nQygUYgFbh8OBUqnEGaX02/jmN7+J\nO++8E4FAANFo9GK5eJf9QfHQoUO6i6QeSGjGzNC+zbbVc+FpgQ0tEKHHkM3nXK2a2l2nB0pbYfXU\n7dL7Tn1eNZhq1m8tYNiMvTJqq96cXwNZl9a0gPVSgmJxkW52xo0QIg3g1KVuxxJYAECk6VYr21ZD\nH4DV0Y/V0AdAvx+DiqJc9kUPhRCzALK4/K/Vap9vl5ut9WPlmFYfWr5/rRSg9bqiKHsvdTsWa6uh\nH6uhD8Dq6Mdq6AOwevphZKuhj6uhD8BaP1aarYZ+LLYPpqVszJqt2Zqt2Zqt2Zqt2ZpdsDWgtWZr\ntmZrtmZrtmZrtky2UoDWY5e6AUtkq6Efq6EPwOrox2roA7B6+mFkq6GPq6EPwFo/Vpqthn4sqg8r\nIkZrzdZszdZszdZszdZsNdpKYbTWbM3WbM3WbM3WbM1Wna0BrTVbszVbszVbszVbs2WySw60hBDv\nFUKcEkKMCCE+e6nbY2RCiG8JIcJCiOPSZx1CiOeFEKfn/vvnPhdCiH+c69dRIcTVl67lF0wIsU4I\ncUAIcUII8WshxMNzn182/RBC2IUQrwoh3pzrw1/Nfb5BCPHKXB+eEEJY5z63zb0fmft+6FK2X21C\nCLMQ4g0hxE/m3l9W/RBCjAohjgkhjgghXp/77LKZT4uxtfvXxbXVcP8C1u5hK7Efy3kfu6RASwhh\nBvA1AHcD2AHgfwshdlzKNjWxfwPwXtVnnwXw34qibAHw33PvgXqftsz9PQTgXy5SG5tZBcBnFEXZ\nDuB6AH8wN+aXUz+KAO5QFOUqAMMA3iuEuB7AlwH8w1wf4gAenNv+QQBxRVE2A/iHue1Wkj0M4IT0\n/nLsx+2KogxLWjOX03xakK3dvy6JrYb7F7B2D1up/Vie+xiVJLgUfwD2A/ip9P7PAfz5pWxTC20e\nAnBcen8KQHDudRDAqbnX/wrgf2ttt5L+UK/xdufl2g8ATgCHUa9LFwHQpp5bAH4KYP/c67a57cSl\nbvtcewbmfsB3APgJAHG59QPAKICA6rPLcj7Ns99r969L35/L+v4116a1e9jK6Mey3ccuteuwH8B5\n6f3E3GeXk/Uoc0Vn5/53z32+4vs2R9vuAfAKLrN+zFHVRwCEATwP4AyAhKIoVNRQbif3Ye77JIDO\ni9tiXXsEwP8NoDb3vhOXXz8UAM8JIQ4JIR6a++yymk8LtNXQl8v2Ol3O9y9g7R62AvuxbPexpkWl\nl9m0KjOuFr2JFd03IYQbwJMA/lhRlJTQL5K5IvuhKEoVwLAQwgfgRwC2a202939F9kEI8X4AYUVR\nDgkhbqOPNTZd0f0AcKOiKFNCiG4AzwshThpsu1L7sBBbTX1R24ru2+V+/wLW7mEa311qW7b72KVm\ntCYArJPeDwCYukRtWaiFhBBBAJj7H577fMX2TQhhQf0m9V1FUZ6a+/iy6wcAKIqSAPA/qMdr+IQQ\n9PAgt5P7MPd9O4DYxW2ppt0I4INCiFEA/wd16v0RXGb9UBRlau5/GPUF41pcpvNpnrYa+nLZXafV\ndP8C1u5hWBn9WNb72KUGWq8B2DKXoWAFcB+AH1/iNs3XfgzggbnXD6AeM0Cff2wuO+H/b+/+VRqG\nojiOf++kIi6Cm4P0AZwcHBwcxKFzN0efQgQfwTdwdnB1te4u/qsIWmdnZ4fjkFMQERzKNU35fiA0\nTTLcH6SHk9yEbgMfk1uQbSrNpd8Z8BwRp992dSZHKWUtrwIppSwBezQPYl4DgzzsZ4ZJtgEwjJxY\nb1NEHEXEekRs0Jz7w4g4oEM5SinLpZSVyTqwD4zo0Pk0BevXP5uH+gXWsFyfmRzV69gMPIDWB15o\n5qeP2x7PH2M9B96BT5qO9pBmfvkKeM3P1Ty20LyR9AY8Alttjz/HtUNzi/MBuMul36UcwCZwmxlG\nwElu7wE3wBi4ABZy+2J+H+f+XtsZfsm0C1x2LUeO9T6Xp8lvuEvn05T5rV//m6Hz9SvHZQ2boRy1\n65h/wSNJklRJ21OHkiRJc8tGS5IkqRIbLUmSpEpstCRJkiqx0ZIkSarERkuSJKkSGy1JkqRKvgAS\nyZen8KcJuwAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "compare(image, laplace_numpy(image))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And let's also check that our implementation quantitavely agrees with scikit-image on every interior pixel." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.allclose(laplace_skimage(image)[1:-1, 1:-1], laplace_numpy(image))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Good, we're now all set for the next step. Let's pretend that we think our implementation is slow. How do we objectively measure that? And then: how do we make it faster?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Profiling and timing " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So, we think our NumPy version is slow. How can we put a number on that feeling? The first idea is to time the execution on our test image. We can easily do this with the `%time` line magic." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 3.43 ms, sys: 1.32 ms, total: 4.74 ms\n", "Wall time: 5.08 ms\n" ] }, { "data": { "text/plain": [ "array([[False, True, True, ..., False, False, False],\n", " [False, True, False, ..., False, False, False],\n", " [ True, True, False, ..., False, False, False],\n", " ..., \n", " [False, False, False, ..., True, False, False],\n", " [False, False, False, ..., True, False, False],\n", " [False, False, False, ..., True, True, False]], dtype=bool)" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%time laplace_numpy(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mmmh, around 5 milliseconds per call. If we run this multiple times, the results slightly vary." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Therefore, it is better to use the `%timeit` line magic, which averages the timing operation and gives us a more accurate measurement." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.37 ms ± 150 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit laplace_numpy(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How does the scikit-image implementation compare to that?" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.88 ms ± 106 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit laplace_skimage(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Approximately the same, albeit a little slower. \n", "\n", "So, our function is too slow for say, our realtime application. To make it go faster, we first need to have an idea about what takes time in it.\n", "Our function works in two steps: first we compute the laplacian and then we threshold the results. Which part of the function is taking the most time? \n", "\n", "To answer that question, we use a profiler. Many different profilers exit. We'll look at three below: %prun, %lprun and pprofile." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using %prun gives us a high level view of what's happening inside our call." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " 4 function calls in 0.004 seconds\n", "\n", " Ordered by: internal time\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", " 1 0.004 0.004 0.004 0.004 :1(laplace_numpy)\n", " 1 0.000 0.000 0.004 0.004 :1()\n", " 1 0.000 0.000 0.004 0.004 {built-in method builtins.exec}\n", " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}\n", "\n", "\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "r = %prun -r laplace_numpy(image)\n", "r.print_stats()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is not very informative. But we understand that most of the time (column tottime) is spent inside our laplace_numpy function." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What about %lprun?" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "%load_ext line_profiler" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Timer unit: 1e-06 s\n", "\n", "Total time: 0.007151 s\n", "File: \n", "Function: laplace_numpy at line 1\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", " 1 def laplace_numpy(image):\n", " 2 \"\"\"Applies Laplace operator to 2D image using our own NumPy implementation. \n", " 3 Then tresholds the result and returns boolean image.\"\"\"\n", " 4 1 6403.0 6403.0 89.5 laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " 5 1 745.0 745.0 10.4 thresh = np.abs(laplacian) > 0.05\n", " 6 1 3.0 3.0 0.0 return thresh\n", "\n" ] } ], "source": [ "r = %lprun -r -f laplace_numpy laplace_numpy(image)\n", "r.print_stats()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Running `%lprun -r -f laplace_numpy laplace_numpy(image)` means that we aske `%lprun` to show how long each line took to execute inside the function `laplace_numpy` and return the result as an object.\n", "\n", "Here, we can answer the earlier question: computing the laplacian is what takes the most time in this function." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see if [`pprofile`](https://github.com/vpelletier/pprofile) confirms that measurement." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "import pprofile\n", "def func_to_profile():\n", " prof = pprofile.Profile()\n", " with prof():\n", " laplace_numpy(image)\n", " prof.print_stats()" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Total duration: 0.00508428s\n", "File: \n", "File duration: 0.00480628s (94.53%)\n", "Line #| Hits| Time| Time per hit| %|Source code\n", "------+----------+-------------+-------------+-------+-----------\n", " 1| 1| 1.90735e-05| 1.90735e-05| 0.38%|def laplace_numpy(image):\n", " 2| 0| 0| 0| 0.00%| \"\"\"Applies Laplace operator to 2D image using our own NumPy implementation.\n", " 3| 0| 0| 0| 0.00%| Then tresholds the result and returns boolean image.\"\"\"\n", " 4| 1| 0.00392222| 0.00392222| 77.14%| laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " 5| 1| 0.000836849| 0.000836849| 16.46%| thresh = np.abs(laplacian) > 0.05\n", "(call)| 1| 0.00480628| 0.00480628| 94.53%|# :1 laplace_numpy\n", " 6| 1| 2.81334e-05| 2.81334e-05| 0.55%| return thresh\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/Users/kappamaki/anaconda/lib/python3.6/site-packages/pprofile.py:102: UserWarning: Cannot access \".buffer\", invalid entities from source files will cause errors when annotating.\n", " 'files will cause errors when annotating.' % (stream, )\n" ] } ], "source": [ "func_to_profile()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "pprofile confirms the previous assessment: it's the laplacian computation that takes time. \n", "\n", "What's more, pprofile is a little bit simpler to use than line_profiler. However, it doesn't feature a cell magic (although there's already someone asking for this [here](https://github.com/vpelletier/pprofile/issues/21))." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At this point, we know that to make our function faster, the first thing to optimize is the computation of the laplacian. Let's try that using Cython." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Cython " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What Cython does, like the other tools we'll see below, is to compile our Python code into C code that will hopefully be very fast. \n", "Since Cython has a so-called IPython magic function, we'll be able to continue working in the notebook. \n", "If we use the `-a` option with the Cython magic, we can obtain an annotated version of our source code that shows where Cython uses C code and where it uses Python objects." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "%load_ext cython" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_862e7a2cc089394207c84948a1866a79.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.27.3

\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: import numpy as np
\n", "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 2: 
\n", "
+3: def laplace_cython(image):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_862e7a2cc089394207c84948a1866a79_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image); /*proto*/\n",
       "static char __pyx_doc_46_cython_magic_862e7a2cc089394207c84948a1866a79_laplace_cython[] = \"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\\n    Cython implementation.\";\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_862e7a2cc089394207c84948a1866a79_1laplace_cython = {\"laplace_cython\", (PyCFunction)__pyx_pw_46_cython_magic_862e7a2cc089394207c84948a1866a79_1laplace_cython, METH_O, __pyx_doc_46_cython_magic_862e7a2cc089394207c84948a1866a79_laplace_cython};\n",
       "static PyObject *__pyx_pw_46_cython_magic_862e7a2cc089394207c84948a1866a79_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_cython (wrapper)\", 0);\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_862e7a2cc089394207c84948a1866a79_laplace_cython(__pyx_self, ((PyObject *)__pyx_v_image));\n",
       "\n",
       "  /* function exit code */\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_862e7a2cc089394207c84948a1866a79_laplace_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_image) {\n",
       "  PyObject *__pyx_v_laplacian = NULL;\n",
       "  PyObject *__pyx_v_thresh = NULL;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_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_XDECREF(__pyx_t_3);\n",
       "  __Pyx_XDECREF(__pyx_t_4);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_862e7a2cc089394207c84948a1866a79.laplace_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XDECREF(__pyx_v_laplacian);\n",
       "  __Pyx_XDECREF(__pyx_v_thresh);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__16 = PyTuple_Pack(3, __pyx_n_s_image, __pyx_n_s_laplacian, __pyx_n_s_thresh); if (unlikely(!__pyx_tuple__16)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__16);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__16);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_862e7a2cc089394207c84948a1866a79_1laplace_cython, NULL, __pyx_n_s_cython_magic_862e7a2cc089394207); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_laplace_cython, __pyx_t_1) < 0) __PYX_ERR(0, 3, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 4:     """Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.
\n", "
 5:     Cython implementation."""
\n", "
+6:     laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]
\n", "
  __pyx_slice_ = PySlice_New(Py_None, __pyx_int_neg_2, Py_None); if (unlikely(!__pyx_slice_)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice_);\n",
       "  __Pyx_GIVEREF(__pyx_slice_);\n",
       "  __pyx_slice__2 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__2)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__2);\n",
       "  __Pyx_GIVEREF(__pyx_slice__2);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyObject_GetItem(__pyx_v_image, __pyx_tuple__3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_tuple__3 = PyTuple_Pack(2, __pyx_slice_, __pyx_slice__2); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__3);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__3);\n",
       "  __pyx_slice__4 = PySlice_New(__pyx_int_2, Py_None, Py_None); if (unlikely(!__pyx_slice__4)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__4);\n",
       "  __Pyx_GIVEREF(__pyx_slice__4);\n",
       "  __pyx_slice__5 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__5)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__5);\n",
       "  __Pyx_GIVEREF(__pyx_slice__5);\n",
       "  __pyx_t_2 = PyObject_GetItem(__pyx_v_image, __pyx_tuple__6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_3 = PyNumber_Add(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_tuple__6 = PyTuple_Pack(2, __pyx_slice__4, __pyx_slice__5); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__6);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__6);\n",
       "  __pyx_slice__7 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__7)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__7);\n",
       "  __Pyx_GIVEREF(__pyx_slice__7);\n",
       "  __pyx_slice__8 = PySlice_New(Py_None, __pyx_int_neg_2, Py_None); if (unlikely(!__pyx_slice__8)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__8);\n",
       "  __Pyx_GIVEREF(__pyx_slice__8);\n",
       "  __pyx_t_2 = PyObject_GetItem(__pyx_v_image, __pyx_tuple__9); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_1 = PyNumber_Add(__pyx_t_3, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_tuple__9 = PyTuple_Pack(2, __pyx_slice__7, __pyx_slice__8); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__9);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__9);\n",
       "  __pyx_slice__10 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__10)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__10);\n",
       "  __Pyx_GIVEREF(__pyx_slice__10);\n",
       "  __pyx_slice__11 = PySlice_New(__pyx_int_2, Py_None, Py_None); if (unlikely(!__pyx_slice__11)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__11);\n",
       "  __Pyx_GIVEREF(__pyx_slice__11);\n",
       "  __pyx_t_2 = PyObject_GetItem(__pyx_v_image, __pyx_tuple__12); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_3 = PyNumber_Add(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_tuple__12 = PyTuple_Pack(2, __pyx_slice__10, __pyx_slice__11); if (unlikely(!__pyx_tuple__12)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__12);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__12);\n",
       "  __pyx_slice__13 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__13)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__13);\n",
       "  __Pyx_GIVEREF(__pyx_slice__13);\n",
       "  __pyx_slice__14 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__14)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__14);\n",
       "  __Pyx_GIVEREF(__pyx_slice__14);\n",
       "  __pyx_t_2 = PyObject_GetItem(__pyx_v_image, __pyx_tuple__15); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_1 = PyNumber_Multiply(__pyx_int_4, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_t_2 = PyNumber_Subtract(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_v_laplacian = __pyx_t_2;\n",
       "  __pyx_t_2 = 0;\n",
       "  __pyx_tuple__15 = PyTuple_Pack(2, __pyx_slice__13, __pyx_slice__14); if (unlikely(!__pyx_tuple__15)) __PYX_ERR(0, 6, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__15);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__15);\n",
       "
+7:     thresh = np.abs(laplacian) > 0.05
\n", "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_abs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {\n",
       "    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);\n",
       "    if (likely(__pyx_t_1)) {\n",
       "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);\n",
       "      __Pyx_INCREF(__pyx_t_1);\n",
       "      __Pyx_INCREF(function);\n",
       "      __Pyx_DECREF_SET(__pyx_t_3, function);\n",
       "    }\n",
       "  }\n",
       "  if (!__pyx_t_1) {\n",
       "    __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_laplacian); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "  } else {\n",
       "    #if CYTHON_FAST_PYCALL\n",
       "    if (PyFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_1, __pyx_v_laplacian};\n",
       "      __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "    } else\n",
       "    #endif\n",
       "    #if CYTHON_FAST_PYCCALL\n",
       "    if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_1, __pyx_v_laplacian};\n",
       "      __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "    } else\n",
       "    #endif\n",
       "    {\n",
       "      __pyx_t_4 = PyTuple_New(1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_4);\n",
       "      __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); __pyx_t_1 = NULL;\n",
       "      __Pyx_INCREF(__pyx_v_laplacian);\n",
       "      __Pyx_GIVEREF(__pyx_v_laplacian);\n",
       "      PyTuple_SET_ITEM(__pyx_t_4, 0+1, __pyx_v_laplacian);\n",
       "      __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    }\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __pyx_t_3 = PyObject_RichCompare(__pyx_t_2, __pyx_float_0_05, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_v_thresh = __pyx_t_3;\n",
       "  __pyx_t_3 = 0;\n",
       "
+8:     return thresh
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __Pyx_INCREF(__pyx_v_thresh);\n",
       "  __pyx_r = __pyx_v_thresh;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "import numpy as np\n", " \n", "def laplace_cython(image):\n", " \"\"\"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\n", " Cython implementation.\"\"\"\n", " laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What the above code shows is that Cython couldn't optimize our function much, as indicated by the yellow hue of the lines above. The yellow intensity in each line shows the amount of interaction with Python objects that it found. The more you have to use Python objects, the less speedup you are likely to achieve. \n", "\n", "Let's time this first compiled version." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.84 ms ± 215 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit laplace_cython(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It performs roughly at the same speed that our NumPy version. So there's no much use in switching to Cython. Can we do better? The key is to eliminate interaction with Python through different ways. A first one is to declare our input image is an array." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "In file included from /Users/kappamaki/.ipython/cython/_cython_magic_53222c7a36e00268207d0fde8ad0c365.c:546:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/arrayobject.h:4:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/ndarrayobject.h:18:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:\n", "/Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: \"Using deprecated NumPy API, disable it by \" \"#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-W#warnings]\n", "#warning \"Using deprecated NumPy API, disable it by \" \\\n", " ^\n", "1 warning generated.\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_53222c7a36e00268207d0fde8ad0c365.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.27.3

\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: import numpy as np
\n", "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "/* … */\n",
       "  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 2: cimport numpy as cnp
\n", "
 3: 
\n", "
+4: def laplace_cython(cnp.ndarray image):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image); /*proto*/\n",
       "static char __pyx_doc_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_laplace_cython[] = \"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\\n    Cython implementation.\";\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_1laplace_cython = {\"laplace_cython\", (PyCFunction)__pyx_pw_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_1laplace_cython, METH_O, __pyx_doc_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_laplace_cython};\n",
       "static PyObject *__pyx_pw_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_cython (wrapper)\", 0);\n",
       "  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_image), __pyx_ptype_5numpy_ndarray, 1, \"image\", 0))) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_laplace_cython(__pyx_self, ((PyArrayObject *)__pyx_v_image));\n",
       "\n",
       "  /* function exit code */\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_laplace_cython(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_image) {\n",
       "  PyObject *__pyx_v_laplacian = NULL;\n",
       "  PyObject *__pyx_v_thresh = NULL;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_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_XDECREF(__pyx_t_3);\n",
       "  __Pyx_XDECREF(__pyx_t_4);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_53222c7a36e00268207d0fde8ad0c365.laplace_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XDECREF(__pyx_v_laplacian);\n",
       "  __Pyx_XDECREF(__pyx_v_thresh);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__25 = PyTuple_Pack(3, __pyx_n_s_image, __pyx_n_s_laplacian, __pyx_n_s_thresh); if (unlikely(!__pyx_tuple__25)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__25);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__25);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_53222c7a36e00268207d0fde8ad0c365_1laplace_cython, NULL, __pyx_n_s_cython_magic_53222c7a36e0026820); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_laplace_cython, __pyx_t_1) < 0) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 5:     """Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.
\n", "
 6:     Cython implementation."""
\n", "
+7:     laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]
\n", "
  __pyx_slice_ = PySlice_New(Py_None, __pyx_int_neg_2, Py_None); if (unlikely(!__pyx_slice_)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice_);\n",
       "  __Pyx_GIVEREF(__pyx_slice_);\n",
       "  __pyx_slice__2 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__2);\n",
       "  __Pyx_GIVEREF(__pyx_slice__2);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_tuple__3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_tuple__3 = PyTuple_Pack(2, __pyx_slice_, __pyx_slice__2); if (unlikely(!__pyx_tuple__3)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__3);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__3);\n",
       "  __pyx_slice__4 = PySlice_New(__pyx_int_2, Py_None, Py_None); if (unlikely(!__pyx_slice__4)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__4);\n",
       "  __Pyx_GIVEREF(__pyx_slice__4);\n",
       "  __pyx_slice__5 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__5)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__5);\n",
       "  __Pyx_GIVEREF(__pyx_slice__5);\n",
       "  __pyx_t_2 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_tuple__6); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_3 = PyNumber_Add(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_tuple__6 = PyTuple_Pack(2, __pyx_slice__4, __pyx_slice__5); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__6);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__6);\n",
       "  __pyx_slice__7 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__7)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__7);\n",
       "  __Pyx_GIVEREF(__pyx_slice__7);\n",
       "  __pyx_slice__8 = PySlice_New(Py_None, __pyx_int_neg_2, Py_None); if (unlikely(!__pyx_slice__8)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__8);\n",
       "  __Pyx_GIVEREF(__pyx_slice__8);\n",
       "  __pyx_t_2 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_tuple__9); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_1 = PyNumber_Add(__pyx_t_3, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_tuple__9 = PyTuple_Pack(2, __pyx_slice__7, __pyx_slice__8); if (unlikely(!__pyx_tuple__9)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__9);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__9);\n",
       "  __pyx_slice__10 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__10)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__10);\n",
       "  __Pyx_GIVEREF(__pyx_slice__10);\n",
       "  __pyx_slice__11 = PySlice_New(__pyx_int_2, Py_None, Py_None); if (unlikely(!__pyx_slice__11)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__11);\n",
       "  __Pyx_GIVEREF(__pyx_slice__11);\n",
       "  __pyx_t_2 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_tuple__12); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_3 = PyNumber_Add(__pyx_t_1, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_tuple__12 = PyTuple_Pack(2, __pyx_slice__10, __pyx_slice__11); if (unlikely(!__pyx_tuple__12)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__12);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__12);\n",
       "  __pyx_slice__13 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__13)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__13);\n",
       "  __Pyx_GIVEREF(__pyx_slice__13);\n",
       "  __pyx_slice__14 = PySlice_New(__pyx_int_1, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_slice__14)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_slice__14);\n",
       "  __Pyx_GIVEREF(__pyx_slice__14);\n",
       "  __pyx_t_2 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_tuple__15); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_1 = PyNumber_Multiply(__pyx_int_4, __pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_t_2 = PyNumber_Subtract(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_v_laplacian = __pyx_t_2;\n",
       "  __pyx_t_2 = 0;\n",
       "  __pyx_tuple__15 = PyTuple_Pack(2, __pyx_slice__13, __pyx_slice__14); if (unlikely(!__pyx_tuple__15)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__15);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__15);\n",
       "
+8:     thresh = np.abs(laplacian) > 0.05
\n", "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_abs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {\n",
       "    __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);\n",
       "    if (likely(__pyx_t_1)) {\n",
       "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);\n",
       "      __Pyx_INCREF(__pyx_t_1);\n",
       "      __Pyx_INCREF(function);\n",
       "      __Pyx_DECREF_SET(__pyx_t_3, function);\n",
       "    }\n",
       "  }\n",
       "  if (!__pyx_t_1) {\n",
       "    __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_v_laplacian); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "  } else {\n",
       "    #if CYTHON_FAST_PYCALL\n",
       "    if (PyFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_1, __pyx_v_laplacian};\n",
       "      __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "    } else\n",
       "    #endif\n",
       "    #if CYTHON_FAST_PYCCALL\n",
       "    if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_1, __pyx_v_laplacian};\n",
       "      __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "    } else\n",
       "    #endif\n",
       "    {\n",
       "      __pyx_t_4 = PyTuple_New(1+1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_4);\n",
       "      __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1); __pyx_t_1 = NULL;\n",
       "      __Pyx_INCREF(__pyx_v_laplacian);\n",
       "      __Pyx_GIVEREF(__pyx_v_laplacian);\n",
       "      PyTuple_SET_ITEM(__pyx_t_4, 0+1, __pyx_v_laplacian);\n",
       "      __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_4, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "    }\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __pyx_t_3 = PyObject_RichCompare(__pyx_t_2, __pyx_float_0_05, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 8, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_v_thresh = __pyx_t_3;\n",
       "  __pyx_t_3 = 0;\n",
       "
+9:     return thresh
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __Pyx_INCREF(__pyx_v_thresh);\n",
       "  __pyx_r = __pyx_v_thresh;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "import numpy as np\n", "cimport numpy as cnp\n", "\n", "def laplace_cython(cnp.ndarray image):\n", " \"\"\"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\n", " Cython implementation.\"\"\"\n", " laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.98 ms ± 62 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit laplace_cython(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The timing didn't improve. It turns, if you click on the yellow lines, that Cython is not able to optimize the broadcasting operation (and its fancy bracketing) that we usually perform with NumPy. To allow Cython to optimize, let's write an explicit loop over the pixels in the image." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "In file included from /Users/kappamaki/.ipython/cython/_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0.c:547:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/arrayobject.h:4:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/ndarrayobject.h:18:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:\n", "/Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: \"Using deprecated NumPy API, disable it by \" \"#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-W#warnings]\n", "#warning \"Using deprecated NumPy API, disable it by \" \\\n", " ^\n", "1 warning generated.\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.27.3

\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: import numpy as np
\n", "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "/* … */\n",
       "  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 02: cimport numpy as cnp
\n", "
 03: 
\n", "
+04: def laplace_cython(cnp.ndarray image):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image); /*proto*/\n",
       "static char __pyx_doc_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_laplace_cython[] = \"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\\n    Cython implementation.\";\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_1laplace_cython = {\"laplace_cython\", (PyCFunction)__pyx_pw_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_1laplace_cython, METH_O, __pyx_doc_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_laplace_cython};\n",
       "static PyObject *__pyx_pw_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_cython (wrapper)\", 0);\n",
       "  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_image), __pyx_ptype_5numpy_ndarray, 1, \"image\", 0))) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_laplace_cython(__pyx_self, ((PyArrayObject *)__pyx_v_image));\n",
       "\n",
       "  /* function exit code */\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_laplace_cython(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_image) {\n",
       "  int __pyx_v_h;\n",
       "  int __pyx_v_w;\n",
       "  PyObject *__pyx_v_laplacian = NULL;\n",
       "  int __pyx_v_i;\n",
       "  int __pyx_v_j;\n",
       "  PyObject *__pyx_v_thresh = NULL;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_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_XDECREF(__pyx_t_3);\n",
       "  __Pyx_XDECREF(__pyx_t_4);\n",
       "  __Pyx_XDECREF(__pyx_t_5);\n",
       "  __Pyx_AddTraceback(\"_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0.laplace_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_XDECREF(__pyx_v_laplacian);\n",
       "  __Pyx_XDECREF(__pyx_v_thresh);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__10 = PyTuple_Pack(7, __pyx_n_s_image, __pyx_n_s_h, __pyx_n_s_w, __pyx_n_s_laplacian, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_thresh); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__10);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__10);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_6d19cbef7cff92c3c6b985a9b7119dc0_1laplace_cython, NULL, __pyx_n_s_cython_magic_6d19cbef7cff92c3c6); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_laplace_cython, __pyx_t_1) < 0) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 05:     """Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.
\n", "
 06:     Cython implementation."""
\n", "
+07:     cdef int h = image.shape[0]
\n", "
  __pyx_v_h = (__pyx_v_image->dimensions[0]);\n",
       "
+08:     cdef int w = image.shape[1]
\n", "
  __pyx_v_w = (__pyx_v_image->dimensions[1]);\n",
       "
+09:     laplacian = np.empty((w-2, h-2))
\n", "
  __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s_empty); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_t_2 = __Pyx_PyInt_From_long((__pyx_v_w - 2)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __pyx_t_4 = __Pyx_PyInt_From_long((__pyx_v_h - 2)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __Pyx_GIVEREF(__pyx_t_2);\n",
       "  PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2);\n",
       "  __Pyx_GIVEREF(__pyx_t_4);\n",
       "  PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_4);\n",
       "  __pyx_t_2 = 0;\n",
       "  __pyx_t_4 = 0;\n",
       "  __pyx_t_4 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {\n",
       "    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);\n",
       "    if (likely(__pyx_t_4)) {\n",
       "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);\n",
       "      __Pyx_INCREF(__pyx_t_4);\n",
       "      __Pyx_INCREF(function);\n",
       "      __Pyx_DECREF_SET(__pyx_t_3, function);\n",
       "    }\n",
       "  }\n",
       "  if (!__pyx_t_4) {\n",
       "    __pyx_t_1 = __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    __Pyx_GOTREF(__pyx_t_1);\n",
       "  } else {\n",
       "    #if CYTHON_FAST_PYCALL\n",
       "    if (PyFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_5};\n",
       "      __pyx_t_1 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    } else\n",
       "    #endif\n",
       "    #if CYTHON_FAST_PYCCALL\n",
       "    if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_4, __pyx_t_5};\n",
       "      __pyx_t_1 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "    } else\n",
       "    #endif\n",
       "    {\n",
       "      __pyx_t_2 = PyTuple_New(1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4); __pyx_t_4 = NULL;\n",
       "      __Pyx_GIVEREF(__pyx_t_5);\n",
       "      PyTuple_SET_ITEM(__pyx_t_2, 0+1, __pyx_t_5);\n",
       "      __pyx_t_5 = 0;\n",
       "      __pyx_t_1 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_2, NULL); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    }\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __pyx_v_laplacian = __pyx_t_1;\n",
       "  __pyx_t_1 = 0;\n",
       "
 10:     cdef int i, j
\n", "
+11:     for i in range(1, h-1):
\n", "
  __pyx_t_6 = (__pyx_v_h - 1);\n",
       "  for (__pyx_t_7 = 1; __pyx_t_7 < __pyx_t_6; __pyx_t_7+=1) {\n",
       "    __pyx_v_i = __pyx_t_7;\n",
       "
+12:         for j in range(1, w-1):
\n", "
    __pyx_t_8 = (__pyx_v_w - 1);\n",
       "    for (__pyx_t_9 = 1; __pyx_t_9 < __pyx_t_8; __pyx_t_9+=1) {\n",
       "      __pyx_v_j = __pyx_t_9;\n",
       "
+13:             laplacian[i-1, j-1] = image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]
\n", "
      __pyx_t_1 = __Pyx_PyInt_From_long((__pyx_v_i - 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_j); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_GIVEREF(__pyx_t_1);\n",
       "      PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);\n",
       "      __Pyx_GIVEREF(__pyx_t_3);\n",
       "      PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3);\n",
       "      __pyx_t_1 = 0;\n",
       "      __pyx_t_3 = 0;\n",
       "      __pyx_t_3 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "      __pyx_t_2 = __Pyx_PyInt_From_long((__pyx_v_i + 1)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_j); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "      __Pyx_GIVEREF(__pyx_t_2);\n",
       "      PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_2);\n",
       "      __Pyx_GIVEREF(__pyx_t_1);\n",
       "      PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1);\n",
       "      __pyx_t_2 = 0;\n",
       "      __pyx_t_1 = 0;\n",
       "      __pyx_t_1 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "      __pyx_t_5 = PyNumber_Add(__pyx_t_3, __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "      __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __pyx_t_3 = __Pyx_PyInt_From_long((__pyx_v_j - 1)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __pyx_t_2 = PyTuple_New(2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_GIVEREF(__pyx_t_1);\n",
       "      PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);\n",
       "      __Pyx_GIVEREF(__pyx_t_3);\n",
       "      PyTuple_SET_ITEM(__pyx_t_2, 1, __pyx_t_3);\n",
       "      __pyx_t_1 = 0;\n",
       "      __pyx_t_3 = 0;\n",
       "      __pyx_t_3 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "      __pyx_t_2 = PyNumber_Add(__pyx_t_5, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "      __pyx_t_3 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __pyx_t_5 = __Pyx_PyInt_From_long((__pyx_v_j + 1)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "      __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __Pyx_GIVEREF(__pyx_t_3);\n",
       "      PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_3);\n",
       "      __Pyx_GIVEREF(__pyx_t_5);\n",
       "      PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_5);\n",
       "      __pyx_t_3 = 0;\n",
       "      __pyx_t_5 = 0;\n",
       "      __pyx_t_5 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_t_1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "      __pyx_t_1 = PyNumber_Add(__pyx_t_2, __pyx_t_5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "      __pyx_t_5 = __Pyx_PyInt_From_int(__pyx_v_i); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "      __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_j); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __Pyx_GIVEREF(__pyx_t_5);\n",
       "      PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5);\n",
       "      __Pyx_GIVEREF(__pyx_t_2);\n",
       "      PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_2);\n",
       "      __pyx_t_5 = 0;\n",
       "      __pyx_t_2 = 0;\n",
       "      __pyx_t_2 = PyObject_GetItem(((PyObject *)__pyx_v_image), __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "      __pyx_t_3 = PyNumber_Multiply(__pyx_int_4, __pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "      __pyx_t_2 = PyNumber_Subtract(__pyx_t_1, __pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "      __pyx_t_3 = __Pyx_PyInt_From_long((__pyx_v_i - 1)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __pyx_t_1 = __Pyx_PyInt_From_long((__pyx_v_j - 1)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_1);\n",
       "      __pyx_t_5 = PyTuple_New(2); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "      __Pyx_GIVEREF(__pyx_t_3);\n",
       "      PyTuple_SET_ITEM(__pyx_t_5, 0, __pyx_t_3);\n",
       "      __Pyx_GIVEREF(__pyx_t_1);\n",
       "      PyTuple_SET_ITEM(__pyx_t_5, 1, __pyx_t_1);\n",
       "      __pyx_t_3 = 0;\n",
       "      __pyx_t_1 = 0;\n",
       "      if (unlikely(PyObject_SetItem(__pyx_v_laplacian, __pyx_t_5, __pyx_t_2) < 0)) __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    }\n",
       "  }\n",
       "
+14:     thresh = np.abs(laplacian) > 0.05
\n", "
  __pyx_t_5 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_5, __pyx_n_s_abs); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_t_5 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_1))) {\n",
       "    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_1);\n",
       "    if (likely(__pyx_t_5)) {\n",
       "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_1);\n",
       "      __Pyx_INCREF(__pyx_t_5);\n",
       "      __Pyx_INCREF(function);\n",
       "      __Pyx_DECREF_SET(__pyx_t_1, function);\n",
       "    }\n",
       "  }\n",
       "  if (!__pyx_t_5) {\n",
       "    __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_t_1, __pyx_v_laplacian); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_2);\n",
       "  } else {\n",
       "    #if CYTHON_FAST_PYCALL\n",
       "    if (PyFunction_Check(__pyx_t_1)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_v_laplacian};\n",
       "      __pyx_t_2 = __Pyx_PyFunction_FastCall(__pyx_t_1, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "    } else\n",
       "    #endif\n",
       "    #if CYTHON_FAST_PYCCALL\n",
       "    if (__Pyx_PyFastCFunction_Check(__pyx_t_1)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_5, __pyx_v_laplacian};\n",
       "      __pyx_t_2 = __Pyx_PyCFunction_FastCall(__pyx_t_1, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "    } else\n",
       "    #endif\n",
       "    {\n",
       "      __pyx_t_3 = PyTuple_New(1+1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_3);\n",
       "      __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_5); __pyx_t_5 = NULL;\n",
       "      __Pyx_INCREF(__pyx_v_laplacian);\n",
       "      __Pyx_GIVEREF(__pyx_v_laplacian);\n",
       "      PyTuple_SET_ITEM(__pyx_t_3, 0+1, __pyx_v_laplacian);\n",
       "      __pyx_t_2 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_3, NULL); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "    }\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = PyObject_RichCompare(__pyx_t_2, __pyx_float_0_05, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __pyx_v_thresh = __pyx_t_1;\n",
       "  __pyx_t_1 = 0;\n",
       "
+15:     return thresh
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __Pyx_INCREF(__pyx_v_thresh);\n",
       "  __pyx_r = __pyx_v_thresh;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "import numpy as np\n", "cimport numpy as cnp\n", "\n", "def laplace_cython(cnp.ndarray image):\n", " \"\"\"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\n", " Cython implementation.\"\"\"\n", " cdef int h = image.shape[0]\n", " cdef int w = image.shape[1]\n", " laplacian = np.empty((w-2, h-2))\n", " cdef int i, j\n", " for i in range(1, h-1):\n", " for j in range(1, w-1):\n", " laplacian[i-1, j-1] = image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "335 ms ± 4.54 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "%timeit laplace_cython(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Woops! The function we just wrote is 100x times slower than our NumPy implementation! The reason can be traced to the core of our function: the sum of the five pixel bound terms should be free from any Python object conversions. However, that line is all yellow and if you click it, you'll see it's full of Python object conversions. \n", "\n", "How do we solve this problem? The answer is: we need to pass the array as a buffer that can be accessed at C speeds. Let's see:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "In file included from /Users/kappamaki/.ipython/cython/_cython_magic_bd5177082c943517a15103961a130b2a.c:548:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/arrayobject.h:4:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/ndarrayobject.h:18:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:\n", "/Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: \"Using deprecated NumPy API, disable it by \" \"#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-W#warnings]\n", "#warning \"Using deprecated NumPy API, disable it by \" \\\n", " ^\n", "1 warning generated.\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_bd5177082c943517a15103961a130b2a.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.27.3

\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: import numpy as np
\n", "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "/* … */\n",
       "  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 02: cimport numpy as cnp
\n", "
 03: 
\n", "
+04: def laplace_cython(cnp.ndarray[double, ndim=2] image):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_bd5177082c943517a15103961a130b2a_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image); /*proto*/\n",
       "static char __pyx_doc_46_cython_magic_bd5177082c943517a15103961a130b2a_laplace_cython[] = \"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\\n    Cython implementation.\";\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_bd5177082c943517a15103961a130b2a_1laplace_cython = {\"laplace_cython\", (PyCFunction)__pyx_pw_46_cython_magic_bd5177082c943517a15103961a130b2a_1laplace_cython, METH_O, __pyx_doc_46_cython_magic_bd5177082c943517a15103961a130b2a_laplace_cython};\n",
       "static PyObject *__pyx_pw_46_cython_magic_bd5177082c943517a15103961a130b2a_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_cython (wrapper)\", 0);\n",
       "  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_image), __pyx_ptype_5numpy_ndarray, 1, \"image\", 0))) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_bd5177082c943517a15103961a130b2a_laplace_cython(__pyx_self, ((PyArrayObject *)__pyx_v_image));\n",
       "\n",
       "  /* function exit code */\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_bd5177082c943517a15103961a130b2a_laplace_cython(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_image) {\n",
       "  int __pyx_v_h;\n",
       "  int __pyx_v_w;\n",
       "  PyArrayObject *__pyx_v_laplacian = 0;\n",
       "  int __pyx_v_i;\n",
       "  int __pyx_v_j;\n",
       "  PyObject *__pyx_v_thresh = NULL;\n",
       "  __Pyx_LocalBuf_ND __pyx_pybuffernd_image;\n",
       "  __Pyx_Buffer __pyx_pybuffer_image;\n",
       "  __Pyx_LocalBuf_ND __pyx_pybuffernd_laplacian;\n",
       "  __Pyx_Buffer __pyx_pybuffer_laplacian;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_cython\", 0);\n",
       "  __pyx_pybuffer_laplacian.pybuffer.buf = NULL;\n",
       "  __pyx_pybuffer_laplacian.refcount = 0;\n",
       "  __pyx_pybuffernd_laplacian.data = NULL;\n",
       "  __pyx_pybuffernd_laplacian.rcbuffer = &__pyx_pybuffer_laplacian;\n",
       "  __pyx_pybuffer_image.pybuffer.buf = NULL;\n",
       "  __pyx_pybuffer_image.refcount = 0;\n",
       "  __pyx_pybuffernd_image.data = NULL;\n",
       "  __pyx_pybuffernd_image.rcbuffer = &__pyx_pybuffer_image;\n",
       "  {\n",
       "    __Pyx_BufFmt_StackElem __pyx_stack[1];\n",
       "    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_image.rcbuffer->pybuffer, (PyObject*)__pyx_v_image, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  }\n",
       "  __pyx_pybuffernd_image.diminfo[0].strides = __pyx_pybuffernd_image.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_image.diminfo[0].shape = __pyx_pybuffernd_image.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_image.diminfo[1].strides = __pyx_pybuffernd_image.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_image.diminfo[1].shape = __pyx_pybuffernd_image.rcbuffer->pybuffer.shape[1];\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_5);\n",
       "  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;\n",
       "    __Pyx_PyThreadState_declare\n",
       "    __Pyx_PyThreadState_assign\n",
       "    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);\n",
       "    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_image.rcbuffer->pybuffer);\n",
       "    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_laplacian.rcbuffer->pybuffer);\n",
       "  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}\n",
       "  __Pyx_AddTraceback(\"_cython_magic_bd5177082c943517a15103961a130b2a.laplace_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  goto __pyx_L2;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_image.rcbuffer->pybuffer);\n",
       "  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_laplacian.rcbuffer->pybuffer);\n",
       "  __pyx_L2:;\n",
       "  __Pyx_XDECREF((PyObject *)__pyx_v_laplacian);\n",
       "  __Pyx_XDECREF(__pyx_v_thresh);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__10 = PyTuple_Pack(7, __pyx_n_s_image, __pyx_n_s_h, __pyx_n_s_w, __pyx_n_s_laplacian, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_thresh); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__10);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__10);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_bd5177082c943517a15103961a130b2a_1laplace_cython, NULL, __pyx_n_s_cython_magic_bd5177082c943517a1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_laplace_cython, __pyx_t_1) < 0) __PYX_ERR(0, 4, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 05:     """Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.
\n", "
 06:     Cython implementation."""
\n", "
+07:     cdef int h = image.shape[0]
\n", "
  __pyx_v_h = (__pyx_v_image->dimensions[0]);\n",
       "
+08:     cdef int w = image.shape[1]
\n", "
  __pyx_v_w = (__pyx_v_image->dimensions[1]);\n",
       "
+09:     cdef cnp.ndarray[double, ndim=2] laplacian = np.empty((w-2, h-2), dtype=np.double)
\n", "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __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_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = __Pyx_PyInt_From_long((__pyx_v_w - 2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_3 = __Pyx_PyInt_From_long((__pyx_v_h - 2)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __Pyx_GIVEREF(__pyx_t_1);\n",
       "  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);\n",
       "  __Pyx_GIVEREF(__pyx_t_3);\n",
       "  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_3);\n",
       "  __pyx_t_1 = 0;\n",
       "  __pyx_t_3 = 0;\n",
       "  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_GIVEREF(__pyx_t_4);\n",
       "  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4);\n",
       "  __pyx_t_4 = 0;\n",
       "  __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_double); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_dtype, __pyx_t_5) < 0) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);\n",
       "  {\n",
       "    __Pyx_BufFmt_StackElem __pyx_stack[1];\n",
       "    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_laplacian.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {\n",
       "      __pyx_v_laplacian = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.buf = NULL;\n",
       "      __PYX_ERR(0, 9, __pyx_L1_error)\n",
       "    } else {__pyx_pybuffernd_laplacian.diminfo[0].strides = __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_laplacian.diminfo[0].shape = __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_laplacian.diminfo[1].strides = __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_laplacian.diminfo[1].shape = __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.shape[1];\n",
       "    }\n",
       "  }\n",
       "  __pyx_t_6 = 0;\n",
       "  __pyx_v_laplacian = ((PyArrayObject *)__pyx_t_5);\n",
       "  __pyx_t_5 = 0;\n",
       "
 10:     cdef int i, j
\n", "
+11:     for i in range(1, h-1):
\n", "
  __pyx_t_7 = (__pyx_v_h - 1);\n",
       "  for (__pyx_t_8 = 1; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {\n",
       "    __pyx_v_i = __pyx_t_8;\n",
       "
+12:         for j in range(1, w-1):
\n", "
    __pyx_t_9 = (__pyx_v_w - 1);\n",
       "    for (__pyx_t_10 = 1; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {\n",
       "      __pyx_v_j = __pyx_t_10;\n",
       "
+13:             laplacian[i-1, j-1] = image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]
\n", "
      __pyx_t_11 = (__pyx_v_i - 1);\n",
       "      __pyx_t_12 = __pyx_v_j;\n",
       "      __pyx_t_13 = -1;\n",
       "      if (__pyx_t_11 < 0) {\n",
       "        __pyx_t_11 += __pyx_pybuffernd_image.diminfo[0].shape;\n",
       "        if (unlikely(__pyx_t_11 < 0)) __pyx_t_13 = 0;\n",
       "      } else if (unlikely(__pyx_t_11 >= __pyx_pybuffernd_image.diminfo[0].shape)) __pyx_t_13 = 0;\n",
       "      if (__pyx_t_12 < 0) {\n",
       "        __pyx_t_12 += __pyx_pybuffernd_image.diminfo[1].shape;\n",
       "        if (unlikely(__pyx_t_12 < 0)) __pyx_t_13 = 1;\n",
       "      } else if (unlikely(__pyx_t_12 >= __pyx_pybuffernd_image.diminfo[1].shape)) __pyx_t_13 = 1;\n",
       "      if (unlikely(__pyx_t_13 != -1)) {\n",
       "        __Pyx_RaiseBufferIndexError(__pyx_t_13);\n",
       "        __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      }\n",
       "      __pyx_t_14 = (__pyx_v_i + 1);\n",
       "      __pyx_t_15 = __pyx_v_j;\n",
       "      __pyx_t_13 = -1;\n",
       "      if (__pyx_t_14 < 0) {\n",
       "        __pyx_t_14 += __pyx_pybuffernd_image.diminfo[0].shape;\n",
       "        if (unlikely(__pyx_t_14 < 0)) __pyx_t_13 = 0;\n",
       "      } else if (unlikely(__pyx_t_14 >= __pyx_pybuffernd_image.diminfo[0].shape)) __pyx_t_13 = 0;\n",
       "      if (__pyx_t_15 < 0) {\n",
       "        __pyx_t_15 += __pyx_pybuffernd_image.diminfo[1].shape;\n",
       "        if (unlikely(__pyx_t_15 < 0)) __pyx_t_13 = 1;\n",
       "      } else if (unlikely(__pyx_t_15 >= __pyx_pybuffernd_image.diminfo[1].shape)) __pyx_t_13 = 1;\n",
       "      if (unlikely(__pyx_t_13 != -1)) {\n",
       "        __Pyx_RaiseBufferIndexError(__pyx_t_13);\n",
       "        __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      }\n",
       "      __pyx_t_16 = __pyx_v_i;\n",
       "      __pyx_t_17 = (__pyx_v_j - 1);\n",
       "      __pyx_t_13 = -1;\n",
       "      if (__pyx_t_16 < 0) {\n",
       "        __pyx_t_16 += __pyx_pybuffernd_image.diminfo[0].shape;\n",
       "        if (unlikely(__pyx_t_16 < 0)) __pyx_t_13 = 0;\n",
       "      } else if (unlikely(__pyx_t_16 >= __pyx_pybuffernd_image.diminfo[0].shape)) __pyx_t_13 = 0;\n",
       "      if (__pyx_t_17 < 0) {\n",
       "        __pyx_t_17 += __pyx_pybuffernd_image.diminfo[1].shape;\n",
       "        if (unlikely(__pyx_t_17 < 0)) __pyx_t_13 = 1;\n",
       "      } else if (unlikely(__pyx_t_17 >= __pyx_pybuffernd_image.diminfo[1].shape)) __pyx_t_13 = 1;\n",
       "      if (unlikely(__pyx_t_13 != -1)) {\n",
       "        __Pyx_RaiseBufferIndexError(__pyx_t_13);\n",
       "        __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      }\n",
       "      __pyx_t_18 = __pyx_v_i;\n",
       "      __pyx_t_19 = (__pyx_v_j + 1);\n",
       "      __pyx_t_13 = -1;\n",
       "      if (__pyx_t_18 < 0) {\n",
       "        __pyx_t_18 += __pyx_pybuffernd_image.diminfo[0].shape;\n",
       "        if (unlikely(__pyx_t_18 < 0)) __pyx_t_13 = 0;\n",
       "      } else if (unlikely(__pyx_t_18 >= __pyx_pybuffernd_image.diminfo[0].shape)) __pyx_t_13 = 0;\n",
       "      if (__pyx_t_19 < 0) {\n",
       "        __pyx_t_19 += __pyx_pybuffernd_image.diminfo[1].shape;\n",
       "        if (unlikely(__pyx_t_19 < 0)) __pyx_t_13 = 1;\n",
       "      } else if (unlikely(__pyx_t_19 >= __pyx_pybuffernd_image.diminfo[1].shape)) __pyx_t_13 = 1;\n",
       "      if (unlikely(__pyx_t_13 != -1)) {\n",
       "        __Pyx_RaiseBufferIndexError(__pyx_t_13);\n",
       "        __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      }\n",
       "      __pyx_t_20 = __pyx_v_i;\n",
       "      __pyx_t_21 = __pyx_v_j;\n",
       "      __pyx_t_13 = -1;\n",
       "      if (__pyx_t_20 < 0) {\n",
       "        __pyx_t_20 += __pyx_pybuffernd_image.diminfo[0].shape;\n",
       "        if (unlikely(__pyx_t_20 < 0)) __pyx_t_13 = 0;\n",
       "      } else if (unlikely(__pyx_t_20 >= __pyx_pybuffernd_image.diminfo[0].shape)) __pyx_t_13 = 0;\n",
       "      if (__pyx_t_21 < 0) {\n",
       "        __pyx_t_21 += __pyx_pybuffernd_image.diminfo[1].shape;\n",
       "        if (unlikely(__pyx_t_21 < 0)) __pyx_t_13 = 1;\n",
       "      } else if (unlikely(__pyx_t_21 >= __pyx_pybuffernd_image.diminfo[1].shape)) __pyx_t_13 = 1;\n",
       "      if (unlikely(__pyx_t_13 != -1)) {\n",
       "        __Pyx_RaiseBufferIndexError(__pyx_t_13);\n",
       "        __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      }\n",
       "      __pyx_t_22 = (__pyx_v_i - 1);\n",
       "      __pyx_t_23 = (__pyx_v_j - 1);\n",
       "      __pyx_t_13 = -1;\n",
       "      if (__pyx_t_22 < 0) {\n",
       "        __pyx_t_22 += __pyx_pybuffernd_laplacian.diminfo[0].shape;\n",
       "        if (unlikely(__pyx_t_22 < 0)) __pyx_t_13 = 0;\n",
       "      } else if (unlikely(__pyx_t_22 >= __pyx_pybuffernd_laplacian.diminfo[0].shape)) __pyx_t_13 = 0;\n",
       "      if (__pyx_t_23 < 0) {\n",
       "        __pyx_t_23 += __pyx_pybuffernd_laplacian.diminfo[1].shape;\n",
       "        if (unlikely(__pyx_t_23 < 0)) __pyx_t_13 = 1;\n",
       "      } else if (unlikely(__pyx_t_23 >= __pyx_pybuffernd_laplacian.diminfo[1].shape)) __pyx_t_13 = 1;\n",
       "      if (unlikely(__pyx_t_13 != -1)) {\n",
       "        __Pyx_RaiseBufferIndexError(__pyx_t_13);\n",
       "        __PYX_ERR(0, 13, __pyx_L1_error)\n",
       "      }\n",
       "      *__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.buf, __pyx_t_22, __pyx_pybuffernd_laplacian.diminfo[0].strides, __pyx_t_23, __pyx_pybuffernd_laplacian.diminfo[1].strides) = (((((*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_12, __pyx_pybuffernd_image.diminfo[1].strides)) + (*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_image.diminfo[1].strides))) + (*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_16, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_17, __pyx_pybuffernd_image.diminfo[1].strides))) + (*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_18, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_19, __pyx_pybuffernd_image.diminfo[1].strides))) - (4.0 * (*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_20, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_21, __pyx_pybuffernd_image.diminfo[1].strides))));\n",
       "    }\n",
       "  }\n",
       "
+14:     thresh = np.abs(laplacian) > 0.05
\n", "
  __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_abs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  __pyx_t_4 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {\n",
       "    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);\n",
       "    if (likely(__pyx_t_4)) {\n",
       "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);\n",
       "      __Pyx_INCREF(__pyx_t_4);\n",
       "      __Pyx_INCREF(function);\n",
       "      __Pyx_DECREF_SET(__pyx_t_3, function);\n",
       "    }\n",
       "  }\n",
       "  if (!__pyx_t_4) {\n",
       "    __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_laplacian)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_5);\n",
       "  } else {\n",
       "    #if CYTHON_FAST_PYCALL\n",
       "    if (PyFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_laplacian)};\n",
       "      __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "    } else\n",
       "    #endif\n",
       "    #if CYTHON_FAST_PYCCALL\n",
       "    if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_laplacian)};\n",
       "      __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "    } else\n",
       "    #endif\n",
       "    {\n",
       "      __pyx_t_2 = PyTuple_New(1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4); __pyx_t_4 = NULL;\n",
       "      __Pyx_INCREF(((PyObject *)__pyx_v_laplacian));\n",
       "      __Pyx_GIVEREF(((PyObject *)__pyx_v_laplacian));\n",
       "      PyTuple_SET_ITEM(__pyx_t_2, 0+1, ((PyObject *)__pyx_v_laplacian));\n",
       "      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_2, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    }\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_float_0_05, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 14, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_v_thresh = __pyx_t_3;\n",
       "  __pyx_t_3 = 0;\n",
       "
+15:     return thresh
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __Pyx_INCREF(__pyx_v_thresh);\n",
       "  __pyx_r = __pyx_v_thresh;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "import numpy as np\n", "cimport numpy as cnp\n", "\n", "def laplace_cython(cnp.ndarray[double, ndim=2] image):\n", " \"\"\"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\n", " Cython implementation.\"\"\"\n", " cdef int h = image.shape[0]\n", " cdef int w = image.shape[1]\n", " cdef cnp.ndarray[double, ndim=2] laplacian = np.empty((w-2, h-2), dtype=np.double)\n", " cdef int i, j\n", " for i in range(1, h-1):\n", " for j in range(1, w-1):\n", " laplacian[i-1, j-1] = image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.37 ms ± 68.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit laplace_cython(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally! We have made our function faster by a factor of 2." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But can we go further? Yes, by observing that on the summation line, Cython still performs some bounds checks." ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "In file included from /Users/kappamaki/.ipython/cython/_cython_magic_416c56f791dd3ffab3f99fad86fc10b5.c:549:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/arrayobject.h:4:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/ndarrayobject.h:18:\n", "In file included from /Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:\n", "/Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: \"Using deprecated NumPy API, disable it by \" \"#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION\" [-W#warnings]\n", "#warning \"Using deprecated NumPy API, disable it by \" \\\n", " ^\n", "1 warning generated.\n" ] }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", " \n", " Cython: _cython_magic_416c56f791dd3ffab3f99fad86fc10b5.pyx\n", " \n", " \n", "\n", "\n", "

Generated by Cython 0.27.3

\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: import numpy as np
\n", "
  __pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "/* … */\n",
       "  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 02: cimport numpy as cnp
\n", "
 03: import cython
\n", "
 04: 
\n", "
 05: @cython.boundscheck(False) # turn off bounds-checking for entire function
\n", "
 06: @cython.wraparound(False)  # turn off negative index wrapping for entire function
\n", "
+07: def laplace_cython(cnp.ndarray[double, ndim=2] image):
\n", "
/* Python wrapper */\n",
       "static PyObject *__pyx_pw_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image); /*proto*/\n",
       "static char __pyx_doc_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_laplace_cython[] = \"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\\n    Cython implementation.\";\n",
       "static PyMethodDef __pyx_mdef_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_1laplace_cython = {\"laplace_cython\", (PyCFunction)__pyx_pw_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_1laplace_cython, METH_O, __pyx_doc_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_laplace_cython};\n",
       "static PyObject *__pyx_pw_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_1laplace_cython(PyObject *__pyx_self, PyObject *__pyx_v_image) {\n",
       "  PyObject *__pyx_r = 0;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_cython (wrapper)\", 0);\n",
       "  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_image), __pyx_ptype_5numpy_ndarray, 1, \"image\", 0))) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __pyx_r = __pyx_pf_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_laplace_cython(__pyx_self, ((PyArrayObject *)__pyx_v_image));\n",
       "\n",
       "  /* function exit code */\n",
       "  goto __pyx_L0;\n",
       "  __pyx_L1_error:;\n",
       "  __pyx_r = NULL;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "\n",
       "static PyObject *__pyx_pf_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_laplace_cython(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_image) {\n",
       "  int __pyx_v_h;\n",
       "  int __pyx_v_w;\n",
       "  PyArrayObject *__pyx_v_laplacian = 0;\n",
       "  int __pyx_v_i;\n",
       "  int __pyx_v_j;\n",
       "  PyObject *__pyx_v_thresh = NULL;\n",
       "  __Pyx_LocalBuf_ND __pyx_pybuffernd_image;\n",
       "  __Pyx_Buffer __pyx_pybuffer_image;\n",
       "  __Pyx_LocalBuf_ND __pyx_pybuffernd_laplacian;\n",
       "  __Pyx_Buffer __pyx_pybuffer_laplacian;\n",
       "  PyObject *__pyx_r = NULL;\n",
       "  __Pyx_RefNannyDeclarations\n",
       "  __Pyx_RefNannySetupContext(\"laplace_cython\", 0);\n",
       "  __pyx_pybuffer_laplacian.pybuffer.buf = NULL;\n",
       "  __pyx_pybuffer_laplacian.refcount = 0;\n",
       "  __pyx_pybuffernd_laplacian.data = NULL;\n",
       "  __pyx_pybuffernd_laplacian.rcbuffer = &__pyx_pybuffer_laplacian;\n",
       "  __pyx_pybuffer_image.pybuffer.buf = NULL;\n",
       "  __pyx_pybuffer_image.refcount = 0;\n",
       "  __pyx_pybuffernd_image.data = NULL;\n",
       "  __pyx_pybuffernd_image.rcbuffer = &__pyx_pybuffer_image;\n",
       "  {\n",
       "    __Pyx_BufFmt_StackElem __pyx_stack[1];\n",
       "    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_image.rcbuffer->pybuffer, (PyObject*)__pyx_v_image, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  }\n",
       "  __pyx_pybuffernd_image.diminfo[0].strides = __pyx_pybuffernd_image.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_image.diminfo[0].shape = __pyx_pybuffernd_image.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_image.diminfo[1].strides = __pyx_pybuffernd_image.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_image.diminfo[1].shape = __pyx_pybuffernd_image.rcbuffer->pybuffer.shape[1];\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_5);\n",
       "  { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;\n",
       "    __Pyx_PyThreadState_declare\n",
       "    __Pyx_PyThreadState_assign\n",
       "    __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);\n",
       "    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_image.rcbuffer->pybuffer);\n",
       "    __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_laplacian.rcbuffer->pybuffer);\n",
       "  __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);}\n",
       "  __Pyx_AddTraceback(\"_cython_magic_416c56f791dd3ffab3f99fad86fc10b5.laplace_cython\", __pyx_clineno, __pyx_lineno, __pyx_filename);\n",
       "  __pyx_r = NULL;\n",
       "  goto __pyx_L2;\n",
       "  __pyx_L0:;\n",
       "  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_image.rcbuffer->pybuffer);\n",
       "  __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_laplacian.rcbuffer->pybuffer);\n",
       "  __pyx_L2:;\n",
       "  __Pyx_XDECREF((PyObject *)__pyx_v_laplacian);\n",
       "  __Pyx_XDECREF(__pyx_v_thresh);\n",
       "  __Pyx_XGIVEREF(__pyx_r);\n",
       "  __Pyx_RefNannyFinishContext();\n",
       "  return __pyx_r;\n",
       "}\n",
       "/* … */\n",
       "  __pyx_tuple__10 = PyTuple_Pack(7, __pyx_n_s_image, __pyx_n_s_h, __pyx_n_s_w, __pyx_n_s_laplacian, __pyx_n_s_i, __pyx_n_s_j, __pyx_n_s_thresh); if (unlikely(!__pyx_tuple__10)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_tuple__10);\n",
       "  __Pyx_GIVEREF(__pyx_tuple__10);\n",
       "/* … */\n",
       "  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_46_cython_magic_416c56f791dd3ffab3f99fad86fc10b5_1laplace_cython, NULL, __pyx_n_s_cython_magic_416c56f791dd3ffab3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  if (PyDict_SetItem(__pyx_d, __pyx_n_s_laplace_cython, __pyx_t_1) < 0) __PYX_ERR(0, 7, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "
 08:     """Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.
\n", "
 09:     Cython implementation."""
\n", "
+10:     cdef int h = image.shape[0]
\n", "
  __pyx_v_h = (__pyx_v_image->dimensions[0]);\n",
       "
+11:     cdef int w = image.shape[1]
\n", "
  __pyx_v_w = (__pyx_v_image->dimensions[1]);\n",
       "
+12:     cdef cnp.ndarray[double, ndim=2] laplacian = np.empty((w-2, h-2), dtype=np.double)
\n", "
  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 12, __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_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_2);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  __pyx_t_1 = __Pyx_PyInt_From_long((__pyx_v_w - 2)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_3 = __Pyx_PyInt_From_long((__pyx_v_h - 2)); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __Pyx_GIVEREF(__pyx_t_1);\n",
       "  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_t_1);\n",
       "  __Pyx_GIVEREF(__pyx_t_3);\n",
       "  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_t_3);\n",
       "  __pyx_t_1 = 0;\n",
       "  __pyx_t_3 = 0;\n",
       "  __pyx_t_3 = PyTuple_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_GIVEREF(__pyx_t_4);\n",
       "  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_4);\n",
       "  __pyx_t_4 = 0;\n",
       "  __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __pyx_t_1 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_1);\n",
       "  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_double); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;\n",
       "  if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_dtype, __pyx_t_5) < 0) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_t_3, __pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_5);\n",
       "  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  if (!(likely(((__pyx_t_5) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_5, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "  __pyx_t_6 = ((PyArrayObject *)__pyx_t_5);\n",
       "  {\n",
       "    __Pyx_BufFmt_StackElem __pyx_stack[1];\n",
       "    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_laplacian.rcbuffer->pybuffer, (PyObject*)__pyx_t_6, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 2, 0, __pyx_stack) == -1)) {\n",
       "      __pyx_v_laplacian = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.buf = NULL;\n",
       "      __PYX_ERR(0, 12, __pyx_L1_error)\n",
       "    } else {__pyx_pybuffernd_laplacian.diminfo[0].strides = __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_laplacian.diminfo[0].shape = __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_laplacian.diminfo[1].strides = __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_laplacian.diminfo[1].shape = __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.shape[1];\n",
       "    }\n",
       "  }\n",
       "  __pyx_t_6 = 0;\n",
       "  __pyx_v_laplacian = ((PyArrayObject *)__pyx_t_5);\n",
       "  __pyx_t_5 = 0;\n",
       "
 13:     cdef int i, j
\n", "
+14:     for i in range(1, h-1):
\n", "
  __pyx_t_7 = (__pyx_v_h - 1);\n",
       "  for (__pyx_t_8 = 1; __pyx_t_8 < __pyx_t_7; __pyx_t_8+=1) {\n",
       "    __pyx_v_i = __pyx_t_8;\n",
       "
+15:         for j in range(1, w-1):
\n", "
    __pyx_t_9 = (__pyx_v_w - 1);\n",
       "    for (__pyx_t_10 = 1; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {\n",
       "      __pyx_v_j = __pyx_t_10;\n",
       "
+16:             laplacian[i-1, j-1] = image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]
\n", "
      __pyx_t_11 = (__pyx_v_i - 1);\n",
       "      __pyx_t_12 = __pyx_v_j;\n",
       "      __pyx_t_13 = (__pyx_v_i + 1);\n",
       "      __pyx_t_14 = __pyx_v_j;\n",
       "      __pyx_t_15 = __pyx_v_i;\n",
       "      __pyx_t_16 = (__pyx_v_j - 1);\n",
       "      __pyx_t_17 = __pyx_v_i;\n",
       "      __pyx_t_18 = (__pyx_v_j + 1);\n",
       "      __pyx_t_19 = __pyx_v_i;\n",
       "      __pyx_t_20 = __pyx_v_j;\n",
       "      __pyx_t_21 = (__pyx_v_i - 1);\n",
       "      __pyx_t_22 = (__pyx_v_j - 1);\n",
       "      *__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_laplacian.rcbuffer->pybuffer.buf, __pyx_t_21, __pyx_pybuffernd_laplacian.diminfo[0].strides, __pyx_t_22, __pyx_pybuffernd_laplacian.diminfo[1].strides) = (((((*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_12, __pyx_pybuffernd_image.diminfo[1].strides)) + (*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_13, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_14, __pyx_pybuffernd_image.diminfo[1].strides))) + (*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_15, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_16, __pyx_pybuffernd_image.diminfo[1].strides))) + (*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_17, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_18, __pyx_pybuffernd_image.diminfo[1].strides))) - (4.0 * (*__Pyx_BufPtrStrided2d(double *, __pyx_pybuffernd_image.rcbuffer->pybuffer.buf, __pyx_t_19, __pyx_pybuffernd_image.diminfo[0].strides, __pyx_t_20, __pyx_pybuffernd_image.diminfo[1].strides))));\n",
       "    }\n",
       "  }\n",
       "
+17:     thresh = np.abs(laplacian) > 0.05
\n", "
  __pyx_t_4 = __Pyx_GetModuleGlobalName(__pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_4);\n",
       "  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_abs); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
       "  __Pyx_GOTREF(__pyx_t_3);\n",
       "  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "  __pyx_t_4 = NULL;\n",
       "  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {\n",
       "    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_3);\n",
       "    if (likely(__pyx_t_4)) {\n",
       "      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);\n",
       "      __Pyx_INCREF(__pyx_t_4);\n",
       "      __Pyx_INCREF(function);\n",
       "      __Pyx_DECREF_SET(__pyx_t_3, function);\n",
       "    }\n",
       "  }\n",
       "  if (!__pyx_t_4) {\n",
       "    __pyx_t_5 = __Pyx_PyObject_CallOneArg(__pyx_t_3, ((PyObject *)__pyx_v_laplacian)); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
       "    __Pyx_GOTREF(__pyx_t_5);\n",
       "  } else {\n",
       "    #if CYTHON_FAST_PYCALL\n",
       "    if (PyFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_laplacian)};\n",
       "      __pyx_t_5 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "    } else\n",
       "    #endif\n",
       "    #if CYTHON_FAST_PYCCALL\n",
       "    if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {\n",
       "      PyObject *__pyx_temp[2] = {__pyx_t_4, ((PyObject *)__pyx_v_laplacian)};\n",
       "      __pyx_t_5 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-1, 1+1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
       "      __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "    } else\n",
       "    #endif\n",
       "    {\n",
       "      __pyx_t_2 = PyTuple_New(1+1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_2);\n",
       "      __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4); __pyx_t_4 = NULL;\n",
       "      __Pyx_INCREF(((PyObject *)__pyx_v_laplacian));\n",
       "      __Pyx_GIVEREF(((PyObject *)__pyx_v_laplacian));\n",
       "      PyTuple_SET_ITEM(__pyx_t_2, 0+1, ((PyObject *)__pyx_v_laplacian));\n",
       "      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_2, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
       "      __Pyx_GOTREF(__pyx_t_5);\n",
       "      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;\n",
       "    }\n",
       "  }\n",
       "  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;\n",
       "  __pyx_t_3 = PyObject_RichCompare(__pyx_t_5, __pyx_float_0_05, Py_GT); __Pyx_XGOTREF(__pyx_t_3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 17, __pyx_L1_error)\n",
       "  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;\n",
       "  __pyx_v_thresh = __pyx_t_3;\n",
       "  __pyx_t_3 = 0;\n",
       "
+18:     return thresh
\n", "
  __Pyx_XDECREF(__pyx_r);\n",
       "  __Pyx_INCREF(__pyx_v_thresh);\n",
       "  __pyx_r = __pyx_v_thresh;\n",
       "  goto __pyx_L0;\n",
       "
" ], "text/plain": [ "" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%cython -a\n", "import numpy as np\n", "cimport numpy as cnp\n", "import cython\n", "\n", "@cython.boundscheck(False) # turn off bounds-checking for entire function\n", "@cython.wraparound(False) # turn off negative index wrapping for entire function\n", "def laplace_cython(cnp.ndarray[double, ndim=2] image):\n", " \"\"\"Applies Laplace operator to 2D image, then tresholds the result and returns boolean image.\n", " Cython implementation.\"\"\"\n", " cdef int h = image.shape[0]\n", " cdef int w = image.shape[1]\n", " cdef cnp.ndarray[double, ndim=2] laplacian = np.empty((w-2, h-2), dtype=np.double)\n", " cdef int i, j\n", " for i in range(1, h-1):\n", " for j in range(1, w-1):\n", " laplacian[i-1, j-1] = image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.58 ms ± 32.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit laplace_cython(image)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.allclose(laplace_numpy(image), laplace_cython(image))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What we can notice in the above function is that we have gotten rid completely of interaction in the for loop, which leads to a 4x increase in performance over our NumPy implementation." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's now turn to pythran." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Pythran " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One of the advantages of pythran is that it can optimize higher level numpy code than Cython. Luckily for us again, it features a line magic, so we keep working in the notebook." ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "%load_ext pythran.magic" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To use pythran, all you have to do is to annotate the function you want to export and give it a signature. This is done in a comment line starting the pythran file. One of the promises of pythran is that it can often handle high level broadcasting with NumPy and still optimize our function.\n", "\n", "Annotating our NumPy function, we obtain this:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "scrolled": true }, "outputs": [], "source": [ "%%pythran\n", "#pythran export laplace_pythran_highlevel(float[][])\n", "import numpy as np\n", "def laplace_pythran_highlevel(image):\n", " \"\"\"Laplace operator in NumPy for 2D images. Pythran accelerated.\"\"\"\n", " laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.allclose(laplace_numpy(image), laplace_pythran_highlevel(image))" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "368 µs ± 5.09 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit laplace_pythran_highlevel(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wow! Pythran translated that to the fastest version so far!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But pythran can also translate \"low level style\" code, just like Cython. Let's try again in a low-level style." ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "%%pythran \n", "#pythran export laplace_pythran_lowlevel(float[][])\n", "import numpy as np\n", "def laplace_pythran_lowlevel(image):\n", " \"\"\"Laplace operator in NumPy for 2D images. Pythran accelerated.\"\"\"\n", " h = image.shape[0]\n", " w = image.shape[1]\n", " laplacian = np.empty((h - 2, w - 2))\n", " for i in range(1, h - 1):\n", " for j in range(1, w - 1):\n", " laplacian[i-1, j-1] = image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.allclose(laplace_numpy(image), laplace_pythran_lowlevel(image))" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "795 µs ± 8.04 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit laplace_pythran_lowlevel(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Less fast than before. What if we move the thresholding operation inside the main loop?" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "%%pythran \n", "#pythran export laplace_pythran_lowlevel(float[][])\n", "import numpy as np\n", "def laplace_pythran_lowlevel(image):\n", " \"\"\"Laplace operator in NumPy for 2D images. Pythran accelerated.\"\"\"\n", " h = image.shape[0]\n", " w = image.shape[1]\n", " laplacian = np.empty((h - 2, w - 2))\n", " for i in range(1, h - 1):\n", " for j in range(1, w - 1):\n", " laplacian[i-1, j-1] = np.abs(image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]) > 0.05\n", " return laplacian" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.allclose(laplace_numpy(image), laplace_pythran_lowlevel(image))" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "577 µs ± 10.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit laplace_pythran_lowlevel(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So in this case, pythran with a low level approach outperforms Cython, with the best result being when it's given high-level Numpy code." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another interesting point here, concerning debugging pythran compilation, is that pythran annotated code is still perfectly valid Python. This helps during the debugging phase, compared to the previously explained Cython approach." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's turn to our last tool, `numba`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Numba " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Numba is very similar to pythran, except that it does just-in-time compilation (JIT). We have several options to for use. Let's try the standard `jit` approach with a decorator." ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "from numba import jit" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "@jit\n", "def laplace_numba(image):\n", " \"\"\"Laplace operator in NumPy for 2D images. Accelerated using numba.\"\"\"\n", " laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We call it once to avoid timing issues due to JIT compilation." ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [], "source": [ "laplace_numba(image);" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.4 ms ± 22.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit laplace_numba(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is rightaway faster than NumPy." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also tell numba to avoid using Python at all in its computation. This is called with `@jit(nopython=True)`." ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "@jit(nopython=True)\n", "def laplace_numba(image):\n", " \"\"\"Laplace operator in NumPy for 2D images. Accelerated using numba.\"\"\"\n", " laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [], "source": [ "laplace_numba(image);" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2.37 ms ± 14 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%timeit laplace_numba(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "No big effect. In fact, we can infer from this that numba managed to generate pure C code from our function and that it did it already previously. \n", "\n", "To confirm that, we can either use the `inspect_types()` method of our jitted function or use the annotation tool provided with numba." ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "laplace_numba (array(float64, 2d, C),)\n", "--------------------------------------------------------------------------------\n", "# File: \n", "# --- LINE 1 --- \n", "# label 0\n", "# del $const0.3\n", "# del $const0.2\n", "# del $0.4\n", "# del $const0.7\n", "# del $const0.6\n", "# del $0.8\n", "# del $0.9\n", "# del $0.5\n", "# del $0.10\n", "# del $const0.14\n", "# del $const0.13\n", "# del $0.15\n", "# del $const0.18\n", "# del $const0.17\n", "# del $0.19\n", "# del $0.20\n", "# del $0.16\n", "# del $0.21\n", "# del $const0.26\n", "# del $const0.25\n", "# del $0.27\n", "# del $const0.30\n", "# del $const0.29\n", "# del $0.31\n", "# del $0.32\n", "# del $0.28\n", "# del $0.33\n", "# del $const0.38\n", "# del $const0.37\n", "# del $0.39\n", "# del $const0.42\n", "# del $const0.41\n", "# del $0.43\n", "# del $0.44\n", "# del $0.40\n", "# del $0.45\n", "# del $const0.51\n", "# del $const0.50\n", "# del $0.52\n", "# del $const0.55\n", "# del $const0.54\n", "# del $0.56\n", "# del $0.57\n", "# del $0.53\n", "# del image\n", "# del $0.58\n", "# del $const0.48\n", "# del $0.11\n", "# del $0.22\n", "# del $0.34\n", "# del $0.46\n", "# del $0.59\n", "# del $0.61\n", "# del $0.62\n", "# del $0.63\n", "# del laplacian\n", "# del $const0.66\n", "# del $0.67\n", "# del thresh\n", "\n", "@jit(nopython=True)\n", "\n", "# --- LINE 2 --- \n", "\n", "def laplace_numba(image):\n", "\n", " # --- LINE 3 --- \n", "\n", " \"\"\"Laplace operator in NumPy for 2D images. Accelerated using numba.\"\"\"\n", "\n", " # --- LINE 4 --- \n", " # image = arg(0, name=image) :: array(float64, 2d, C)\n", " # $const0.2 = const(NoneType, None) :: none\n", " # $const0.3 = const(int, -2) :: int64\n", " # $0.4 = global(slice: ) :: Function()\n", " # $0.5 = call $0.4($const0.2, $const0.3, func=$0.4, args=(Var($const0.2, (4)), Var($const0.3, (4))), kws=(), vararg=None) :: (none, int64) -> slice\n", " # $const0.6 = const(int, 1) :: int64\n", " # $const0.7 = const(int, -1) :: int64\n", " # $0.8 = global(slice: ) :: Function()\n", " # $0.9 = call $0.8($const0.6, $const0.7, func=$0.8, args=(Var($const0.6, (4)), Var($const0.7, (4))), kws=(), vararg=None) :: (int64, int64) -> slice\n", " # $0.10 = build_tuple(items=[Var($0.5, (4)), Var($0.9, (4))]) :: (slice x 2)\n", " # $0.11 = static_getitem(value=image, index=(slice(None, -2, None), slice(1, -1, None)), index_var=$0.10) :: array(float64, 2d, A)\n", " # $const0.13 = const(int, 2) :: int64\n", " # $const0.14 = const(NoneType, None) :: none\n", " # $0.15 = global(slice: ) :: Function()\n", " # $0.16 = call $0.15($const0.13, $const0.14, func=$0.15, args=(Var($const0.13, (4)), Var($const0.14, (4))), kws=(), vararg=None) :: (int64, none) -> slice\n", " # $const0.17 = const(int, 1) :: int64\n", " # $const0.18 = const(int, -1) :: int64\n", " # $0.19 = global(slice: ) :: Function()\n", " # $0.20 = call $0.19($const0.17, $const0.18, func=$0.19, args=(Var($const0.17, (4)), Var($const0.18, (4))), kws=(), vararg=None) :: (int64, int64) -> slice\n", " # $0.21 = build_tuple(items=[Var($0.16, (4)), Var($0.20, (4))]) :: (slice x 2)\n", " # $0.22 = static_getitem(value=image, index=(slice(2, None, None), slice(1, -1, None)), index_var=$0.21) :: array(float64, 2d, A)\n", " # $const0.25 = const(int, 1) :: int64\n", " # $const0.26 = const(int, -1) :: int64\n", " # $0.27 = global(slice: ) :: Function()\n", " # $0.28 = call $0.27($const0.25, $const0.26, func=$0.27, args=(Var($const0.25, (4)), Var($const0.26, (4))), kws=(), vararg=None) :: (int64, int64) -> slice\n", " # $const0.29 = const(NoneType, None) :: none\n", " # $const0.30 = const(int, -2) :: int64\n", " # $0.31 = global(slice: ) :: Function()\n", " # $0.32 = call $0.31($const0.29, $const0.30, func=$0.31, args=(Var($const0.29, (4)), Var($const0.30, (4))), kws=(), vararg=None) :: (none, int64) -> slice\n", " # $0.33 = build_tuple(items=[Var($0.28, (4)), Var($0.32, (4))]) :: (slice x 2)\n", " # $0.34 = static_getitem(value=image, index=(slice(1, -1, None), slice(None, -2, None)), index_var=$0.33) :: array(float64, 2d, A)\n", " # $const0.37 = const(int, 1) :: int64\n", " # $const0.38 = const(int, -1) :: int64\n", " # $0.39 = global(slice: ) :: Function()\n", " # $0.40 = call $0.39($const0.37, $const0.38, func=$0.39, args=(Var($const0.37, (4)), Var($const0.38, (4))), kws=(), vararg=None) :: (int64, int64) -> slice\n", " # $const0.41 = const(int, 2) :: int64\n", " # $const0.42 = const(NoneType, None) :: none\n", " # $0.43 = global(slice: ) :: Function()\n", " # $0.44 = call $0.43($const0.41, $const0.42, func=$0.43, args=(Var($const0.41, (4)), Var($const0.42, (4))), kws=(), vararg=None) :: (int64, none) -> slice\n", " # $0.45 = build_tuple(items=[Var($0.40, (4)), Var($0.44, (4))]) :: (slice x 2)\n", " # $0.46 = static_getitem(value=image, index=(slice(1, -1, None), slice(2, None, None)), index_var=$0.45) :: array(float64, 2d, A)\n", " # $const0.48 = const(int, 4) :: int64\n", " # $const0.50 = const(int, 1) :: int64\n", " # $const0.51 = const(int, -1) :: int64\n", " # $0.52 = global(slice: ) :: Function()\n", " # $0.53 = call $0.52($const0.50, $const0.51, func=$0.52, args=(Var($const0.50, (4)), Var($const0.51, (4))), kws=(), vararg=None) :: (int64, int64) -> slice\n", " # $const0.54 = const(int, 1) :: int64\n", " # $const0.55 = const(int, -1) :: int64\n", " # $0.56 = global(slice: ) :: Function()\n", " # $0.57 = call $0.56($const0.54, $const0.55, func=$0.56, args=(Var($const0.54, (4)), Var($const0.55, (4))), kws=(), vararg=None) :: (int64, int64) -> slice\n", " # $0.58 = build_tuple(items=[Var($0.53, (4)), Var($0.57, (4))]) :: (slice x 2)\n", " # $0.59 = static_getitem(value=image, index=(slice(1, -1, None), slice(1, -1, None)), index_var=$0.58) :: array(float64, 2d, A)\n", " # $0.61 = arrayexpr(expr=('-', [('+', [('+', [('+', [Var($0.11, (4)), Var($0.22, (4))]), Var($0.34, (4))]), Var($0.46, (4))]), ('*', [const(int, 4), Var($0.59, (4))])]), ty=array(float64, 2d, C)) :: array(float64, 2d, C)\n", " # laplacian = $0.61 :: array(float64, 2d, C)\n", "\n", " laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", "\n", " # --- LINE 5 --- \n", " # $0.62 = global(np: ) :: Module()\n", " # $0.63 = getattr(value=$0.62, attr=abs) :: Function()\n", " # $const0.66 = const(float, 0.05) :: float64\n", " # $0.67 = arrayexpr(expr=('>', [(, [Var(laplacian, (4))]), const(float, 0.05)]), ty=array(bool, 2d, C)) :: array(bool, 2d, C)\n", " # thresh = $0.67 :: array(bool, 2d, C)\n", "\n", " thresh = np.abs(laplacian) > 0.05\n", "\n", " # --- LINE 6 --- \n", " # $0.69 = cast(value=thresh) :: array(bool, 2d, C)\n", " # return $0.69\n", "\n", " return thresh\n", "\n", "\n", "================================================================================\n" ] } ], "source": [ "laplace_numba.inspect_types()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Admittedly, not very helpful. Let's try the annotation tool." ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting numba_annotation_demo.py\n" ] } ], "source": [ "%%file numba_annotation_demo.py\n", "import numpy as np\n", "import skimage.data\n", "import skimage.color\n", "from numba import jit\n", "\n", "@jit(nopython=True)\n", "def laplace_numba(image):\n", " \"\"\"Laplace operator in NumPy for 2D images. Accelerated using numba.\"\"\"\n", " laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", " thresh = np.abs(laplacian) > 0.05\n", " return thresh\n", "\n", "image = skimage.data.astronaut()\n", "image = skimage.color.rgb2gray(image)\n", "laplace_numba(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have to run the annotation tool from the command line:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [], "source": [ "!numba --annotate-html annotation.html numba_annotation_demo.py" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [], "source": [ "from IPython.display import HTML" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", " \n", "\n", " \n", "\n", "
\n", " Function name: laplace_numba
\n", " in file: numba_annotation_demo.py
\n", " with signature: (array(float64, 2d, C),) -> array(bool, 2d, C)\n", "
\n", "\n", "
\n", "\n", " show numba IR\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", " \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", "\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", " 6:\n", " \n", " @jit(nopython=True)\n", "
 \n", " \n", " label 0\n", " \n", "
 \n", " \n", "   del $const0.3\n", " \n", "
 \n", " \n", "   del $const0.2\n", " \n", "
 \n", " \n", "   del $0.4\n", " \n", "
 \n", " \n", "   del $const0.7\n", " \n", "
 \n", " \n", "   del $const0.6\n", " \n", "
 \n", " \n", "   del $0.8\n", " \n", "
 \n", " \n", "   del $0.9\n", " \n", "
 \n", " \n", "   del $0.5\n", " \n", "
 \n", " \n", "   del $0.10\n", " \n", "
 \n", " \n", "   del $const0.14\n", " \n", "
 \n", " \n", "   del $const0.13\n", " \n", "
 \n", " \n", "   del $0.15\n", " \n", "
 \n", " \n", "   del $const0.18\n", " \n", "
 \n", " \n", "   del $const0.17\n", " \n", "
 \n", " \n", "   del $0.19\n", " \n", "
 \n", " \n", "   del $0.20\n", " \n", "
 \n", " \n", "   del $0.16\n", " \n", "
 \n", " \n", "   del $0.21\n", " \n", "
 \n", " \n", "   del $0.22\n", " \n", "
 \n", " \n", "   del $0.11\n", " \n", "
 \n", " \n", "   del $const0.26\n", " \n", "
 \n", " \n", "   del $const0.25\n", " \n", "
 \n", " \n", "   del $0.27\n", " \n", "
 \n", " \n", "   del $const0.30\n", " \n", "
 \n", " \n", "   del $const0.29\n", " \n", "
 \n", " \n", "   del $0.31\n", " \n", "
 \n", " \n", "   del $0.32\n", " \n", "
 \n", " \n", "   del $0.28\n", " \n", "
 \n", " \n", "   del $0.33\n", " \n", "
 \n", " \n", "   del $0.34\n", " \n", "
 \n", " \n", "   del $0.23\n", " \n", "
 \n", " \n", "   del $const0.38\n", " \n", "
 \n", " \n", "   del $const0.37\n", " \n", "
 \n", " \n", "   del $0.39\n", " \n", "
 \n", " \n", "   del $const0.42\n", " \n", "
 \n", " \n", "   del $const0.41\n", " \n", "
 \n", " \n", "   del $0.43\n", " \n", "
 \n", " \n", "   del $0.44\n", " \n", "
 \n", " \n", "   del $0.40\n", " \n", "
 \n", " \n", "   del $0.45\n", " \n", "
 \n", " \n", "   del $0.46\n", " \n", "
 \n", " \n", "   del $0.35\n", " \n", "
 \n", " \n", "   del $const0.51\n", " \n", "
 \n", " \n", "   del $const0.50\n", " \n", "
 \n", " \n", "   del $0.52\n", " \n", "
 \n", " \n", "   del $const0.55\n", " \n", "
 \n", " \n", "   del $const0.54\n", " \n", "
 \n", " \n", "   del $0.56\n", " \n", "
 \n", " \n", "   del $0.57\n", " \n", "
 \n", " \n", "   del $0.53\n", " \n", "
 \n", " \n", "   del image\n", " \n", "
 \n", " \n", "   del $0.58\n", " \n", "
 \n", " \n", "   del $const0.48\n", " \n", "
 \n", " \n", "   del $0.59\n", " \n", "
 \n", " \n", "   del $0.60\n", " \n", "
 \n", " \n", "   del $0.47\n", " \n", "
 \n", " \n", "   del $0.61\n", " \n", "
 \n", " \n", "   del $0.62\n", " \n", "
 \n", " \n", "   del laplacian\n", " \n", "
 \n", " \n", "   del $0.63\n", " \n", "
 \n", " \n", "   del $const0.66\n", " \n", "
 \n", " \n", "   del $0.65\n", " \n", "
 \n", " \n", "   del $0.67\n", " \n", "
 \n", " \n", "   del thresh\n", " \n", "
\n", " 7:\n", " \n", " def laplace_numba(image):\n", "
\n", " 8:\n", " \n", "     """Laplace operator in NumPy for 2D images. Accelerated using numba."""\n", "
\n", " 9:\n", " \n", "     laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", "
 \n", "     \n", "   image = arg(0, name=image) :: array(float64, 2d, C)\n", " \n", "
 \n", "     \n", "   $const0.2 = const(NoneType, None) :: none\n", " \n", "
 \n", "     \n", "   $const0.3 = const(int, -2) :: int64\n", " \n", "
 \n", "     \n", "   $0.4 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.5 = call $0.4($const0.2, $const0.3, func=$0.4, args=(Var($const0.2, numba_annotation_demo.py (9)), Var($const0.3, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (none, int64) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $const0.6 = const(int, 1) :: int64\n", " \n", "
 \n", "     \n", "   $const0.7 = const(int, -1) :: int64\n", " \n", "
 \n", "     \n", "   $0.8 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.9 = call $0.8($const0.6, $const0.7, func=$0.8, args=(Var($const0.6, numba_annotation_demo.py (9)), Var($const0.7, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (int64, int64) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $0.10 = build_tuple(items=[Var($0.5, numba_annotation_demo.py (9)), Var($0.9, numba_annotation_demo.py (9))]) :: (slice<a:b> x 2)\n", " \n", "
 \n", "     \n", "   $0.11 = static_getitem(value=image, index=(slice(None, -2, None), slice(1, -1, None)), index_var=$0.10) :: array(float64, 2d, A)\n", " \n", "
 \n", "     \n", "   $const0.13 = const(int, 2) :: int64\n", " \n", "
 \n", "     \n", "   $const0.14 = const(NoneType, None) :: none\n", " \n", "
 \n", "     \n", "   $0.15 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.16 = call $0.15($const0.13, $const0.14, func=$0.15, args=(Var($const0.13, numba_annotation_demo.py (9)), Var($const0.14, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (int64, none) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $const0.17 = const(int, 1) :: int64\n", " \n", "
 \n", "     \n", "   $const0.18 = const(int, -1) :: int64\n", " \n", "
 \n", "     \n", "   $0.19 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.20 = call $0.19($const0.17, $const0.18, func=$0.19, args=(Var($const0.17, numba_annotation_demo.py (9)), Var($const0.18, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (int64, int64) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $0.21 = build_tuple(items=[Var($0.16, numba_annotation_demo.py (9)), Var($0.20, numba_annotation_demo.py (9))]) :: (slice<a:b> x 2)\n", " \n", "
 \n", "     \n", "   $0.22 = static_getitem(value=image, index=(slice(2, None, None), slice(1, -1, None)), index_var=$0.21) :: array(float64, 2d, A)\n", " \n", "
 \n", "     \n", "   $0.23 = $0.11 + $0.22 :: array(float64, 2d, C)\n", " \n", "
 \n", "     \n", "   $const0.25 = const(int, 1) :: int64\n", " \n", "
 \n", "     \n", "   $const0.26 = const(int, -1) :: int64\n", " \n", "
 \n", "     \n", "   $0.27 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.28 = call $0.27($const0.25, $const0.26, func=$0.27, args=(Var($const0.25, numba_annotation_demo.py (9)), Var($const0.26, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (int64, int64) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $const0.29 = const(NoneType, None) :: none\n", " \n", "
 \n", "     \n", "   $const0.30 = const(int, -2) :: int64\n", " \n", "
 \n", "     \n", "   $0.31 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.32 = call $0.31($const0.29, $const0.30, func=$0.31, args=(Var($const0.29, numba_annotation_demo.py (9)), Var($const0.30, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (none, int64) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $0.33 = build_tuple(items=[Var($0.28, numba_annotation_demo.py (9)), Var($0.32, numba_annotation_demo.py (9))]) :: (slice<a:b> x 2)\n", " \n", "
 \n", "     \n", "   $0.34 = static_getitem(value=image, index=(slice(1, -1, None), slice(None, -2, None)), index_var=$0.33) :: array(float64, 2d, A)\n", " \n", "
 \n", "     \n", "   $0.35 = $0.23 + $0.34 :: array(float64, 2d, C)\n", " \n", "
 \n", "     \n", "   $const0.37 = const(int, 1) :: int64\n", " \n", "
 \n", "     \n", "   $const0.38 = const(int, -1) :: int64\n", " \n", "
 \n", "     \n", "   $0.39 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.40 = call $0.39($const0.37, $const0.38, func=$0.39, args=(Var($const0.37, numba_annotation_demo.py (9)), Var($const0.38, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (int64, int64) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $const0.41 = const(int, 2) :: int64\n", " \n", "
 \n", "     \n", "   $const0.42 = const(NoneType, None) :: none\n", " \n", "
 \n", "     \n", "   $0.43 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.44 = call $0.43($const0.41, $const0.42, func=$0.43, args=(Var($const0.41, numba_annotation_demo.py (9)), Var($const0.42, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (int64, none) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $0.45 = build_tuple(items=[Var($0.40, numba_annotation_demo.py (9)), Var($0.44, numba_annotation_demo.py (9))]) :: (slice<a:b> x 2)\n", " \n", "
 \n", "     \n", "   $0.46 = static_getitem(value=image, index=(slice(1, -1, None), slice(2, None, None)), index_var=$0.45) :: array(float64, 2d, A)\n", " \n", "
 \n", "     \n", "   $0.47 = $0.35 + $0.46 :: array(float64, 2d, C)\n", " \n", "
 \n", "     \n", "   $const0.48 = const(int, 4) :: int64\n", " \n", "
 \n", "     \n", "   $const0.50 = const(int, 1) :: int64\n", " \n", "
 \n", "     \n", "   $const0.51 = const(int, -1) :: int64\n", " \n", "
 \n", "     \n", "   $0.52 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.53 = call $0.52($const0.50, $const0.51, func=$0.52, args=(Var($const0.50, numba_annotation_demo.py (9)), Var($const0.51, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (int64, int64) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $const0.54 = const(int, 1) :: int64\n", " \n", "
 \n", "     \n", "   $const0.55 = const(int, -1) :: int64\n", " \n", "
 \n", "     \n", "   $0.56 = global(slice: <class 'slice'>) :: Function(<class 'slice'>)\n", " \n", "
 \n", "     \n", "   $0.57 = call $0.56($const0.54, $const0.55, func=$0.56, args=(Var($const0.54, numba_annotation_demo.py (9)), Var($const0.55, numba_annotation_demo.py (9))), kws=(), vararg=None) :: (int64, int64) -> slice<a:b>\n", " \n", "
 \n", "     \n", "   $0.58 = build_tuple(items=[Var($0.53, numba_annotation_demo.py (9)), Var($0.57, numba_annotation_demo.py (9))]) :: (slice<a:b> x 2)\n", " \n", "
 \n", "     \n", "   $0.59 = static_getitem(value=image, index=(slice(1, -1, None), slice(1, -1, None)), index_var=$0.58) :: array(float64, 2d, A)\n", " \n", "
 \n", "     \n", "   $0.60 = $const0.48 * $0.59 :: array(float64, 2d, C)\n", " \n", "
 \n", "     \n", "   $0.61 = $0.47 - $0.60 :: array(float64, 2d, C)\n", " \n", "
 \n", "     \n", "   laplacian = $0.61 :: array(float64, 2d, C)\n", " \n", "
\n", " 10:\n", " \n", "     thresh = np.abs(laplacian) > 0.05\n", "
 \n", "     \n", "   $0.62 = global(np: <module 'numpy' from '/Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/__init__.py'>) :: Module(<module 'numpy' from '/Users/kappamaki/anaconda/lib/python3.6/site-packages/numpy/__init__.py'>)\n", " \n", "
 \n", "     \n", "   $0.63 = getattr(value=$0.62, attr=abs) :: Function(<ufunc 'absolute'>)\n", " \n", "
 \n", "     \n", "   $0.65 = call $0.63(laplacian, func=$0.63, args=[Var(laplacian, numba_annotation_demo.py (9))], kws=(), vararg=None) :: (array(float64, 2d, C),) -> array(float64, 2d, C)\n", " \n", "
 \n", "     \n", "   $const0.66 = const(float, 0.05) :: float64\n", " \n", "
 \n", "     \n", "   $0.67 = $0.65 > $const0.66 :: array(bool, 2d, C)\n", " \n", "
 \n", "     \n", "   thresh = $0.67 :: array(bool, 2d, C)\n", " \n", "
\n", " 11:\n", " \n", "     return thresh\n", "
 \n", "     \n", "   $0.69 = cast(value=thresh) :: array(bool, 2d, C)\n", " \n", "
 \n", "     \n", "   return $0.69\n", " \n", "
\n", "\n", "
\n", "\n", "


\n", "\n", " \n", "\n", " \n", "\n", "
\n", " Function name: __numba_array_expr_0x115caebe
\n", " in file: numba_annotation_demo.py
\n", " with signature: (float64, float64, float64, float64, float64) -> float64\n", "
\n", "\n", "
\n", "\n", " show numba IR\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", "\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", "\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", "\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", "\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", " 1:\n", " \n", " import numpy as np\n", "
 \n", " \n", " label 0\n", " \n", "
 \n", " \n", "   del _0_22\n", " \n", "
 \n", " \n", "   del _0_11\n", " \n", "
 \n", " \n", "   del _0_34\n", " \n", "
 \n", " \n", "   del $0.3\n", " \n", "
 \n", " \n", "   del _0_46\n", " \n", "
 \n", " \n", "   del $0.5\n", " \n", "
 \n", " \n", "   del _0_59\n", " \n", "
 \n", " \n", "   del $const0.8\n", " \n", "
 \n", " \n", "   del $0.7\n", " \n", "
 \n", " \n", "   del $0.10\n", " \n", "
 \n", " \n", "   del $0.11\n", " \n", "
\n", " 2:\n", " \n", " import skimage.data\n", "
\n", " 3:\n", " \n", " import skimage.color\n", "
\n", " 4:\n", " \n", " from numba import jit\n", "
\n", " 5:\n", " \n", " \n", "
\n", " 6:\n", " \n", " @jit(nopython=True)\n", "
\n", " 7:\n", " \n", " def laplace_numba(image):\n", "
\n", " 8:\n", " \n", "     """Laplace operator in NumPy for 2D images. Accelerated using numba."""\n", "
\n", " 9:\n", " \n", "     laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", "
 \n", "     \n", "   _0_11 = arg(0, name=_0_11) :: float64\n", " \n", "
 \n", "     \n", "   _0_22 = arg(1, name=_0_22) :: float64\n", " \n", "
 \n", "     \n", "   _0_34 = arg(2, name=_0_34) :: float64\n", " \n", "
 \n", "     \n", "   _0_46 = arg(3, name=_0_46) :: float64\n", " \n", "
 \n", "     \n", "   _0_59 = arg(4, name=_0_59) :: float64\n", " \n", "
 \n", "     \n", "   $0.3 = _0_11 + _0_22 :: float64\n", " \n", "
 \n", "     \n", "   $0.5 = $0.3 + _0_34 :: float64\n", " \n", "
 \n", "     \n", "   $0.7 = $0.5 + _0_46 :: float64\n", " \n", "
 \n", "     \n", "   $const0.8 = const(int, 4) :: int64\n", " \n", "
 \n", "     \n", "   $0.10 = $const0.8 * _0_59 :: float64\n", " \n", "
 \n", "     \n", "   $0.11 = $0.7 - $0.10 :: float64\n", " \n", "
 \n", "     \n", "   $0.12 = cast(value=$0.11) :: float64\n", " \n", "
 \n", "     \n", "   return $0.12\n", " \n", "
\n", " 10:\n", " \n", "     thresh = np.abs(laplacian) > 0.05\n", "
\n", " 11:\n", " \n", "     return thresh\n", "
\n", "\n", "
\n", "\n", "


\n", "\n", " \n", "\n", " \n", "\n", "
\n", " Function name: _broadcast_onto
\n", " in file: /Users/kappamaki/anaconda/lib/python3.6/site-packages/numba/targets/npyimpl.py
\n", " with signature: (int64, int64*, int64, int64*) -> int64\n", "
\n", "\n", "
\n", "\n", " show numba IR\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", " \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", "\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", " \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", " \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", "\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", "\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", "\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", "\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", " \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", " \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", " \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", " \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", " \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", "\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", " \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", " \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", " \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", " \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", " \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", " 176:\n", " \n", " def _broadcast_onto(src_ndim, src_shape, dest_ndim, dest_shape):\n", "
 \n", " \n", " label 0\n", " \n", "
\n", " 177:\n", " \n", "     '''Low-level utility function used in calculating a shape for\n", "
\n", " 178:\n", " \n", "     an implicit output array. This function assumes that the\n", "
\n", " 179:\n", " \n", "     destination shape is an LLVM pointer to a C-style array that was\n", "
\n", " 180:\n", " \n", "     already initialized to a size of one along all axes.\n", "
\n", " 181:\n", " \n", " \n", "
\n", " 182:\n", " \n", "     Returns an integer value:\n", "
\n", " 183:\n", " \n", "     >= 1 : Succeeded. Return value should equal the number of dimensions in\n", "
\n", " 184:\n", " \n", "              the destination shape.\n", "
\n", " 185:\n", " \n", "     0 : Failed to broadcast because source shape is larger than the\n", "
\n", " 186:\n", " \n", "              destination shape (this case should be weeded out at type\n", "
\n", " 187:\n", " \n", "              checking).\n", "
\n", " 188:\n", " \n", "     < 0 : Failed to broadcast onto destination axis, at axis number ==\n", "
\n", " 189:\n", " \n", "              -(return_value + 1).\n", "
\n", " 190:\n", " \n", "     '''\n", "
\n", " 191:\n", " \n", "     if src_ndim > dest_ndim:\n", "
 \n", "     \n", "   src_ndim = arg(0, name=src_ndim) :: int64\n", " \n", "
 \n", "     \n", "   src_shape = arg(1, name=src_shape) :: int64*\n", " \n", "
 \n", "     \n", "   dest_ndim = arg(2, name=dest_ndim) :: int64\n", " \n", "
 \n", "     \n", "   dest_shape = arg(3, name=dest_shape) :: int64*\n", " \n", "
 \n", "     \n", "   $0.3 = src_ndim > dest_ndim :: bool\n", " \n", "
 \n", "     \n", "   branch $0.3, 8, 12\n", " \n", "
 \n", "     \n", " label 8\n", " \n", "
 \n", "     \n", "   del src_shape\n", " \n", "
 \n", "     \n", "   del src_ndim\n", " \n", "
 \n", "     \n", "   del dest_shape\n", " \n", "
 \n", "     \n", "   del dest_ndim\n", " \n", "
 \n", "     \n", "   del $0.3\n", " \n", "
 \n", "     \n", "   del $const8.1\n", " \n", "
\n", " 192:\n", " \n", "         # This check should have been done during type checking, but\n", "
\n", " 193:\n", " \n", "         # let's be defensive anyway...\n", "
\n", " 194:\n", " \n", "         return 0\n", "
 \n", "         \n", "   $const8.1 = const(int, 0) :: int64\n", " \n", "
 \n", "         \n", "   $8.2 = cast(value=$const8.1) :: int64\n", " \n", "
 \n", "         \n", "   return $8.2\n", " \n", "
 \n", "         \n", " label 12\n", " \n", "
 \n", "         \n", "   del $0.3\n", " \n", "
 \n", "         \n", "   del $const12.1\n", " \n", "
 \n", "         \n", "   del dest_ndim\n", " \n", "
 \n", "         \n", "   del $12.4\n", " \n", "
\n", " 195:\n", " \n", "     else:\n", "
\n", " 196:\n", " \n", "         src_index = 0\n", "
 \n", "         \n", "   $const12.1 = const(int, 0) :: int64\n", " \n", "
 \n", "         \n", "   src_index = $const12.1 :: int64\n", " \n", "
\n", " 197:\n", " \n", "         dest_index = dest_ndim - src_ndim\n", "
 \n", "         \n", "   $12.4 = dest_ndim - src_ndim :: int64\n", " \n", "
 \n", "         \n", "   dest_index = $12.4 :: int64\n", " \n", "
 \n", "         \n", "   jump 24\n", " \n", "
 \n", "         \n", " label 24\n", " \n", "
\n", " 198:\n", " \n", "         while src_index < src_ndim:\n", "
 \n", "         \n", "   jump 26\n", " \n", "
 \n", "         \n", " label 26\n", " \n", "
 \n", "         \n", "   $26.3 = src_index < src_ndim :: bool\n", " \n", "
 \n", "         \n", "   branch $26.3, 34, 120\n", " \n", "
 \n", "         \n", " label 34\n", " \n", "
 \n", "         \n", "   del $26.3\n", " \n", "
 \n", "         \n", "   del $34.3\n", " \n", "
 \n", "         \n", "   del $34.6\n", " \n", "
 \n", "         \n", "   del $const34.8\n", " \n", "
\n", " 199:\n", " \n", "             src_dim_size = src_shape[src_index]\n", "
 \n", "             \n", "   $34.3 = getitem(value=src_shape, index=src_index) :: int64\n", " \n", "
 \n", "             \n", "   src_dim_size = $34.3 :: int64\n", " \n", "
\n", " 200:\n", " \n", "             dest_dim_size = dest_shape[dest_index]\n", "
 \n", "             \n", "   $34.6 = getitem(value=dest_shape, index=dest_index) :: int64\n", " \n", "
 \n", "             \n", "   dest_dim_size = $34.6 :: int64\n", " \n", "
\n", " 201:\n", " \n", "             # Check to see if we've already mutated the destination\n", "
\n", " 202:\n", " \n", "             # shape along this axis.\n", "
\n", " 203:\n", " \n", "             if dest_dim_size != 1:\n", "
 \n", "             \n", "   $const34.8 = const(int, 1) :: int64\n", " \n", "
 \n", "             \n", "   $34.9 = dest_dim_size != $const34.8 :: bool\n", " \n", "
 \n", "             \n", "   branch $34.9, 58, 86\n", " \n", "
 \n", "             \n", " label 58\n", " \n", "
 \n", "             \n", "   del $34.9\n", " \n", "
 \n", "             \n", "   del dest_dim_size\n", " \n", "
\n", " 204:\n", " \n", "                 # If we have mutated the destination shape already,\n", "
\n", " 205:\n", " \n", "                 # then the source axis size must either be one,\n", "
\n", " 206:\n", " \n", "                 # or the destination axis size.\n", "
\n", " 207:\n", " \n", "                 if src_dim_size != dest_dim_size and src_dim_size != 1:\n", "
 \n", "                 \n", "   $58.3 = src_dim_size != dest_dim_size :: bool\n", " \n", "
 \n", "                 \n", "   branch $58.3, 66, 102\n", " \n", "
 \n", "                 \n", " label 66\n", " \n", "
 \n", "                 \n", "   del $58.3\n", " \n", "
 \n", "                 \n", "   $const66.2 = const(int, 1) :: int64\n", " \n", "
 \n", "                 \n", "   $66.3 = src_dim_size != $const66.2 :: bool\n", " \n", "
 \n", "                 \n", "   del src_dim_size\n", " \n", "
 \n", "                 \n", "   del $const66.2\n", " \n", "
 \n", "                 \n", "   branch $66.3, 74, 102\n", " \n", "
 \n", "                 \n", " label 74\n", " \n", "
 \n", "                 \n", "   del src_shape\n", " \n", "
 \n", "                 \n", "   del src_ndim\n", " \n", "
 \n", "                 \n", "   del src_index\n", " \n", "
 \n", "                 \n", "   del dest_shape\n", " \n", "
 \n", "                 \n", "   del $66.3\n", " \n", "
 \n", "                 \n", "   del dest_index\n", " \n", "
 \n", "                 \n", "   del $const74.2\n", " \n", "
 \n", "                 \n", "   del $74.3\n", " \n", "
 \n", "                 \n", "   del $74.4\n", " \n", "
\n", " 208:\n", " \n", "                     return -(dest_index + 1)\n", "
 \n", "                     \n", "   $const74.2 = const(int, 1) :: int64\n", " \n", "
 \n", "                     \n", "   $74.3 = dest_index + $const74.2 :: int64\n", " \n", "
 \n", "                     \n", "   $74.4 = unary(fn=-, value=$74.3) :: int64\n", " \n", "
 \n", "                     \n", "   $74.5 = cast(value=$74.4) :: int64\n", " \n", "
 \n", "                     \n", "   return $74.5\n", " \n", "
 \n", "                     \n", " label 86\n", " \n", "
 \n", "                     \n", "   del dest_dim_size\n", " \n", "
 \n", "                     \n", "   del $34.9\n", " \n", "
 \n", "                     \n", "   del $const86.2\n", " \n", "
\n", " 209:\n", " \n", "             elif src_dim_size != 1:\n", "
 \n", "             \n", "   $const86.2 = const(int, 1) :: int64\n", " \n", "
 \n", "             \n", "   $86.3 = src_dim_size != $const86.2 :: bool\n", " \n", "
 \n", "             \n", "   branch $86.3, 94, 102\n", " \n", "
 \n", "             \n", " label 94\n", " \n", "
 \n", "             \n", "   del $86.3\n", " \n", "
 \n", "             \n", "   del src_dim_size\n", " \n", "
\n", " 210:\n", " \n", "                 # If the destination size is still its initial\n", "
\n", " 211:\n", " \n", "                 dest_shape[dest_index] = src_dim_size\n", "
 \n", "                 \n", "   dest_shape[dest_index] = src_dim_size :: (int64*, int64, int64) -> none\n", " \n", "
 \n", "                 \n", "   jump 102\n", " \n", "
 \n", "                 \n", " label 102\n", " \n", "
 \n", "                 \n", "   del src_dim_size\n", " \n", "
 \n", "                 \n", "   del $86.3\n", " \n", "
 \n", "                 \n", "   del $66.3\n", " \n", "
 \n", "                 \n", "   del $58.3\n", " \n", "
 \n", "                 \n", "   del $const102.2\n", " \n", "
 \n", "                 \n", "   del $102.3\n", " \n", "
 \n", "                 \n", "   del $const102.5\n", " \n", "
 \n", "                 \n", "   del $102.6\n", " \n", "
\n", " 212:\n", " \n", "             src_index += 1\n", "
 \n", "             \n", "   $const102.2 = const(int, 1) :: int64\n", " \n", "
 \n", "             \n", "   $102.3 = inplace_binop(fn=+=, immutable_fn=+, lhs=src_index, rhs=$const102.2, static_lhs=<object object at 0x1118f99a0>, static_rhs=<object object at 0x1118f99a0>) :: int64\n", " \n", "
 \n", "             \n", "   src_index = $102.3 :: int64\n", " \n", "
\n", " 213:\n", " \n", "             dest_index += 1\n", "
 \n", "             \n", "   $const102.5 = const(int, 1) :: int64\n", " \n", "
 \n", "             \n", "   $102.6 = inplace_binop(fn=+=, immutable_fn=+, lhs=dest_index, rhs=$const102.5, static_lhs=<object object at 0x1118f99a0>, static_rhs=<object object at 0x1118f99a0>) :: int64\n", " \n", "
 \n", "             \n", "   dest_index = $102.6 :: int64\n", " \n", "
 \n", "             \n", "   jump 26\n", " \n", "
 \n", "             \n", " label 120\n", " \n", "
 \n", "             \n", "   del src_shape\n", " \n", "
 \n", "             \n", "   del src_ndim\n", " \n", "
 \n", "             \n", "   del src_index\n", " \n", "
 \n", "             \n", "   del dest_shape\n", " \n", "
 \n", "             \n", "   del $26.3\n", " \n", "
 \n", "             \n", "   jump 122\n", " \n", "
 \n", "             \n", " label 122\n", " \n", "
 \n", "             \n", "   del dest_index\n", " \n", "
\n", " 214:\n", " \n", "     return dest_index\n", "
 \n", "     \n", "   $122.2 = cast(value=dest_index) :: int64\n", " \n", "
 \n", "     \n", "   return $122.2\n", " \n", "
\n", "\n", "
\n", "\n", "


\n", "\n", " \n", "\n", " \n", "\n", "
\n", " Function name: __numba_array_expr__0x7fffffffeea3510e
\n", " in file: numba_annotation_demo.py
\n", " with signature: (float64,) -> bool\n", "
\n", "\n", "
\n", "\n", " show numba IR\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", "\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", " \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", " \n", " \n", " \n", "\n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", " \n", " \n", " \n", "\n", " \n", " \n", " \n", "\n", " \n", "\n", " \n", "\n", "
\n", " 1:\n", " \n", " import numpy as np\n", "
 \n", " \n", " label 0\n", " \n", "
 \n", " \n", "   laplacian = arg(0, name=laplacian) :: float64\n", " \n", "
 \n", " \n", "   $0.1 = global(__ufunc_or_dufunc_0x7fa0b0d043e: <ufunc 'absolute'>) :: Function(<ufunc 'absolute'>)\n", " \n", "
 \n", " \n", "   del laplacian\n", " \n", "
 \n", " \n", "   del $0.1\n", " \n", "
 \n", " \n", "   del $const0.4\n", " \n", "
 \n", " \n", "   del $0.3\n", " \n", "
 \n", " \n", "   del $0.5\n", " \n", "
\n", " 2:\n", " \n", " import skimage.data\n", "
\n", " 3:\n", " \n", " import skimage.color\n", "
\n", " 4:\n", " \n", " from numba import jit\n", "
\n", " 5:\n", " \n", " \n", "
\n", " 6:\n", " \n", " @jit(nopython=True)\n", "
\n", " 7:\n", " \n", " def laplace_numba(image):\n", "
\n", " 8:\n", " \n", "     """Laplace operator in NumPy for 2D images. Accelerated using numba."""\n", "
\n", " 9:\n", " \n", "     laplacian = image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:] - 4*image[1:-1, 1:-1]\n", "
 \n", "     \n", "   $0.3 = call $0.1(laplacian, func=$0.1, args=[Var(laplacian, numba_annotation_demo.py (1))], kws=(), vararg=None) :: (float64,) -> float64\n", " \n", "
 \n", "     \n", "   $const0.4 = const(float, 0.05) :: float64\n", " \n", "
 \n", "     \n", "   $0.5 = $0.3 > $const0.4 :: bool\n", " \n", "
 \n", "     \n", "   $0.6 = cast(value=$0.5) :: bool\n", " \n", "
 \n", "     \n", "   return $0.6\n", " \n", "
\n", " 10:\n", " \n", "     thresh = np.abs(laplacian) > 0.05\n", "
\n", " 11:\n", " \n", "     return thresh\n", "
\n", "\n", "
\n", "\n", "


\n", "\n", " \n", "\n", "\n", "\n", "" ], "text/plain": [ "" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "HTML(data=open('annotation.html').read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What this shows is that `numba` managed to correctly optimize the broadcasting (if it hadn't we would have seen colored source code lines)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see also investigate how numba optimizes the low-level approach with explicit for loops." ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [], "source": [ "@jit(nopython=True)\n", "def laplace_numba(image):\n", " \"\"\"Laplace operator for 2D images. Numba accelerated.\"\"\"\n", " h = image.shape[0]\n", " w = image.shape[1]\n", " laplacian = np.empty((h - 2, w - 2))\n", " for i in range(1, h - 1):\n", " for j in range(1, w - 1):\n", " laplacian[i-1, j-1] = np.abs(image[i-1, j] + image[i+1, j] + image[i, j-1] + image[i, j+1] - 4*image[i, j]) > 0.05\n", " return laplacian" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [], "source": [ "laplace_numba(image);" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "848 µs ± 191 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit laplace_numba(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This approach improves the performance! " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another way of approaching optimization with numba is to thing in terms of NumPy ufuncs. You can write generalized ufuncs with numba using another decorator, `@guvectorize`. However, this comes at the cost that we have to think in terms of an ufunc and thus we have to provide an array that gets filled by our computation routine." ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": [ "from numba import guvectorize" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [], "source": [ "@guvectorize('void(float64[:, :], float64[:, :])', \"(m, n)->(m, n)\")\n", "def laplace_numba_guvectorize(image, laplacian):\n", " \"\"\"Laplace operator in NumPy for 2D images. Numba accelerated.\"\"\"\n", " h = image.shape[0]\n", " w = image.shape[1]\n", " for i in range(1, h - 1):\n", " for j in range(1, w - 1):\n", " laplacian[i-1, j-1] = np.abs(4 * image[i, j] - image[i - 1, j] - image[i + 1, j] - image[i, j + 1] - image[i, j - 1]) > 0.05" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [], "source": [ "laplacian = np.empty_like(image)" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [], "source": [ "laplace_numba_guvectorize(image, laplacian);" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.allclose(laplace_numpy(image), laplacian[:-2, :-2])" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "697 µs ± 150 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "%timeit laplace_numba_guvectorize(image, laplacian);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This approach is even faster. However, it has some limitations: the signature for array sizes forces us to use the same shapes in the input and output. I could'nt use the \"(m, n)->(m-1, n-1)\" signature. Note that we also could have target parallel execution by using the `target=parallel` option in the decorator." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Wrap-up and plots " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Time for a wrap-up and some plots." ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4.62 ms ± 457 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "3.56 ms ± 449 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n", "1.65 ms ± 57 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n", "354 µs ± 14 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n", "578 µs ± 5.66 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n", "635 µs ± 5.76 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "timings = {}\n", "for func in [laplace_skimage, laplace_numpy, laplace_cython, laplace_pythran_highlevel, laplace_pythran_lowlevel, laplace_numba]:\n", " t = %timeit -o func(image)\n", " timings[func.__name__] = t" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "519 µs ± 8.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)\n" ] } ], "source": [ "t = %timeit -o laplace_numba_guvectorize(image, laplacian);\n", "timings['laplace_numba_guvectorize'] = t" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here are the table and the plots." ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "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", "
timings (μs)
laplace_pythran_highlevel354.292226
laplace_numba_guvectorize518.729539
laplace_pythran_lowlevel578.317114
laplace_numba635.353504
laplace_cython1646.003612
laplace_numpy3564.326801
laplace_skimage4624.369004
\n", "
" ], "text/plain": [ " timings (μs)\n", "laplace_pythran_highlevel 354.292226\n", "laplace_numba_guvectorize 518.729539\n", "laplace_pythran_lowlevel 578.317114\n", "laplace_numba 635.353504\n", "laplace_cython 1646.003612\n", "laplace_numpy 3564.326801\n", "laplace_skimage 4624.369004" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.Series({key: timings[key].average * 1e6 for key in timings}).to_frame(name='timings (μs)').sort_values(by='timings (μs)')" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 71, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nX820adOedLy77rqL6dOnj1rrAQccwDvf+U4+9rGP8atf/YrJk3urlp/3vOdx5513Nl33WBiiJUmS\nNKQtt9zyie3NNtvsic+bbbYZjz766IhjJk2a9ESfqhqy7+67784NN9zArFmz+Nu//dsh11dvtdVW\nT3oV3erjrVq16om2U045hXPOOYcHH3yQl770pU8sJXnooYeemJVenwzRkiRJm6ipU6c+sXZ4PB14\n4IF88YtfBOCyyy7j3nvvBXpvA9l666350z/9U0466SQWL178pLEvetGL+OEPf7hW28KFCwG48sor\neeyxxwD40Y9+xKxZs3jXu97FnDlzngjR3//+959Y570+GaIlSZI2Udtuuy0HHHAAM2fO5OSTTx63\n87zvfe/jsssuY++99+brX/86M2bMYOrUqSxbtox9992X2bNn84EPfIC///u/f9LYefPmceWVV67V\ndt555zFnzhz++7//m5/97Gd8+ctf5vTTT2fmzJnsueeebLXVVhx66KEAfPOb32TevPX/+yoy3PS6\ntL7MmTOnFi1aNNFlSJL0jHPrrbfyohe9aKLLGHcPP/wwkyZNYvLkyVx77bWccMIJLF26dMzjDzzw\nQC666CKe85znMDAwwKJFi9huu+3GNPZlL3sZ//Ef//HEOux+Q93/JDdU1ZzRjut7oiVJkjSufvrT\nn3LkkUfy+OOPs8UWW/CpT32qafyHP/xhfvrTn/Kc5zynadzdd9/NO9/5ziED9FNliJYkSdK42m23\n3ViyZMk6j99vv/2e2B7urSBDmT59Oocffvg6n3ckromWJEmSGhmiJUmSJpA/nzYxnup9N0RLkiRN\nkClTpnDPPfcYpJ9mVcU999zDlClT1vkYromWJEmaIDvttBO33347d99990SXssmZMmUKO+200zqP\nN0RLkiRNkM0335xddtllosvQOnA5hyRJktTIEC1JkiQ1MkRLkiRJjfy13xp3Se4HvjfRdWi92A74\nxUQXofXCZ7nx8FluPHyWzww7V9X00Tr5g4V6OnxvLL+DXs98SRb5LDcOPsuNh89y4+Gz3LC4nEOS\nJElqZIiWJEmSGhmi9XQ4e6IL0Hrjs9x4+Cw3Hj7LjYfPcgPiDxZKkiRJjZyJliRJkhoZojWukrwq\nyfeS/DDJKRNdj54syb8k+XmSm/vafivJN5L8oPvzuV17knyse543Jdm7b8yxXf8fJDl2Iq5lU5bk\nt5N8M8mtSW5J8vau3We5gUkyJcn1SW7snuWpXfsuSa7rnssFSbbo2rfsPv+w2z/Qd6y/7dq/l+QP\nJ+aKlGRSkiVJLuo++yw3AoZojZskk4B/Ag4FXgwcneTFE1uVhnAu8KpBbacAV1TVbsAV3WfoPcvd\nun/eApwJvaAGvA/YD9gXeN/qsKanzaPAX1fVi4CXAn/Z/ffms9zwPAy8oqr2BGYDr0ryUuD/AB/t\nnuW9wHFd/+OAe6vqd4GPdv3onv8bgJfQ+2/8E93/l/X0eztwa99nn+VGwBCt8bQv8MOquq2qHgG+\nABw2wTVpkKq6CvjloObDgM902/9/e3fvYkcVx2H8+WkiCAFX4gshK2hhYaedkEaiRIgSUiQQEBWx\n1MJK0VItrMQ/wAhRxLAkgosIEkgsjeILSGITUXQxuEVMVAQh8WtxzobLelcd4e7euzwfWObOmVPM\n5Qs7v5k559wjwP6R9jfTfAzMVdUO4EHgRJILSX4GTvD3wlwTlOR8ks/7519pF+ydmOXM6Zn81ne3\n9r8Au4FjvX11lisZHwPur6rq7UeT/JHkW+Ac7f+y1lFVzQMPAa/3/cIsNwWLaE3STuCHkf2l3qbp\nd2uS89CKM+CW3r5WpmY9Rfor4HuA05jlTOqv/78Elmk3Mt8AF5Nc7l1Gc7maWT9+CdiOWU6L14Bn\ngT/7/nbMclOwiNYk1Zg2l4OZbWtlatZToqq2AceBZ5L88k9dx7SZ5ZRIciXJ3cA87YnjXeO69a1Z\nTqmqehhYTvLZaPOYrmY5gyyiNUlLwG0j+/PAjxt0Lhrmp/5qn75d7u1rZWrWU6CqttIK6LeTvNub\nzXKGJbkIfEQb5z5XVVv6odFcrmbWj99AG6JllhtvF7Cvqr6jDWncTXsybZabgEW0JulT4M4+C/k6\n2qSIxQ0+J/03i8DKqgyPA++NtD/WV3a4F7jUhwh8COypqhv7JLQ9vU3rpI+bPAx8neTVkUNmOWOq\n6uaqmuufrwceoI1xPwUc6N1WZ7mS8QHgZNqPQCwCh/qKD3fQJpF+sj7fQgBJnk8yn+R22jXwZJJH\nMMtNYcu/d5H+nySXq+pp2gX4WuCNJGc2+LS0SlW9A9wH3FRVS7SVGV4BFqrqSeB74GDv/gGwlzap\n5XfgCYAkF6rqJdqNE8CLSVZPVtRk7QIeBb7qY2kBXsAsZ9EO4EhffeEaYCHJ+1V1FjhaVS8DX9Bu\nmujbt6rqHO2p5SGAJGeqagE4S1u95akkV9b5u2i85zDLmecvFkqSJEkDOZxDkiRJGsgiWpIkSRrI\nIlqSJEkayCJakiRJGsgiWpIkSRrIIlqSJEkayCJakiRJGsgiWpIkSRroL3mPta7e6BKiAAAAAElF\nTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "fig, ax = plt.subplots(figsize=(10, 10))\n", "pd.Series({key: timings[key].average * 1e6 for key in timings}).to_frame(name='timings (μs)').sort_values(by='timings (μs)').plot(kind='barh', ax=ax)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**conclusions**\n", "\n", "\n", "So, what have I learned during these last three days? Here are some thoughts:\n", "\n", "- most approaches suggest you rewrite your function in a low-level style if you want a good optimization result\n", "- most approaches rely on the type annotations which you supply and which are crucial for good results (and sometimes it's easy to forget one variable which in turn prevents the optimizer from doing its best)\n", "- pythran, like numba, can in theory optimize high-level NumPy code (in our example, pythran did better than numba)\n", "- pythran yields the best performance in our benchmark\n", "- Cython, contrary to what I expected, comes in after those two (but still yields a good speed-up)\n", "- debugging all code generators is usually frustrating, due to difficult to understand error messages, low-level stuff (try reading the Cython output by clicking the yellow lines) \n", "- numba also allows targeting GPUs, something I haven't spoken about here since I don't have a GPU on my MacBook (this was the topic I had the most difficulty with during the training session since I've never worked with GPUs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**further reading**\n", "\n", "- the resources that we used during the training can be found [here](http://calcul.math.cnrs.fr/spip.php?article284) (in French) - congratulations to the nice people who put in a lot of effort to organize the workshop: [Loïc Gouarin](https://www.math.u-psud.fr/~gouarin/), [Xavier Juvigny](https://www.researchgate.net/profile/Xavier_Juvigny), [Serge Guelton](http://serge.liyun.free.fr/serge/) and [Konrad Hinsen](http://khinsen.net) \n", "- there is a [great numba tutorial on YouTube](https://www.youtube.com/watch?v=SzBi3xdEF2Y) that was offered at SciPy 2016 (and that's going to get repeated at this year's SciPy) by Lorena Barba and Gil Forsyth" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*This post was entirely written using the IPython notebook. Its content is BSD-licensed. You can see a static view or download this notebook with the help of nbviewer at [20170706_OptimizingYourPythonCode.ipynb](http://nbviewer.ipython.org/urls/raw.github.com/flothesof/posts/master/20170706_OptimizingYourPythonCode.ipynb).*" ] } ], "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.6.1" }, "toc": { "colors": { "hover_highlight": "#DAA520", "navigate_num": "#000000", "navigate_text": "#333333", "running_highlight": "#FF0000", "selected_highlight": "#FFD700", "sidebar_border": "#EEEEEE", "wrapper_background": "#FFFFFF" }, "moveMenuLeft": true, "nav_menu": { "height": "144px", "width": "253px" }, "navigate_menu": true, "number_sections": true, "sideBar": true, "threshold": 4, "toc_cell": false, "toc_section_display": "block", "toc_window_display": false, "widenNotebook": false } }, "nbformat": 4, "nbformat_minor": 2 }