diff --git a/.gitignore b/.gitignore deleted file mode 100644 index ce8f01c..0000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -*.pyc -report/index.html -report/*.json -report/images - -*.ipynb -.ipynb_checkpoints diff --git a/.ipynb_checkpoints/Untitled0-checkpoint.ipynb b/.ipynb_checkpoints/Untitled0-checkpoint.ipynb new file mode 100644 index 0000000..9023908 --- /dev/null +++ b/.ipynb_checkpoints/Untitled0-checkpoint.ipynb @@ -0,0 +1,139 @@ +{ + "metadata": { + "name": "Untitled0" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%pylab inline\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.kernel.zmq.pylab.backend_inline].\n", + "For more information, type 'help(pylab)'.\n" + ] + } + ], + "prompt_number": 1 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import json\n", + "\n", + "with open('benchmark_results.json') as f:\n", + " data = json.load(f)" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 12 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "groups = data['benchmark_results']" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 13 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "pairwise_group = [g for g in groups if g['group_name'] == 'pairwise'][0]" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 20 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "def plot_group(group, width=0.35):\n", + " records = group['records']\n", + " labels = [r['name'] for r in records]\n", + " warm_time = np.asarray([r['warm_time'] for r in records])\n", + " max_time = np.asarray([r['cold_time'] or r['warm_time'] for r in records])\n", + " overhead = max_time - warm_time\n", + " \n", + " ind = np.arange(len(labels))\n", + " p1 = plt.bar(ind, warm_time, width, color='g')\n", + " p2 = plt.bar(ind, overhead, width, color='b', bottom=warm_time)\n", + " \n", + " plt.ylabel('Time (s)')\n", + " plt.title(group['group_name'])\n", + " plt.xticks(ind + width /2., labels, rotation=45)\n", + " plt.ylim((0, np.median(max_time) * 2))\n", + " plt.legend( (p1[0], p2[0]), ('Execution time', 'Cold startup overhead'), loc='best')\n", + " plt.savefig(group['group_name'] + '.png')" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 58 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "plot_group(pairwise_group)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "display_data", + "png": "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\noEGDhgrl/wBAf0tfjxGgsAAAAABJRU5ErkJggg==\n", + "text": [ + "" + ] + } + ], + "prompt_number": 59 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "!open pairwise.png" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 61 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [] + } + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/LICENSE.TXT b/LICENSE.TXT deleted file mode 100644 index 1e8a1d6..0000000 --- a/LICENSE.TXT +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2013, python-benchmarks contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index 6cb2193..0000000 --- a/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -WEB_REPO_ALIAS ?= origin - -all: clean run - -clean: - rm -f report/*.json - rm -f report/*.html - -run: - python run_benchmarks.py - -github: - @echo "Publish report to github.io pages" - ghp-import -p report -r ${WEB_REPO_ALIAS} diff --git a/README.md b/README.md deleted file mode 100644 index cab692b..0000000 --- a/README.md +++ /dev/null @@ -1,127 +0,0 @@ -python-benchmarks -================= - -A set of benchmark problems and implementations for Python. - - -Results -------- - -[numfocus.github.io/python-benchmarks]( - http://numfocus.github.io/python-benchmarks) - - -Motivation ----------- - -This repository is the result of a discussion of started by -[@aterrel](https://github.com/aterrel) at SciPy 2013 where people interested in -the development of compiler technologies for the Python programming language -shared design decisions. - -The goal of this repository to gather Python implementations of realistic use -cases where: - -- naive code written with the [CPython](http://python.org) interpreter is too - slow to be of practical use, - -- an implementation of the algorithm cannot be efficiently vectorized using - NumPy primitives (for instance by involving nested `for`-loops) - -Initial use cases focus on **data processing** tasks such as **machine -learning** and **signal processing**. - -For each benchmark, we would like to gather: - -- a naive pure python implementation (optionally using NumPy for large - homogeneous numerical datastructures) run using CPython - -- variants of the Python version that should be able to run the naive pure - Python version with minimal code change: - - - JIT compiler packaged as a library for CPython such as: - - [Numba](http://numba.pydata.org/) or - - [Parakeet](http://www.parakeetpython.com) - - - JIT compiler implemented in an alternative Python interpreter such as: - - [PyPy](http://pypy.org/) optionally with - [NumPyPy](https://bitbucket.org/pypy/numpypy) - - - Python to C/C++ code translation + compiled extension for the CPython - interpreter such as done by: - - [Pythran](https://github.com/serge-sans-paille/pythran) - - [Shed Skin](http://code.google.com/p/shedskin/) - -- pure Python programs that explicitly represent the computation as a graph of - Python objects and use code generation and a compiler to dynamically build a - compiled extension such as done by [Theano](https://github.com/Theano/Theano) - -- alternative language implementations in Cython, C or Fortran with Python - bindings to serve as speed reference. - - -Running -------- - -To run all the benchmarks: - - python run_benchmarks.py - -To run the benchmarks of a specific folder: - - python run_benchmarks.py --folders pairwise - -To run only the benchmarks with specific platforms: - - python run_benchmarks.py --platforms numba parakeet cython - -To ignore previously collected data: - - python run_benchmarks.py --ignore-data - -To see all the tracebacks of the collected errors: - - python run_benchmarks.py --log-level debug - -To open a browser on the generated HTML report page: - - python run_benchmarks.py --open-report - -To publish the generated report to github (assuming you want to push to -origin): - - make github - -Or to another remote alias: - - WEB_ALIAS_REPO=upstream make github - - -Dependencies ------------- - -### Using pip - -- Some dependencies use [llvmpy](http://www.llvmpy.org/) that require to have - llvm built with the `REQUIRES_RTTI=1` environment variable. Under OSX you - can install llvm with HomeBrew: - - brew install llvm --rtti - -- Install the dependencies from the `requirements.txt` file: - - pip install -r requirements.txt - -Note: some packages (pythran and ply) have a depency on SciPy which is -complicated and slow to install from source because of the need of a gfortran -compiler and a large C++ code base. It is recommended to install a binary -package for SciPy (see http://scipy.org/install.html for instructions). - - -### Using conda / Anaconda - -TODO - -### Non CPython dependencies - -You can also install PyPy from http://pypy.org diff --git a/Untitled0.ipynb b/Untitled0.ipynb new file mode 100644 index 0000000..d26c519 --- /dev/null +++ b/Untitled0.ipynb @@ -0,0 +1,221 @@ +{ + "metadata": { + "name": "Untitled0" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%pylab inline\n", + "import os\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.kernel.zmq.pylab.backend_inline].\n", + "For more information, type 'help(pylab)'.\n" + ] + } + ], + "prompt_number": 104 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import json\n", + "\n", + "with open('benchmark_results.json') as f:\n", + " data = json.load(f)" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 105 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "groups = data['benchmark_results']" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 106 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "pairwise_group = [g for g in groups if g['group_name'] == 'pairwise'][0]" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 107 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "def plot_group(group, width=0.5, folder=\"report/images\"):\n", + " records = group['records']\n", + " name = group['group_name']\n", + " labels = [r['name'][len(name) + 1:] for r in records]\n", + " warm_time = np.asarray([r['warm_time'] for r in records])\n", + " max_time = np.asarray([r['cold_time'] or r['warm_time'] for r in records])\n", + " overhead = max_time - warm_time\n", + " \n", + " plt.figure(figsize=(12, 6))\n", + " ind = np.arange(len(labels))\n", + " p1 = plt.bar(ind, warm_time, width, color='g', alpha=0.6)\n", + " p2 = plt.bar(ind, overhead, width, color='g', alpha=0.2, bottom=warm_time)\n", + " \n", + " plt.ylabel('Time (s)')\n", + " plt.title(group['group_name'])\n", + " plt.xticks(ind + width /2., labels, rotation=15)\n", + " plt.ylim((0, warm_time[0] * 5))\n", + " plt.legend((p1[0], p2[0]),\n", + " ('Execution time', 'Cold startup overhead'),\n", + " loc='best')\n", + " if not os.path.exists(folder):\n", + " os.makedirs(folder)\n", + " filename = os.path.join(folder, group['group_name'] + '.png')\n", + " plt.savefig(filename)" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 134 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for group in groups:\n", + " plot_group(group)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "display_data", + "png": "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\niRMnFBMTo65du6pp06Zq166diouL1bt3b9nb2+vEiRPasGGDunXrph49eujAgQPKzc3VJ598Iqnm\nzlVF3VLReejk5KRZs2YpMTFRmzZtUtOmTeXj46PJkyerpKRE+fn5+vvf/67i4mL9+OOP1j8/PXv2\nVJ8+fbRx40YNGDBA3377rQoLCyVJgwYNsv5rfk38RZOgbZCrL2C88vXz588rKytL6enpCgsLU3Bw\nsI4dO6b7779fCQkJevfdd/Xpp5/KwcFBW7du1T333KOUlBTrNvr376+9e/fK29tbDRs2tI7k9erV\nS7/++qtycnJu56ECFbrRD9mWLVuW+5CNjo7WxYsXFRoaKnd3d911112SpEOHDllH8davX69WrVpp\n//79atmypYqKivT9999LuvSh27NnT37hxG13+dqCK6eDXBmuz549q0WLFkm6NB3w//2//6cOHTpo\n5syZmjFjhu655x49+eSTCg0N1eHDh1VSUiJfX1+dOHHCOn/bzc1Nx44d0wMPPKADBw6oe/fu2rRp\nkx5//HHrn5WaGDZw57s691x9HiYmJuqjjz6So6OjHnzwQX3xxReys7OTg4ODTCaTpk+frpdeekml\npaXauXOnQkJCtG/fPuv6TZs2VX5+vtq2bau0tDSdPHlSktS7d28FBgbq119/rZHnPkHbIJfnmF7+\nkM3Ly7O+Pnv2bL3wwgt66KGH1LVrVx0/flwBAQHq2bOnSkpK5OjoqKKiIt13333avXu3unfvrgsX\nLmj9+vWSLl0M1q9fP0mXPnTvuusuXbhwQSaTSd988428vb2r56BRp93qh2zjxo2tH7IzZsxQcXGx\nvvrqK/Xo0UN5eXm6ePGiJKlBgwbav3+/ioqKtGvXLmVlZWn79u2ys7PT/fffr+7du8tiscjZ2Vnz\n589XgwYNbvv3AHWbyWQqNx1EktatW6fk5GRJlx7GNn36dJ0+fVpdunRRWVmZQkJC1Lt3b/Xo0cMa\npn18fGQymXTs2DENHTpU77//vjZu3KgVK1bIyclJnTt31pAhQzR16lT9z//8jxYuXKg333yTJyWj\nWl2de1JTU3X06FFJUnp6ulauXKni4mJFRkaqY8eOeuONN+Tq6qqhQ4dap9G6ubnJxcVF3333nfr3\n769jx47p66+/VnJysj7//HMNHz5cDRo0UJ8+fazXMzg6OurDDz+0/qJZ09TMSzTvANnZ2Vq+fLmS\nk5N1+PBheXl56V//+pd+/fVXNWjQQKNHj1avXr20bt06paSkqHXr1goODtaZM2eUlZUlNzc3BQQE\n6OzZsyooKNDf//53vfvuu4qOjpYkvffee5KkSZMmWU+2y7f946pzVIfLH7KXpaam6sKFC2rbtq31\nQzYoKEiRkZH67LPP9MYbb0iShg4dqqVLl0qSzGazXFxc9O233+qZZ57RL7/8ooyMDLm5ualNmzaa\nMmWKHnzwQTVs2FAzZsyQl5eXTCaTxo4dW66X6925BzBKXl6ejhw5ohUrVujnn3/Whx9+qH/+858a\nPXq0fHx81KhRI/Xt21c7d+5U3759dd999+nIkSPy9vbWH/7wB33yySeKiIiQu7u7XFxctHfvXj34\n4IM6f/68Dh8+rBMnTig8PFyenp6SpK5du6pr167VfNTAJSkpKdq1a5e2bNmiHj166OLFizp06JA2\nbtyoCxcu6Mcff1RMTIzS09OtWaaoqEi9e/dWdHS0zp8/ryZNmsjNzU3fffed6tevr2XLlik6Olo/\n/fSThg4dqnvvvVeStGDBgnL7tlgsslgsNfIzv+Z1dAf473//q+joaKWkpGjMmDFauXKlWrVqpXnz\n5ql+/frauXOn7rnnHjk6Osre3l4//vijTCaT7O3t1bJlS+3cuVOS5OLiosaNG2vHjh3q27evXnvt\nNW3dulUHDhzQvffeK4vFonr16llPsMsjiDXxRMOdLyUlRcuXL9fIkSP1+uuva/ny5XrxxRclyfoh\nO27cOIWHh1vve3r5Q/b06dM6f/68mjZtKnd3d6WkpKhevXpycHDQvn37rCN9EyZM0FdffaX//Oc/\nGjJkiNq3b2/d/9VzYflzgNuptLRUY8eO1auvvqpHHnlEvXv31uLFi+Xp6amff/7Z+i8z999/v7Zs\n2SJXV1e5uLhYR/yGDRtmfRZCs2bN1LJlS5WVlcnLy0vbt29XdHS01q9fb714GKhJ4uPj1blzZ/38\n88966KGHdPjwYRUVFam4uFixsbHy8PBQdna2zp8/L09PT9nZ2Sk5OVn29vby9vZW8+b/v737C2n6\n3+M4/txcbc65aa7Yn9i0nKZzNarBdrPcwEbluljJKpVC+kN0MYi66apICAqtm4QuSoLqpj8Xq2gS\nXXQRXYykIjCjbBFEBmHrIhulOxex70/pcM75cc7ONN+PO3G6z2C+fe3zfX/fn2Xcv38fAIvFglar\nJZPJsHHjRi5fvszw8DC9vb1UVVUpz1n4vwB/XU2ai2RHuwjGx8dJpVKMjIwo4ffo0aN0dHTQ2tpK\nTU0NHz9+pKGhgZaWFtLpNCqVirVr1xIKhRgaGmLXrl1UVVVx8eJFzGYzU1NTSktIoQ+wsHs4F3uS\nxMKSSqXYsWMHiUSCWCzGvXv3cDqdSpENh8P/tMjW19fPKrKxWAyLxcLLly/59OkTp0+fxmw2K+91\ntVpNeXk509PTyu6FfMAUc0FZWRmNjY2MjY3R1taG0+nk+vXr6PV6Xr9+zZcvXzAajTidTq5duwbA\n8uXLefz4MT9//qSlpQWPx8OHDx+w2Wzs27dP+d21tbUlelVC/Geam5v59u0bO3fuZNWqVaxYsYL+\n/n46Ozu5efMmT58+JR6Pk81mqaysZMOGDZw5c4bm5malFapwL1okEiEajQK/8k5FRYWSe2YG6vlw\n/DpA2fHjx4+XehF/mjdv3pDL5WhoaKC6uppcLofJZOLHjx9cuHCByclJurq6qK6upr6+nnQ6zblz\n57Db7Rw4cIBt27ahUqlQqVTo9XrgrxBR2LmWUCHmksWLF9PX18fAwADhcBir1cqdO3eIx+Pcvn2b\n0dFRPB4PTU1NGI1G0uk0w8PDjI2Nkcvl0Ov1ZLNZAoEAdXV1bN68GYPBwJIlS9DpdL89X+FvQD5k\nirmkrKyMVCrF3r17KS8v58mTJ2i1Wt69e0dFRQV2u50HDx5w9epVdu/eTVVVFTqdDpfLhVarpbOz\nk8rKylK/DCH+NpPJRCqVYvXq1bhcLjQaDY8ePaK1tRWr1cqxY8ew2Wx0dXUBv8awPn/+nImJCcLh\nMNFolEAgQD6fV+5xmHmlfj7XfElrRWC325menlYOENBqtXz+/Jn9+/cTjUZ58eIFdXV15PN56urq\nOHnyJK9evWLPnj3odLp/GaLn45tM/PkcDgc+n08ZNVlbW4vRaMThcNDe3k5/fz+ZTEbpLe3t7cVg\nMJDJZLDZbBw5coTDhw+Tz+eVk00LU0tkVJmYL3w+H9+/f+f9+/fo9XqWLl3K169ficfjDA0N4fV6\nMRgM3LhxA7PZzPr16+np6cFoNJZ66UL81wKBAJcuXQJ+tXVks1mWLVtGW1sbiURCGccH4HK56Ovr\n4+zZs7hcLuVnZmacPyXvSOtIEVgsFkKhEKdOnWJkZIRnz57R1NTEwMAAW7ZsIZlMMjk5qUxF0Gg0\nysSGuXqEqBD/TqHIbtq0aVaRdbvdJBIJRkdHlccWiuxMU1NTsy4FztzJEGI+KNzIlUwmOXToECtX\nrtMru3oAAAFsSURBVGRiYoJQKER7e/us/lIh/jShUIiOjg5OnDjB3bt38Xg8SojWaDREIpHfhjUU\nwrVarZ43rSB/l6S6Itm6dSsOh4OHDx/S3d3NunXrGB8f5+DBg0Qikd9Gj6lUKgnZYl6TIisEbN++\nnUWLFgEQDAYJBoMlXpEQ/x9+v581a9ZgtVoZHBzE7XYDcOXKFc6fP8+tW7dQq9WzWkIWQt2XZFdE\nXq8Xr9erfP327VuCwSCxWKyEqxKiOKTICgE9PT2lXoIQJVFTU4PJZEKn0+F2u8nlcmi1WhobG0km\nk8pZBwvtKqUE7SKbOc/X7/fj9/tLvCIhikOKrBBCLGzxeFyp8YUDZHw+n/L9hVj/VXm500gI8T8y\nODiIRqOhu7u71EsRQgghSk6CthBCCCGEEEUg4/2EEEIIIYQoAgnaQgghhBBCFIEEbSGEEEIIIYpA\ngrYQQgghhBBFIEFbCCGEEEKIIpCgLYQQQgghRBH8AzPB1yJLuHkxAAAAAElFTkSuQmCC\n", + "text": [ + "" + ] + }, + { + "metadata": {}, + "output_type": "display_data", + "png": "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\neLAcHByUnJysxMTEiw7akup96+6L6WexWK6KwFheXn7Zt8mt1gEAaNwYOnKFOHr0qObOnau33npL\nI0eOVLNmzWRra6vhw4dr/vz5kqQ///xT06ZNk5eXl7y8vPTYY4+ptLS02vXt2LFDN998s1q2bKlR\no0bp1KlTNW47MzNTAwYMkLOzs1q3bq3Ro0dLkvr37y9JCgkJUYsWLbRmzRoVFxfrL3/5i9q0aSNX\nV1eNGDFCeXl51nWFhobqmWeeUd++feXo6KgHH3xQX3/9taZMmaIWLVooOjpaWVlZsrGxUUVFRZV+\n7733nqTTQzRuvfVWPfroo3J2dlZQUJA2bdpUY/179uxRaGioXFxc1KVLF3366aeSpK1bt8rDw6NK\nYF27dq1CQkIkSRUVFZo3b578/f3l5uam+++/X0eOHJEka42LFy+Wr6+vBg4caP2D4YknnpCrq6s6\ndOig5OTkKu9hVFSUPD095e3trTlz5lj3cd++fbr99tvl5uam1q1b64EHHtDRo0fr9X4BAIDGgaB9\nhfj+++916tQp3XnnnTW2efHFF5WWlqadO3dq586dSktL0wsvvHBOu9LSUo0cOVKRkZE6cuSI7r33\nXn300Uc1nlmeM2eOhgwZouLiYuXl5enRRx+VJKWkpEiSdu3apWPHjunee+9VRUWFoqKitH//fu3f\nv1/NmjXTlClTqqzvP//5j9555x0dP37cOq75X//6l44dO6Y333yz2hrOHiqRlpYmf39/HT58WH//\n+9911113WUPwmcrKyjRixAgNGTJEBw8e1D//+U+NHTtWGRkZ6tWrlxwdHbVx40Zr+5UrV2rs2LGS\npH/+859KTExUSkqKCgoK5OLiokceeaTK+lNSUvTf//5XGzZskMVi0datWxUYGKjDhw/rySefrDIc\nZty4cXJwcNC+ffu0Y8cOff7553r33Xetrz/99NMqKCjQnj17lJOTo5iYmHq9XwAAoHEgaF8hDh8+\nLDc3N9nY1PyWrFy5Us8++6zc3Nzk5uamuXPnasWKFee0S01NVXl5uaZOnSpbW1vdfffd6tGjR43r\ndXBwUFZWlvLy8uTg4KBbbrmlxraurq6688471bRpU1133XV66qmntGXLFuvrJpNJ48aNU1BQkGxs\nbGRnd3p00oUOg2jTpo21/vvuu0+dOnXSZ599Vu2+njhxQrNmzZKdnZ1uu+02/eUvf9HKlSslSaNH\nj1Z8fLwk6dixY1q/fr31jP2iRYv0wgsvyNPTU/b29po7d64+/PDDKmfaY2Ji1KxZMzVt2lSS5Ovr\nq6ioKJlMJj344IMqKCjQ77//rgMHDmj9+vV6/fXX1axZM7Vu3VrTpk3TqlWrJEnXX3+9Bg4cKHt7\ne7m5uemxxx6z/twu9P0CAACNA0H7CtGqVSsdOnSoSsg7W35+vnx9fa3L7dq1U35+frXtvLy8qjzn\n6+tbY9hdsGCBLBaLevbsqS5dumjJkiU11nDy5ElNnDhRfn5+cnJy0oABA3T06NEq665u9pMLPTtb\nXf017evZ2/P19bUOZxk9erQ+/vhjlZaW6uOPP1a3bt2s7bOysnTnnXfKxcVFLi4u6ty5s+zs7HTg\nwIEa96Vt27bWx82bN5ckHT9+XNnZ2SorK5OHh4d1fZMmTdLBgwclSQcOHNCoUaPk7e0tJycnRURE\n6PDhw9Z9uJD3CwAANA4E7StEnz591KRJE61du7bGNp6ensrKyrIu79+/X56enue08/DwqDJuWpKy\ns7NrDLvu7u6Ki4tTXl6eFi1apIcffli//vprtW0XLlyovXv3Ki0tTUePHtWWLVusFz1WOns7Zy87\nOjpKOh3aKxUWFlZpU139Z4dR6fTPJCcnp8r2s7Oz5e3tLUnq3LmzfH19tX79eq1cuVJjxoyxtmvX\nrp2Sk5N15MgR67+TJ0/Kw8Ojxtpr4uPjoyZNmujw4cPWdR09elS7d++WJD311FOytbXVzz//rKNH\nj2rFihXWP6ou9P0CAACNA0H7CuHk5KTnnntOjzzyiBISEnTy5EmVlZVp/fr1mjlzpqTTZ2dfeOEF\nHTp0SIcOHdJzzz2niIiIc9bVp08f2dnZ6c0331RZWZk+/vhjbdu2rcZtr1mzRrm5uZIkZ2dnmUwm\n6xAWd3d37du3z9r2+PHjatasmZycnFRUVKS///3v56zv7DOxZ6+jdevW8vLy0ooVK2Q2m7V48eIq\nr0vS77//bq1/zZo1+t///qdhw4ads63evXurefPmWrBggcrKyrR582atW7dOo0aNsrYZM2aM3njj\nDX399de69957rc9PmjRJTz31lPbv3y9JOnjwoBITE2v8OZ2Ph4eHBg0apOnTp+vYsWOqqKjQvn37\nrOPcjx8/LkdHR7Vs2VJ5eXl65ZVXrH0v9P0CAACNA0H7CjJ9+nS99tpreuGFF9SmTRu1a9dOb731\n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\n27evYmNjdf311zdIvcCFqqiokMVisR7jZrNZtra2slgs+umnn7R69WrdeuutGjFihNatW6fMzEx9\n8MEH+vXXX2Vra6tBgwY18B4Al151eafy8a5du5ScnKw777xTAQEBSklJkdls1jvvvKOAgICLGlJl\nGxMTE3NRlaNRqaioqHLW7sy/4ipvDPT+++/rjTfe0ObNm9W+fXv94x//kI+Pj06ePKktW7Zo27Zt\nKi0t1ZEjR+Tm5iZ7e/uG2h3ggp195uKXX37RJ598ojlz5mjlypX66quv1KpVK5WUlCgjI0MeHh7q\n2rWrbG1t1bRp0zrfjAu4XCq/lam8iZvJZLIe4ydPnlSTJk302WefaeDAgaqoqNCJEyeUlpam3Nxc\nPf7440pJSVFOTo769++vmJgYPf744w28R8DFO/tmh2d/9kvSa6+9pvfff1+JiYk6cuSI1q5da70b\n+bZt23T48GHZ2Njo+PHjNd63pTYE7avYqVOnZGd3+kuLygOuuq/GZ8+erblz5+rUqVPq3Lmzjh07\npri4OD355JN66KGHZLFYtG3bNt1+++3q1q2bnJyclJqaqlWrVslsNqt79+4NsXtAjcxmsywWS5UP\nVYvFotLSUq1fv14LFy7UyZMn1aVLF6Wnp+uFF17QwIEDFR8fr9LSUn322WcaMGCAmjZtqi1btigt\nLU3/+Mc/1Lx5cwUHBzfgngGnnXnSpDJYm0wmFRcXq6ysTDNnztSsWbO0Z88eDR8+XM2bN9dzzz2n\nV199VRMnTlSHDh303HPPKTIyUv3799eMGTPUvHlzXXfdderWrZscHR0beA+B+jGbzdbfhzNt375d\nzz77rGJjY2UymdS1a1ft2rVL8fHxmjdvnqZNm6aCggKtXbtWMTExMpvN+vPPP/XVV19Zv91s27bt\nBdfDGO2r1J49e/TXv/5Vubm5kk5/EJeUlGjt2rX66aefrO0+/PBDderUSZ9//rl++eUXPf3007rx\nxht16623qqysTJJ0++236/DhwyovL9ett96qiIgIvfrqq+rfv79atGjRIPsHnKmoqEjPPPOMdayp\nra2t9avy33//XdLp34FVq1bp9ddf1w033KCvvvpKf/vb39SvXz+FhITIxcVFkjR8+HC1aNFCBw4c\n0AMPPKD//Oc/evvttzV27Fjt2rVLpaWlDbafuHZZLJZzLk6vtGPHDsXHx6tv377q06ePFixYoMDA\nQH3++efatWuXPvroI3l7e8vNzU3NmzeXJN18883y8PDQ5s2b5ebmpgkTJujFF1/UyZMn1aZNGy7+\nRaOxbt06PfXUU9Y7ild+9m/dulV79+6VdHrM9dKlSxUQEKDp06dr48aNmj9/vkaMGKE2bdrI3d1d\nkvTggw/qxx9/lL29vR544AE9/vjjiouLU7du3XTkyJF61UfQvkq1bNlSHh4eSktLk3T6QAwNDdW7\n776rhQsXasGCBTpw4IDS09M1YcIEeXh4aPr06UpJSVHTpk3VqlUr/fjjj5KkTp06acuWLWrVqpW+\n+eYb3X333erZs6fS0tIUGhragHsJnFZeXq78/Hx98803kqTs7GxFREQoMDBQ0dHRWrVqlSwWi5KT\nkzV79mxNnTpVTz31lDZt2qQ//vhDfn5+OnnypCoqKuTh4aHt27fLwcFBOTk5WrJkiSZNmqS3335b\nAwcOlIODQwPvLa4FZrO5yuwgZw4HkU4PeZo7d64k6Y033lBcXJzeeOMNrV+/XrGxsWrXrp3atGmj\n4cOHWz/Lb7/9dsXFxUk6/Y1nmzZtrOscN26cxo8fr0OHDl2uXQQuSuUfg02aNNGxY8e0f/9+SdL6\n9esVGBiomTNn6u9//7s2bNigoqIirVu3TjNnztSQIUM0ffp0xcfHy9PTU3Z2dvr5558lSW3atJGt\nra1yc3O1adMmRUREqFu3bjp+/Lg6duxYrzoJ2o1U5cUulc6elszFxUWdOnXS1q1bJUkbN27U1KlT\n9dlnn+mxxx7TO++8oyZNmig3N1eOjo4qLy/XDTfcoKKiIpWUlOiGG27QmjVr9Oqrr2rMmDG64447\n1Lp1a/n6+io6Olpff/21kpKS5OnpeVn3G9cmi8Uis9lc41k2Z2dn9ezZ0zpbwrfffqtmzZrp559/\n1owZMzRjxgz98ccf2rdvn9q3b6/S0lK1a9dOzZs3V0ZGhm6++WatXLlS69at03fffScnJyd5eXnJ\nbDZr//79uvnmm5WUlKQ77rjjcu42rmGV38qc6Z577tGePXskSQcPHtTu3buVnZ2tQYMGqXXr1vL0\n9JSfn59Gjx5t/V248cYbVVhYqIMHD2rs2LF67733tGzZMj3wwAM6fvy4hg0bJklq3ry5nJycFBYW\nds6wK6ChnO+zv3JoSOfOnWVvb6+srCyZzWa9++67WrZsmTZv3qw777xTzz//vJydnWVvb2+dPcTX\n11ctW7bUgQMH1LNnT7366qv6z3/+o4iICA0fPlw+Pj5ycnLSiBEj9MknnyghIUFeXl71uqcCv0mN\ngNlsPuemGZXjj/Ly8rR169Zz5vlt1qyZbrjhBmVmZkqStm3bph49eqisrEw333yz7OzsVFRUpJtu\nukn//ve/ZWdnp9zcXPXs2VOS5OXlpYEDByo/P19hYWGaN2+eHBwc5OPjowEDBui66647Z95J4FI5\n+2tyk8kkW1tb2djY6OTJk9Y2lRwcHBQYGKi8vDxVVFQoMTFRgwYNkr29vXr06KF27dpp9+7d6tq1\nq9auXWs9K3399deroKBAHTt2VHBwsJYvX66YmBg98MADuv766+Xn56e5c+fq//2//1fvD1ngQh0/\nflwbNmzQmDFjNH78eOsZ6aKiIq1Zs0aS5OPjI19fX23fvl3BwcG67rrrdPjwYUlS//79rdNR3nTT\nTSoqKlJaWprCwsJkZ2enP/74Q0OHDtWbb75p3WZcXJxefvll9e7dmwt+0WAq53mv/Kw987P/xIkT\n2rdvn7Vt5XHq5eUlV1dXZWVlydbWVrt27bIOBbznnnvk4OCgjIwM3XTTTVq8eLEk6aefflJAQICc\nnZ0VEhIiR0dH/frrr+rUqZOmTZsmSerWrZvuu+8++fj4WP9Pqs/vBkH7CrR3717NnDlTq1atknT6\nzEblTTMkqaysTGvXrtWMGTM0ZswYffnll5KqjtkzmUy6/vrrderUKR05ckReXl5KS0uzzhDi6+ur\nH3/8UXPnztWhQ4fUt29f3X777QoNDVXbtm3l6+srBwcH3XrrrRo/frxat25tXXflL0B1V/AC9ZGe\nnm4d9mE2m8/5mjw3N1effvqp7rrrLj344IP6888/z/nAa9eunRwcHJSVlSV3d3fl5eVZX+vatau+\n+OILzZgxQ+np6Zo0aZJGjhypFi1aaNiwYXJycpKPj4+GDx+uzz//XA8++GCV2XgqP/gJILgYZw8H\nqU56erqmTp2qhQsXKiIiQm5ubnr22WclSVFRUfrss88kSa6urrr++uu1bds2BQYGqry83DpGtVev\nXvrpp59UUlKitm3bql+/fmrdurWaNm0qT09PBQYGKioqSp6entZ6+vTpo++++07dunXjD0pcNtnZ\n2Xrrrbe0efNmSf83z3vlZ63FYtHixYv1+uuv67bbbtPnn3+u8vJya//KY9XX11eHDx/WoUOH1KdP\nH23YsEGS9Oeff8rLy0slJSWaNGmSfvzxRw0ZMkTR0dHq2rWrmjRpou7du6u8vFwPPfSQnnnmGfn6\n+lrXXzl64Oz/ky4E82hfYUpKSjR//nx17NhRffr0kXT6wsbVq1dr9+7deuKJJ9S7d29lZmbq008/\n1YYNG9S+fftq19WmTRt5eXnp+++/10MPPaS4uDhVVFTo5MmTcnV1Vb9+/eTu7q5nn31WmZmZuumm\nm6wHkq+vr1xcXFRWVqby8vIqBz5hA5dKWVmZFi1apOXLlysqKkp9+/aVra2t9u7dq82bN+uOO+5Q\nhw4dlJCQoHfffVeTJk3SxIkTJZ07dVOrVq3Uvn17paSk6L777tPLL7+sbt26KSQkRLa2tgoODlZQ\nUJBefvllLV68WGFhYdb5gj08PGRra6v9+/frxIkTatasWZWp0s7+Ch+oj/MdR5XHc9u2bdW0aVO5\nuLho6NCh6tKliyZNmqT09HQNHz5cDz/8sKTTwwNzcnKUlZUlOzs7OTo6aufOnRowYIDat2+vZ599\n1nrh7vTp063bGTRokFJTUxUaGqqKigprTWfOpsNnPC6HkydPaty4cbr99tvVrl07SVJWVpYSExP1\n22+/6eGHH1ZAQIC++OIL5eTkaOXKlfL396+yjsrfm44dO2rr1q3av3+/Ro4cqQULFmjQoEFKSUlR\nWVmZevfurWbNmqlz587atm2b+vXrJycnJ0mSv7+/LBaLMjIyrNctVP4OXIqTiUzvd4Vp0qSJoqOj\n1bt3bx06dEjXX3+9nnnmGZlMJg0dOlTPPfec2rZtqy5duig7O1s33XST9azE2QeEnZ2dsrKytHnz\nZj322GPy8fHR0qVLVVJSooiICHXt2lWSrGc5TCaT9Wyira2tQkND1aVLl2qnyQEuVuUNNZ5++mnN\nnj1bvXv3lrOzs/7xj39o7ty5OnHihNavX68mTZqob9++2rJli+644w517NixxuP90KFD+uqrrxQd\nHa0mTZpowYIF+ve//y0PDw9FR0fLzs5O1113nfr166fOnTurSZMm1q8DO3XqpEGDBql58+bVToUJ\n1MWZZ8Ck/5tq7Pfff9e2bds0efJkrV27Vv7+/vL09Kwy/7V0+v+AAwcO6MSJExo4cKBcXV31ySef\nyM3NTd27d9cHH3ygiooKFRUV6dtvv9XBgwd16623qmPHjgoKCpKPj49MJpN69OhhnWFEOn3BsI2N\n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\nXKB3795cunSJ06dPc/nyZQ4fPsywYcOwtrYmPDxcb+u2trb8/e9/13fcrays5OjRo/zhD3+gd+/e\nfPrpp8Bz3P8/2UyVZ8/PzcdbsGCBJCUlSWVlpfTp00fS09P1xyYnJ4u/v7+EhobK3r175Z///Gej\nx9byUz/44APx9fWVlStXyqVLl8RoNDbVy1UUKSgokKVLl0pcXJx0795dhg0bJtXV1VJRUSHz58+X\nvXv3SmlpqfTp00cyMzOlurpaDAaDtG/fXm7evCkiIllZWRIZGSm3b9+W48ePy5gxYyQwMFCCgoLk\n22+/FRGps16gdm7d6dOnJSwsTEJCQmTOnDly/PhxlWetPDVhYWGyd+9eERG5efOm/Pa3v5UTJ07I\n1q1bxc7OTuLi4vTHZmdny4wZM2TatGmSnZ2tf792+679f0V5luTm5kpKSooMHz5cEhMTZcGCBTJ0\n6FAREcnMzJSXX35ZRGpiIQcHBxERMRgMkpubK76+vnLv3j0RqYlZpkyZIg8fPpT9+/dLdHS0dOvW\nTebNm6ev7WnMgwcPZO3ateLl5SVz5syRL7/8UsrKypr4VT99L9xWUdqW5Lt27SIkJITy8nIyMjLY\nsWOHno+3Zs0a8vPzWbZsGfBDPt6yZcv0fLy2bdty4cIFmjVrhq2tLV9//TXdunWjWbNmxMfHM378\n+EZzR7UyTvDD3VtcXNyzu1pWea5UVFSwbNkyHj58SExMDDNnzuTDDz8kMTGR2bNnc+TIEWJjY7Gz\ns8PCwoKsrCw8PT2xsLDAw8ODI0eOMGbMGJycnGjZsiVpaWmMGjUKNzc3LCwscHFxAX7YXl1qVejR\ndOrUiZ07d9bZaENRnpbQ0FD+9re/MXDgQB49esTdu3dp06YNPj4+TJ06laysLP2xnTp1YsWKFXV+\n/9GjR3VGqdUspPIs2rdvH6+//jpTp05l+PDh/OMf/8Dd3V1Pk4qKimo0Tapjx4510qSGDx+Os7Mz\nOTk5eppUz5499U31aqt/bWhpUlolqRfFCxVoP+6GlpmZya1bt0hMTMTJyUlvUKamplhbWzdaE7Wx\nqZHndrpEeeYUFRWxb98+Ll26pLfJt99+m5EjR9K7d28cHR0pLCykc+fO+Pr6kp6ejomJCYGBgURG\nRrJ//37GjBmDvb09H374IU5OTjx69Ah3d3eg7tbm0HjQUXvTDUV52iIjIxk5ciQLFy5kz549dO3a\nlU6dOgE1G4T179+/zgAJ/LABmJYGpSjPutppUl5eXnTo0IGkpCQ9TSojI0NPk2rZsqWeJtWlSxcC\nAgIapEkNHjwYoE6alFbrXbtWVJpUjWYLFixY8LRP4kmxsLBgxYoVJCcnExUVhYuLC7t37yYmJoZd\nu3aRlZVF165d8fb2xtbWlvT0dM6cOcPVq1cxGAzY2Nhw9+5dQkND8fDwYNCgQbRo0QIHB4dGV79q\nDU6NcCjPiitXrmAwGOjcuTOtWrXCYDBgZ2dHZWUl69evp6KigtjYWFq1akXHjh1JT0/n/fffx9XV\nlfj4eKKjo/W1A9qCLa1Tlf9f1KtuHJVfEkdHR9LS0ggPD2fy5Mn87ne/A2Dz5s0sXryYiRMn4ubm\nVmcjG9WvK780dnZ27Nu3Dz8/Pzp16oSZmRlffvklvXv3xsXFhblz59K2bVtiY2MBCAgI4Pz585SU\nlBAVFcXgwYMJDQ1FRPSiDbWvCRXv/LgX6hPRzc2NHj16kJubC0D79u2xtbXFzc2NV199laSkJPLy\n8mjXrh1Qs6NXixYtyMvLo23btsyaNYsZM2YgIlhYWADUKc+nKM86V1dXqqurOXDgAFAzunDnzh3e\nfPNNBg8ezIULF/Dw8EBE8PDwYNGiRWRnZzN+/HisrKz+bRCtOljll8jR0RE7OzusrKzw8fHRS1B6\nenqSmppKWFjYj+4WqSi/JFqaFFAnTapv375MnTpVL8cHP6RJrVy5Up/h0WZyNOqa+O+8UKkj0HT5\neKrBKb8Ezs7OREZGsnTpUi5dusS5c+fw9vYmOTmZV155hdTUVCoqKvT1BWZmZnrlBG0UQ1GeNzEx\nMXofrk1t9+jRQ/+56t+V54FKk3o6XrhPTtXQlBfdkCFDcHNz49ixY4wbN46goCCKioqYMGEC/fv3\nb7CI18TERAXZynPtN7/5zdM+BUVpciEhIfj7++Pi4kJKSgo+Pj5ATZrU2rVr+eyzzzA1Na0zg6Ni\nnv/dC/fpqRqaotTk3wUEBOhf5+bm0qtXL4YPH/4Uz0pRFEVpKo2lSVlaWuppUto+H2oG5/F64QJt\n1dAUpYa2iYapqSkhISGEhIQ85TNSFEVRmpJKk3ryTOQFXMWXkpKCmZkZ48aNe9qnoiiKoiiKojyn\nXshAW1EURVEURVGa2gtV3k9RFEVRFEVRnhQVaCuKoiiKoihKE1CBtqIoiqIoiqI0ARVoK4qiKIqi\nKEoTUIG2oiiKoiiKojQBFWgriqIoiqIoShP4P6g0bnwdxQYSAAAAAElFTkSuQmCC\n", + "text": [ + "" + ] + }, + { + "metadata": {}, + "output_type": "display_data", + "png": "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\nyJEjJUm33nqrJMnNzU3NmzdXRkaG5syZo379+lnbf/fdd+rRo4fc3NzUs2dPff/999bXIiMj9fLL\nL6tv375q3ry5oqKidOjQoQuO6+TJk4qOjtaePXvUrFkzNW/eXHv37q1US25urhwcHDRnzhy1adNG\nLVu21AcffKAffvhBXbp0kbu7u5599tlK2501a5bCwsLk4eGhgQMHavfu3bXreAAAgFoiUNtJdSPC\n06ZN09atW/XRRx9p3bp1mjVrlubOnStJ+utf/6qcnBz99NNPysnJUWFhoV599VVJUmZmpkaNGqW3\n335bxcXFWrt2rdq2PTsibzKZKn1RyLmP161bJ0kqLi7WsWPH1Lt370r1HD58WIMHD9bYsWN1+PBh\njRs3ToMHD670TZQLFizQnDlztH//fpWUlOjvf//7BcfVpEkTpaWlydfXV8ePH9exY8fk4+NT5ReY\nZGZmKicnRwsXLtSYMWP0+uuva/Xq1fr111+1ePFirV27VtLZXyDeeOMNff755zp48KD69eun4cOH\n19z5AAAAVxCB2g4sFovuueceubu7W//NnDlTkuTq6qp58+bpueee08iRI5WcnCxfX19ZLBZ9+OGH\nmjZtmtzc3NS0aVONHz9eCxculCTNnDlTcXFx6t+/vyTJ19dXHTt2rHb/VT2uyldffaWOHTtqxIgR\ncnBwUGxsrEJCQrR8+XJJZ8P5o48+qqCgIDVq1Eh/+tOftGXLlhr3e7HnXnrpJbm4uOjOO+9Us2bN\n9OCDD8rT01O+vr7q16+fdfsffPCBxo8fr44dO8rBwUHjx4/Xli1bKs3RBgAAsLVrZg51fWIymbRs\n2bJq51D37NlT7du318GDBzV06FBJ0oEDB3Tq1Cl169bN2s5isai8vFySVFBQoMGDB1/xWvfs2aM2\nbdpUeq5t27bas2ePdbl169bWx66urjpx4oShfXp7e1fa3vnLFdvPy8vTmDFj9Pzzz1dav7CwUAEB\nAYZqAAAAuFSMUNdD//rXv1RSUiJfX1+99dZbkiRPT0+5urpq27ZtOnLkiI4cOaKjR4/q2LFjkqSA\ngADl5ORUub0mTZro5MmT1uWioiLr46qmXJzLz89PeXmVL7jMy8uTn5/fZR9XVfuqaf8X06ZNG82Y\nMcPaH0eOHNHJkycvmLYCAABgSzYN1GlpaQoJCVFwcLCmTJlSZZvRo0crODhY4eHhysrKsj5/9OhR\nPfDAAwoNDVVYWJgyMjJsWWqdq26qxc6dO/XSSy/pk08+0dy5c/XWW2/pp59+koODg5544gmNHTtW\nBw4ckHR2JLbiwsO4uDjNnj1bq1evVnl5uQoLC7Vjxw5J0o033qiFCxeqrKxMmzZt0qeffmoNsl5e\nXnJwcNCuXbuqrCc6Olo7d+7UggULVFZWpkWLFum3337TXXfdVeOxnM/b21uHDh2y/hJwOeueq2Kd\np556Sq+//rq2bdsm6ew88CVLllz29gAAAIyw2ZQPs9msxMREffPNN/Lz81OPHj0UExOj0NBQa5vU\n1FTl5OQoOztbGzduVEJCgjU4jxkzRoMGDdLSpUtVVlZWaYS1Nnxa+lzWre1qs/3LMWTIkEr3oR4w\nYIAWL16skSNH6q9//as6d+4sSXr99dc1cuRI/fjjj5oyZYpeffVV9e7dWwcPHpSfn5+efvppDRgw\nQD169NDs2bP13HPP6X//+5+8vb313nvvqWPHjvrb3/6m4cOHy93dXRERERoxYoQOHz4sSWrcuLFe\nfPFF3XLLLSorK9PKlSsrXcTYsmVLrVixQmPGjFFCQoKCg4O1YsUKeXh4WGs//4LH6kadQ0JCNHz4\ncLVv317l5eX69ddfL3rBZHUq2txzzz06ceKEYmNjlZeXpxYtWmjAgAHWaTIAAAB1wWSx0Q2Iv//+\neyUlJSktLU2S9Oabb0o6e6eKCk899ZRuu+02DRs2TNLZwLVmzRo1atRIXbt21e+//37x4k2mKkc4\nq3seaCgu5f/w12u/lmeQZx1VdGUdzDmoqFvr5ts4baEh973U8Psf9jVw2ECbfq+DLeXNy1PaojR7\nl1FrDbnvpYbf/xc7N9tshPr8C8P8/f21cePGGtsUFBTI0dFRXl5eevTRR/XTTz+pW7duevfdd9W4\nceML9jNp0iTr48jISEVGRl7xYwEAAMC1JT09Xenp6ZfU1maB+lIvNjs/6ZtMJpWVlWnz5s1KTk5W\njx49NHbsWL355pvWey6f69xADQAAAFwJ5w/UJiUlVdvWZhcl+vn5VbofcH5+vvz9/S/apqCgQH5+\nfvL395e/v7969OghSXrggQe0efNmW5UKAAAA1JrNAnX37t2VnZ2t3NxclZSUaNGiRYqJianUJiYm\nxvotgBkZGXJzc5O3t7dat26tgIAA7dy5U5L0zTffqFOnTrYqFQAAAKg1m035cHJyUnJysqKiomQ2\nmxUXF6fQ0FClpKRIkuLj4zVo0CClpqYqKChITZo00ezZs63r//Of/9SIESNUUlKiDh06VHoNAAAA\nqC9s+k2J0dHRio6OrvRcfHx8peXk5OQq1w0PD9cPP/xgs9oAAACAK4FvSgQAAAAMIFADAAAABhCo\nG5j09PRK9+4+3yOPPKKXXnqpDiu6+syZM0f9+vWrk33xfgEA0PDZdA51ffL9pu917NQxm22/eePm\nurn7zZfcfv78+Zo2bZp27NihZs2a6cYbb7R+BbgRF/vq74txcHBQTk6O2rdvX+t9R0ZGauTIkYqL\ni6v1Nq41tX2/AABA/XHNBOpjp47Z9KuCD+YcvOS206ZN05QpU5SSkqKoqCi5uLgoLS1Ny5cvNxyo\npQu/LKcu1rNYLFdFMCwrK6vzfda23wEAQP3AlI86VlxcrFdeeUXvvfee7rnnHrm6usrR0VGDBw/W\nlClTJEl//PGHxo4dKz8/P/n5+em5555TSUlJldvLysrSTTfdpObNmys2NlZnzpypdt85OTmKiIiQ\nm5ubvLy8NHz4cEnSrbfeKunsnVWaNWumJUuW6OjRo7rrrrvUqlUreXh4aMiQISosLLRuKzIyUhMn\nTlTfvn3VpEkTPfzww1q3bp0SExPVrFkzjR49Wrm5uXJwcFB5eXml9WbOnCnp7NSKW265Rc8++6zc\n3NwUGhqq1atXV1v/9u3bFRkZKXd3d91www368ssvJUkbN26Uj49PpWD6+eefKzw8XJJUXl6uN998\nU0FBQfL09NSwYcN05MgRSbLWOGvWLLVt21b9+/e3/mLw5z//WR4eHmrfvr3S0tIqvYdxcXHy9fWV\nv7+/XnrpJesx7tq1S7fffrs8PT3l5eWlhx56SMXFxbV6vwAAQMNAoK5j33//vc6cOaN777232jav\nvfaaMjMz9dNPP+mnn35SZmamJk+efEG7kpIS3XPPPRo1apSOHDmioUOH6tNPP612pPill17SwIED\ndfToURUWFurZZ5+VJK1du1aS9PPPP+v48eMaOnSoysvLFRcXp927d2v37t1ydXVVYmJipe19/PHH\n+vDDD3XixAnrvON//etfOn78uKZPn15lDedPccjMzFRQUJAOHTqkpKQk3Xfffdawe67S0lINGTJE\nAwcO1IEDB6z3Kc/OzlavXr3UpEkTffvtt9b28+fP14gRIySdvaf58uXLtXbtWu3du1fu7u565pln\n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\npTYxMTGaO3euJCkjI0Nubm7y9va+pHUBAACA+sBmI9ROTk5KTk5WVFSUzGaz4uLiFBoaqpSUFElS\nfHy8Bg0apNTUVAUFBalJkyaaPXv2RdcFAAAA6huThYnIAAAAQK3xTYkNSHl5ucrKyrgYs4Ezm80y\nm832LgPnsFgsvCf1kNls5vPOBsxms8rLy+1dBsT5oK7URT8TqOux808kDg4OcnJykslk4sOwgagI\naue+l46OjnJ0dJTZbNbvv/9ux+pQwWQyydHR0d5lQGd/Zio+3xwdHS/5jlGomsViUVlZWaVzhqOj\noxwcHHTkyBFt3rxZx48ft2OF15bzz+sV5wNJ+t///qfS0lJ7lHVVsdd5l0Bdz5SXl1s/+M4/kXz3\n3Xd6/vnnFRERoQ0bNtijPFyiih/kiqB27nv5yy+/KDo6Wp06ddLUqVN14sQJe5V5TSkvL79gZK7i\nfcrLy1NycrLeeecdHTx40F4lXnMqwt65Jz6TySQHBwcdPnxY69evV1JSEiN4BphMJjk5OcnB4f9O\n91lZWYqKilKfPn308ccf68iRI3as8Op2frg791xgsVi0ePFiDRkyRM8995yGDh2q7777zl6lNnj2\nPu8SqO3s/D9DODg4WD/4srKytGPHDlksFp0+fVpTp06Vr6+vkpOT1a1bN3uVjPOcPwJUXl5u/UE+\nevSoUlJS9Pzzz2vHjh2SpNWrV2vgwIHatm2b3n//fTVt2tRutV/NysvLKwU1BwcH68jcyZMn9ccf\nf8hkMunTTz/VsGHDtHPnTrVr107Ozs52rPrqlpeXp3379lmXK8LeuSe+8vJyPfzww4qIiNDixYuV\nlJSkn3/+2R7lNhhVjchVyM3N1d///neNGjVKy5cvlyTt2LFDnTp10vbt2zVt2jS1adOmrku+alW8\nBzExMcrPz68U7oqLi/Xtt9+qqKhIkrRt2zYtXLhQjz/+uPr06SNnZ2f+r1+i+njetdldPnBpzv8z\n86+//qoNGzboiy++UFFRkTw8PDR27Fi1bNlSrVq1kouLi5o3b64zZ87I1dWVP4fagcVikcVisf7i\nUxEKJOnMmTNq1KiRTp8+rfHjx+vQoUO67rrrFBQUpLvuukvr16/XsWPHtG7dOu3fv19du3ZVcHCw\nwsPD7XlIVxWLxWId5TxXXl6evvrqK61YsUJ79uzRsGHD9Nxzz+nw4cMKDw/X9OnT7VTx1euPP/5Q\naWmpmjZtquPHj2vJkiW67777rK8XFRVpwYIFWrVqlcaPH6++fftq06ZNMplMWrNmjTw8PLRp0yat\nXLlSXbt2teOR1C8VIeLcz6CKc8nhw4fl4eGhU6dOaebMmZo3b57uuOMO3XbbbXrxxRfl5uYmNzc3\nLVu2TOXl5WrXrp3CwsLUr18/NWrUyG7H1NCtWrVKHTp0UIcOHSRJM2fOlJeXlywWi77++mstWbJE\nBQUFOnz4sLp06aKZM2fqt99+0969e3X33Xfrjz/+0MmTJ7Vq1So9++yzdj6a+qchnHcdJ02aNOmK\nbhEXqBg5OPcEb7FYVFJSopUrV+rtt9/WqVOndMMNN2jbtm2aPHmy+vfvrwULFqikpERfffWVIiIi\n1KhRI61Zs0aZmZl699131bhxY3Xu3NmOR3ZtOHr0qBo1amT9Dbji37nef/99jR8/XjNnzpSbm5u6\ndOmi9evX64cfftAnn3yi/v3764cfflBxcbEeeugh+fv7y8PDQ/Pnz9eaNWvUoUMH+fn52ekIG66K\naRwVP1sVYVo6+xeejIwMtW7dWtddd53ef/99vfHGG/r44481atQozZo1S8eOHdOdd96pyZMn6+ef\nf9Znn32mjIwM3XLLLYxU11LFXwYqRv/Lysrk5+en6667Tt26ddPx48fl7u6u4cOHa+nSpQoICFD7\n9u311VdfydvbW3l5ecrLy9OwYcMkSS4uLvr000/1yCOP2PfA7CgvL09ubm4qKyuTg4NDlZ9BKSkp\nevrpp/Xxxx9rz5496t+/v3bv3q2lS5dq/vz56t27t06dOqWtW7fq7rvvVlRUlNq0aaPNmzfriy++\nUIsWLbg97SWqmOd/7vuwZMkSpaam6pZbbtGOHTt04MABPfjgg3rsscc0f/58LV68WFlZWXrkkUc0\nZ84cNW3aVD4+Pvrhhx8UGxsrJycnFRUV6dtvv1V0dLSaNGli56O0r4Z43mXKhw0cPnxYEydO1K+/\n/irp/ybDWywW7d+/X9LZ364WLlyod955R506ddJ///tfPf744+rXr5/Cw8Pl7u4uSRo8eLCaNWum\nffv26aGHHtLHH3+sDz74QCNGjNDPP/+skpISux3n1c5sNuujjz7SX/7yF0n/Nxq0Y8cOzZkzR3v3\n7pV09kKSdevW6YUXXlBycrI++OADffbZZ7rtttsUHh5u/fPe4MGD9f3336t169YaMmSIhg0bptdf\nf11eXl7W9xsX99NPP2nJkiWSZA0XFaMUFSHuzJkzevrppxUfH68vvvhC999/v06dOqWePXuqcePG\nCg0NVWBgoJ588kn9+OOPcnd3186dOzV16lQlJCRo/fr1Wr16tT0Ps0Gq+FP3udPWfvnlF73++ut6\n4IEH9Pnnn2vWrFl6+eWX9ccff6hfv34qKirSmDFj9Oc//1nh4eFKTU1Vt27d9Ouvv+r06dOSpODg\nYG3cuNG6fK1ZtWqVoqOjJf3fZ9B3332n1157Tdu3b1d5ebkOHTpkHZzJzMzUZ599pqVLlyowMFAD\nBgzQ1q1bJUldunTRiRMndOTIEXXv3l133HGHHn/8cYWEhMjHx8dux1jfnXttk1R5jm5RUZGKi4tV\nUFCgGTNm6P7779evv/6qoKAgZWVlSZJuu+02+fr66uTJk3JxcVGXLl20a9cueXp66uTJk1q9erVM\nJpN27typY8eOacuWLfY6VLtryOddArUNlJWVac+ePVq/fr2ks6MLI0eOVEhIiEaPHq2FCxfKYrEo\nLS1N48eP15gxYzRhwgStXr1ap0+fVmBgoE6dOqXy8nL5+Pjoxx9/lIuLi/Lz8zV79mw99dRT+uCD\nD9S/f3+5uLjY+WivDlXNPXR0dFTLli1lMpmsVwVPnDhRDz74oFasWKEJEyZow4YN+v7772U2m3Xn\nnXeqa9euGjZsmGbNmqWbbrpJR48etX44Xn/99dbH77//vvr06aOHHnpIbm5u1j8TomoVJ7OcnBwl\nJiZKOntS++WXX/Tkk0/q9ttv10cffaTy8nLt2rVL27ZtU2Zmpj766CM1bdpUixcvlpeXl3r27Kkf\nf/xRkuTs7CwnJyft2bNHJ06c0NatW7Vu3Tq1a9eOKTg1OP/aj4pfZiwWi1atWqWpU6daQ8LGjRvV\noUMHDR48WL1795aTk5N+//133X777Tp16pSuu+46lZWVqVevXvrxxx91/fXXy8fHR9OnT7f+lcHZ\n2Vk7d+604xHbXnW3B7zxxhvVqFEj7dmzRw4ODkpKStKECRN09OhRJSQk6KuvvtKmTZvUqlUrhYSE\nSJISEhL0ww8/qGnTpmrevLm+/vprSVLz5s31yy+/KCAgQIsXL1bnzp01atQoNW3aVD169KizY20o\nqvolUTo7lWnChAnq3bu37r77bmVnZ2vkyJFq1qyZVq1apREjRsjT01MeHh7KzMxUp06d1KZNG23a\ntEmSFBQUpIKCAnl5eelPf/qT/vGPf6hbt25KT09XWFiY8vLy7HK8de1qO+8SqGuh4gKQ6m5d5+bm\nVunEvWHDBrm6uuqXX37R888/r+eff16nT5/Wrl271K5dO5WUlKhNmzZq3LixsrOzddNNN2n+/Pla\nsWKFvvvuO7Vo0UJ+fn4ym83avXu3brrpJqWmpuqOO+6oy8O+6lzsjioVP+iBgYFycXHRjh07lJeX\npx07digtLU1Lly5Vt27d9MYbb1R6ryWpb9++ys3Nlbu7u1xdXZWSkqI333xTTz/9tF544QVJUu/e\nvfXBBx9o8+bNeuutt5gL//+r+FPq+T9bFSezu+++W6WlpTpz5owcHR319ttvy9/fXykpKZo2bZqW\nLl2qrKws3XzzzcrPz5ck3X///fr999/VpEkTNW7cWB9++KEkKTs7WxaLRZ06ddLnn3+uF154QYcO\nHdKYMWPk7+9ftwdez53/eXfurb4qLu7cu3evhg0bpnfffVdms1kBAQF65plnNGTIED3wwANycXFR\np06dJJ0duQ4JCVF5ebl+/vlnOTk5qX379iopKdEvv/yiWbNmaffu3UpISJC7u7t69uypNWvWSKo+\neDZE594isLrPgFatWikgIEDp6ek6deqUtm/frjfeeENTp07VPffco2+++UbFxcUqLS213nKtR48e\n+s9//qOwsDB5eXlp4cKFmjhxohITEzVo0CA1bdpUffv2VWpqqjZu3KjXXnvN+peea1VV96KveE82\nbNigpKQk600CcnNztX//fs2ePVsbN25U9+7d1atXL4WFhWnu3LnW9SMiIvT555/Lw8ND7dq10/ff\nfy9J6tixo3Jzc7VlyxYlJCTonXfe0ZIlSzRr1iyVlpaqe/fudXfgdexqPu8SqC/BuR960v/9ucfB\nwUGnTp2ytqng4uKikJAQFRYWqry8XMuXL9eAAQPk7OysHj16qE2bNtq6dau6dOmizz//3DrK3KFD\nB+3du1fXX3+9OnfurLlz52rSpEl66KGH1KFDBwUGBuqVV17Rk08+KT8/v6vqxFIXysrKqr2jyubN\nm7Vt2zZJla8W9vHxkZeXl7Kzs+Xg4KAffvhBXl5eMpvNSkhIUEZGhoKCgiTJOk1g7dq1uvvuuyWd\nHYno1KmTLBaLkpKSNGLECElS165d1aVLF0l8ecW5Ki4mPP+CQulsPzk5OcnPz0//+c9/dODAAR06\n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\ncHBwcHD8Bf4PujBo3G2ZPWQAAAAASUVORK5CYII=\n", + "text": [ + "" + ] + } + ], + "prompt_number": 135 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "from IPython.display import Image\n", + "Image('report/images/pairwise.png')" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "png": "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\nd+7UiRMnNHz4cFVUVCg2Nlb79u3Tvn375OTkpPj4+Crb+/jjj/Xhhx/q5MmT1uum3n33XZ04cULv\nvPNOtTVcespdRkaGAgICdOTIEU2fPl2/+93vrOHoYufPn9eQIUM0cOBAHTp0yHqPuOzsbPXo0UNN\nmjTRV199ZW2/aNEijRo1StKF+8mtWrVKGzdu1P79++Xq6qpnn322yvY3btyon3/+WWvXrpXFYtHW\nrVsVFBSkI0eO6E9/+pNiY2OtbceMGSNHR0ft3btXmZmZWrdunf75z39an3/xxRe1f/9+7dq1S/n5\n+UpISLip1wsAAOB2QABDrTpy5Ijc3d1lZ3flf2qLFi3SSy+9JHd3d7m7u+vll1/WwoULL2uXnp6u\n8vJyjR8/Xg0aNNCwYcPUrVu3K27X0dFRubm5KiwslKOjo3r16nXFtm5ubho6dKgaNWqkpk2basqU\nKdqwYYP1eZPJpDFjxig4OFh2dnayt79w9u6Nnk7XqlUra/2///3v1a5dO3355ZfVHuupU6f05z//\nWfb29urbt68eeOABLVq0SJI0cuRIJScnS5JOnDihNWvWWEf4kpKSNGPGDHl5ecnBwUEvv/yyli9f\nXmVkLiEhQU5OTmrUqJEkyc/PT7GxsTKZTHrssce0f/9+HTx4UAcOHNCaNWv01ltvycnJSS1bttSE\nCRO0ePFiSVLbtm3Vv39/OTg4yN3dXRMnTrT2242+XgAAALcDAhhqVYsWLXT48OEqH/4vVVRUJD8/\nP+tymzZtVFRUVG07b2/vKo/5+fldMQS9/vrrslgs6t69u+666y7NmzfvijWcPn1acXFx8vf3l7Oz\ns8LCwlRaWlpl29XNxnijoznV1X+lY710f35+ftbTIkeOHKkVK1aorKxMK1asUNeuXa3tc3NzNXTo\nULm6usrV1VXt27eXvb29Dhw4cMVjad26tfX3xo0bS5JOnjypvLw8nT9/Xp6entbtPf300zp06JAk\n6cCBA4qOjpaPj4+cnZ01evRoHTlyxHoMN/J6AQAA3A4IYKhVd999txo2bKjPPvvsim28vLyUm5tr\nXd63b5+8vLwua+fp6VnluixJysvLu2II8vDw0OzZs1VYWKikpCQ988wzV5z58I033tCePXuUkZGh\n0tJSbdiwwTrZRqVL93PpcpMmTSRdCHOViouLq7Sprv5LQ4p0oU/y8/Or7D8vL08+Pj6SpPbt28vP\n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\npjarvT6rqKio8sHezs7O+s3/qVOndO7cOZlMJn366acaMWKE9uzZozvuuEMODg42rLp+y8vL04ED\nB6zLleHg4g9KFRUVeuyxxxQWFqalS5dq+vTp2rlzpy3KrTOq+8a/Um5urv7+978rJiZGq1atkiTt\n3r1bHTp00K5du/Tmm2+qTZs2Rpdcb1W+BlFRUcrPz68SBkpLS/XVV1+puLhYkpSVlaXFixfrySef\nVK9eveTg4MC/9evE+279wiyIMNSlpzz99NNP2rJliz7//HMVFxfLzc1NEyZMUIsWLdSqVSs5Ojqq\nefPmOnv2rJycnDg1x0YsFossFos1LFd+iJSks2fPqlGjRjpz5owmT56sI0eOqGHDhgoICNADDzyg\nzZs36/jx49q0aZMOHjyoLl26KDAwUCEhIbY8pHrFYrFYR1EulpeXpy+//FKrV69WUVGRRowYoYkT\nJ+ro0aMKCQnRO++8Y6OK669z587p/Pnzatq0qU6cOKFly5bpd7/7nfX54uJiJScna926dZo8ebLu\nvfdebd++XSaTSRs2bJCbm5u2b9+uNWvWqEuXLjY8kltL5YfOi/8GVb6fHD16VG5ubjp9+rTmzJmj\nhQsX6r777lPfvn314osvysXFRS4uLlq5cqUqKip0xx13qH379urdu7caNWpks2Oq69atW6e2bduq\nbdu2kqQ5c+aoZcuWslgsWrt2rZYtW6aCggIdPXpUnTp10pw5c/Tzzz9r//79evDBB3Xu3DmdOnVK\n69at03PPPWfjo7n18L5bvzVISEhIsHURqF8qv5W8+MOgxWJRWVmZ1qxZozfeeEOnT5/WXXfdpays\nLM2YMUP9+/dXcnKyysrK9OWXXyosLEyNGjXShg0blJGRobfffluNGzdWx44dbXhkt4+SkhI1atTI\n+g1b5c/F3n//fU2ePFlz5syRi4uLOnXqpM2bN2vbtm365JNP1L9/f23btk2lpaV69NFH5ePjIzc3\nNy1atEgbNmxQ27Zt5e3tbaMjrLsqTyus/P9VGb6kC6PI6enpat26tRo2bKj3339fr776qj7++GPF\nxMRo7ty5On78uO6//37NmDFDO3fu1IoVK5Senq577rmHkbCbVDnyWDm6WF5eLm9vbzVs2FBdu3bV\niRMn5OrqqpEjR2r58uXy9fXVnXfeqS+//FIeHh7Ky8tTXl6eRowYIUlydHTUp59+qjFjxtj2wGwo\nLy9PLi4uKi8vl52dXbV/g5KSkvTMM8/o448/VlFRkfr37699+/Zp+fLlWrRokXr27KnTp0/rhx9+\n0IMPPqiIiAi1adNG3333nT7//HM5Oztzu5frVHmd4sWvw7Jly5SSkqJ77rlHu3fv1qFDh/TII4/o\niSee0KJFi7R06VJlZmZqzJgxmj9/vpo2bSpPT09t27ZN0dHRsre3V3Fxsb766itFRkaqSZMmNj5K\n2+J99/bCKYj41Y4ePaqpU6fqp59+kvTfCz8tFosOHjwo6cI3N4sXL9Zbb72lDh066N///reefPJJ\n9e7dWyEhIXJ1dZUkDR48WM2aNdOBAwf06KOP6uOPP9YHH3ygUaNGaefOnSorK7PZcd4OzGazPvro\nI/3pT3+S9N9vm3fv3q358+dr//79ki5cOL1p0ya98MILSkxM1AcffKAVK1aob9++CgkJsZ5uMnjw\nYH3zzTdq3bq1hgwZohEjRuiVV15Ry5Ytra85ru7777/XsmXLJMn6YbTyW9DKD/1nz57VM888o7i4\nOH3++ecaNmyYTp8+re7du6tx48YKDg6Wv7+//vCHP+jbb7+Vq6ur9uzZo1mzZmns2LHavHmz1q9f\nb8vDrJMqT726+FTqH3/8Ua+88ooefvhhffbZZ5o7d65eeuklnTt3Tr1791ZxcbHGjx+vP/7xjwoJ\nCVFKSoq6du2qn376SWfOnJEkBQYGauvWrdbl2826desUGRkp6b9/g77++mv97W9/065du1RRUaEj\nR45Yv9DLyMjQihUrtHz5cvn7+2vAgAH64YcfJEmdOnXSyZMndezYMYWGhuq+++7Tk08+qaCgIHl6\netrsGG91F1+fLVW9xqi4uFilpaUqKCjQ7NmzNWzYMP30008KCAhQZmamJKlv377y8vLSqVOn5Ojo\nqE6dOmnv3r1yd3fXqVOntH79eplMJu3Zs0fHjx/Xjh07bHWoNsf77u2JAIZfrby8XEVFRdq8ebOk\nC99cjh49WkFBQRo3bpwWL14si8Wi1NRUTZ48WePHj9eUKVO0fv16nTlzRv7+/jp9+rQqKirk6emp\nb7/9Vo6OjsrPz9e8efP09NNP64MPPlD//v3l6Oho46OtP6q7dqJBgwZq0aKFTCaTddakqVOn6pFH\nHtHq1as1ZcoUbdmyRd98843MZrPuv/9+denSRSNGjNDcuXP129/+ViUlJdY309/85jfW399//331\n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\nAElFTkSuQmCC\n", + "prompt_number": 136, + "text": [ + "" + ] + } + ], + "prompt_number": 136 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 136 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 117 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "plt.bar(range(10), range(10), bottom=0, log=True)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 140, + "text": [ + "" + ] + }, + { + "metadata": {}, + "output_type": "display_data", + "png": "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\no2prayVJOTk5Gj58uOdV/e3YsUP33ntvv69B+xCJRJSbm6vOzk719PSos7NT48eP97rp4MGDmjp1\nqu644w4NHjxYjzzyiLZs2ZL1HVdq5bZt27R06VJJ0tKlS/XZZ59d83W4CuX/aWtr0969ezV16lTf\nU3Tp0iWVl5crPz9fjz76qGKxmO9Jevnll/Xmm29q0KDwvHWCIFBVVZUqKyv13nvv+Z6j1tZWjR49\nWjU1NXrwwQf1wgsvqLOz0/esfjZt2hSKiwfm5eXplVde0d1336277rpLI0aMUFVVlddNJSUlamxs\n1OnTp9XZ2akvv/xSR48e9brpbydPnlR+fr4kKT8/XydPnrzmc8Lzf2oInD9/XvPmzdPatWs1dOhQ\n33M0aNAg7du3T0ePHtWuXbuUTCa97vniiy80ZswYVVRUhOqT83fffae9e/dq+/btevvtt9XY2Oh1\nT09Pj1paWrR8+XK1tLTozjvv1OrVq71u+qfu7m59/vnnmj9/vu8p+uWXX7RmzRq1tbXp+PHjOn/+\nvD7++GOvmwoLC7Vy5Uo9+eSTmjlzpioqKkL1oeZvQRCk9H368C335OLFi5o7d66ee+45Pfvss77n\n9DN8+HA99dRTam5u9rpj9+7d2rZtmyZOnKjq6mrt3LlTS5Ys8bpJksaNGydJGj16tGbPnq2mpiav\ne6LRqKLRqKZMmSJJmjdvnlpaWrxu+qft27froYce0ujRo31PUXNzs6ZNm6ZRo0YpJydHc+bM0e7d\nu33PUm1trZqbm/Xtt99qxIgRuv/++31PknT50/tvv/0mSTpx4oTGjBlzzecQeV0+n/v8888rFovp\npZde8j1HkvTHH3/o7NmzkqSuri598803qqio8Lpp1apVam9vV2trqzZt2qTHHntMH330kddNnZ2d\n6ujokHT5XgZff/31v66Wmm1jx45VQUGBDh06JOny+e/i4mKvm/6pvr5e1dXVvmdIuvyp+YcfflBX\nV5ecc9qxY0coTkv+/vvvkqQjR47o008/DcWpLUmaNWuWNm7cKEnauHFjah9Ib8S/Cv+XRYsWuXHj\nxrnbbrvNRaNRt379+mxP+JfGxkYXBIErKyvr+3rZ9u3bvW768ccfXUVFhSsrK3OlpaXujTfe8Lrn\n/yWTyVB8u+bXX391ZWVlrqyszBUXF7tVq1b5nuScc27fvn2usrLSPfDAA2727Nmh+XbN+fPn3ahR\no9y5c+d8T+lTV1fX9xXKJUuWuO7ubt+T3PTp010sFnNlZWVu586dXjb83crc3Ny+Vp46dco9/vjj\nA/oKZeBciE6uAgAyitM1AGAYkQcAw4g8ABhG5AHAMCIPAIYReQAw7H8BO8xIZZvOjAAAAABJRU5E\nrkJggg==\n", + "text": [ + "" + ] + } + ], + "prompt_number": 140 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [] + } + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/arc_distance/__init__.py b/arc_distance/__init__.py deleted file mode 100644 index b4eb763..0000000 --- a/arc_distance/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# Authors: Yuancheng Peng -# License: MIT -"""Computes the arc distance between a collection of points - -This code is challenging because it requires efficient vectorisation of -trigonometric functions that are note natively supported in SSE/AVX. The numpy -version makes use of numpy.tile and transpose, which proves to be challenging -too. - -See also http://en.wikipedia.org/wiki/Great-circle_distance -""" - -import numpy as np - - -def make_env(n=1000): - rng = np.random.RandomState(42) - a = rng.rand(n, 2) - b = rng.rand(n, 2) - return (a, b), {} diff --git a/arc_distance/arc_distance_numba.py b/arc_distance/arc_distance_numba.py deleted file mode 100644 index 531de6f..0000000 --- a/arc_distance/arc_distance_numba.py +++ /dev/null @@ -1,10 +0,0 @@ -# Authors: Yuancheng Peng -# License: MIT - -from arc_distance import arc_distance_python as adp -from numba import autojit - - -benchmarks = (("arc_distance_numba_for_loops", - autojit(adp.arc_distance_python_nested_for_loops)), - ) diff --git a/arc_distance/arc_distance_parakeet.py b/arc_distance/arc_distance_parakeet.py deleted file mode 100644 index 4f16244..0000000 --- a/arc_distance/arc_distance_parakeet.py +++ /dev/null @@ -1,31 +0,0 @@ -# Authors: Alex Rubinsteyn -# License: MIT - -from arc_distance import arc_distance_python as adp -from parakeet import jit -import numpy as np - -@jit -def arc_distance_parakeet_comprehensions(a, b): - """ - Calculates the pairwise arc distance between all points in vector a and b. - Uses nested list comprehensions, which are efficiently parallelized - by Parakeet. - """ - def arc_dist(ai, bj): - theta1 = ai[0] - phi1 = ai[1] - theta2 = bj[0] - phi2 = bj[1] - d_theta = theta2 - theta1 - d_phi = phi2 - phi1 - temp = (np.sin(d_theta / 2) ** 2) + \ - (np.cos(theta1) * np.cos(theta2) * np.sin(d_phi / 2) ** 2) - return 2 * np.arctan2(np.sqrt(temp), np.sqrt(1 - temp)) - return np.array([[arc_dist(ai, bj) for bj in b] for ai in a]) - -benchmarks = (("arc_distance_parakeet_for_loops", - jit(adp.arc_distance_python_nested_for_loops)), - ("arc_distance_parakeet_comprehensions", - arc_distance_parakeet_comprehensions) - ) diff --git a/arc_distance/arc_distance_python.py b/arc_distance/arc_distance_python.py deleted file mode 100644 index 6881254..0000000 --- a/arc_distance/arc_distance_python.py +++ /dev/null @@ -1,71 +0,0 @@ -# Authors: Federico Vaggi -# License: MIT -# Source: https://bitbucket.org/FedericoV/numpy-tip-complex-modeling/ - -import numpy as np -from math import * - - -def arc_distance_python_nested_for_loops(a, b): - """ - Calculates the pairwise arc distance between all points in vector a and b. - """ - a_nrows = a.shape[0] - b_nrows = b.shape[0] - - distance_matrix = np.zeros([a_nrows, b_nrows]) - - for i in range(a_nrows): - theta_1 = a[i, 0] - phi_1 = a[i, 1] - for j in range(b_nrows): - theta_2 = b[j, 0] - phi_2 = b[j, 1] - temp = (pow(sin((theta_2 - theta_1) / 2), 2) - + - cos(theta_1) * cos(theta_2) - * pow(sin((phi_2 - phi_1) / 2), 2)) - distance_matrix[i, j] = 2 * (atan2(sqrt(temp), sqrt(1 - temp))) - return distance_matrix - - -def arc_distance_numpy_tile(a, b): - """ - Calculates the pairwise arc distance between all points in vector a and b. - """ - theta_1 = np.tile(a[:, 0], (b.shape[0], 1)).T - phi_1 = np.tile(a[:, 1], (b.shape[0], 1)).T - - theta_2 = np.tile(b[:, 0], (a.shape[0], 1)) - phi_2 = np.tile(b[:, 1], (a.shape[0], 1)) - - temp = (np.sin((theta_2 - theta_1) / 2)**2 - + - np.cos(theta_1) * np.cos(theta_2) - * np.sin((phi_2 - phi_1) / 2)**2) - distance_matrix = 2 * (np.arctan2(np.sqrt(temp), np.sqrt(1 - temp))) - - return distance_matrix - - -def arc_distance_numpy_broadcast(a, b): - """ - Calculates the pairwise arc distance between all points in vector a and b. - """ - theta_1 = a[:, 0][:, None] - theta_2 = b[:, 0][None, :] - phi_1 = a[:, 1][:, None] - phi_2 = b[:, 1][None, :] - - temp = (np.sin((theta_2 - theta_1) / 2)**2 - + - np.cos(theta_1) * np.cos(theta_2) - * np.sin((phi_2 - phi_1) / 2)**2) - distance_matrix = 2 * (np.arctan2(np.sqrt(temp), np.sqrt(1 - temp))) - return distance_matrix - -benchmarks = ( - arc_distance_python_nested_for_loops, - arc_distance_numpy_tile, - arc_distance_numpy_broadcast, -) diff --git a/arc_distance/arc_distance_pythran.py b/arc_distance/arc_distance_pythran.py deleted file mode 100644 index 050f9d5..0000000 --- a/arc_distance/arc_distance_pythran.py +++ /dev/null @@ -1,39 +0,0 @@ -# Authors: Yuancheng Peng -# License: MIT - -from arc_distance import arc_distance_python -from pythran import compile_pythrancode -from inspect import getsource -import re -import imp - -# grab imports -imports = ''' -import numpy as np -from math import * -''' - -exports = ''' -#pythran export arc_distance_python_nested_for_loops(float [][], float [][]) -''' - -modname = 'arc_distance_pythran' - -# grab the source from original functions -funs = (arc_distance_python.arc_distance_python_nested_for_loops,) -sources = map(getsource, funs) -source = '\n'.join(sources) - -# patch -source = re.sub(r'\[a_nrows, b_nrows\]', '(a_nrows, b_nrows)', source) - -# compile to native module -source = '\n'.join([exports, imports, source]) -native = compile_pythrancode(modname, source) - -# load -native = imp.load_dynamic(modname, native) - -benchmarks = (("arc_distance_pythran_nested_for_loops", - native.arc_distance_python_nested_for_loops), - ) diff --git a/arc_distance/arc_distance_theano.py b/arc_distance/arc_distance_theano.py deleted file mode 100644 index 76d2c6c..0000000 --- a/arc_distance/arc_distance_theano.py +++ /dev/null @@ -1,66 +0,0 @@ -# Authors: Frederic Bastien -# License: MIT -import theano -import theano.tensor as tensor - - -def arc_distance_theano_alloc_prepare(dtype='float64'): - """ - Calculates the pairwise arc distance between all points in vector a and b. - """ - a = tensor.matrix(dtype=str(dtype)) - b = tensor.matrix(dtype=str(dtype)) - # Theano don't implement all case of tile, so we do the equivalent with alloc. - #theta_1 = tensor.tile(a[:, 0], (b.shape[0], 1)).T - theta_1 = tensor.alloc(a[:, 0], b.shape[0], b.shape[0]).T - phi_1 = tensor.alloc(a[:, 1], b.shape[0], b.shape[0]).T - - theta_2 = tensor.alloc(b[:, 0], a.shape[0], a.shape[0]) - phi_2 = tensor.alloc(b[:, 1], a.shape[0], a.shape[0]) - - temp = (tensor.sin((theta_2 - theta_1) / 2)**2 - + - tensor.cos(theta_1) * tensor.cos(theta_2) - * tensor.sin((phi_2 - phi_1) / 2)**2) - distance_matrix = 2 * (tensor.arctan2(tensor.sqrt(temp), - tensor.sqrt(1 - temp))) - name = "arc_distance_theano_alloc" - rval = theano.function([a, b], - distance_matrix, - name=name) - rval.__name__ = name - - return rval - - -def arc_distance_theano_broadcast_prepare(dtype='float64'): - """ - Calculates the pairwise arc distance between all points in vector a and b. - """ - a = tensor.matrix(dtype=str(dtype)) - b = tensor.matrix(dtype=str(dtype)) - - theta_1 = a[:, 0][None, :] - theta_2 = b[:, 0][None, :] - phi_1 = a[:, 1][:, None] - phi_2 = b[:, 1][None, :] - - temp = (tensor.sin((theta_2 - theta_1) / 2)**2 - + - tensor.cos(theta_1) * tensor.cos(theta_2) - * tensor.sin((phi_2 - phi_1) / 2)**2) - distance_matrix = 2 * (tensor.arctan2(tensor.sqrt(temp), - tensor.sqrt(1 - temp))) - name = "arc_distance_theano_broadcast" - rval = theano.function([a, b], - distance_matrix, - name=name) - rval.__name__ = name - - return rval - - -benchmarks = ( - arc_distance_theano_alloc_prepare('float64'), - arc_distance_theano_broadcast_prepare('float64'), -) diff --git a/benchmark_results.json b/benchmark_results.json new file mode 100644 index 0000000..850129d --- /dev/null +++ b/benchmark_results.json @@ -0,0 +1,638 @@ +{ + "benchmark_results": [ + { + "group_name": "arc_distance", + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance", + "records": [ + { + "name": "arc_distance_pythran_nested_for_loops", + "cold_time": 0.08391904830932617, + "warm_time": 0.078933000564575195, + "all_warm_times": [ + 0.08530902862548828, + 0.0794990062713623, + 0.0789330005645752, + 0.08436894416809082 + ], + "std_warm_times": 0.0028381331101485696, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance/arc_distance_pythran.py", + "rank": 1, + "speedup": 86.867659007638892 + }, + { + "name": "arc_distance_parakeet_for_loops", + "cold_time": 0.3778650760650635, + "warm_time": 0.081580162048339844, + "all_warm_times": [ + 0.08158016204833984, + 0.08426403999328613, + 0.08521890640258789, + 0.0838930606842041 + ], + "std_warm_times": 0.0013369841008558296, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance/arc_distance_parakeet.py", + "rank": 2, + "speedup": 84.048925686496844 + }, + { + "name": "arc_distance_theano_broadcast", + "cold_time": 0.08967018127441406, + "warm_time": 0.086144208908081055, + "all_warm_times": [ + 0.08614706993103027, + 0.08614420890808105, + 0.0862588882446289, + 0.0865941047668457 + ], + "std_warm_times": 0.00018375925416707701, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance/arc_distance_theano.py", + "rank": 3, + "speedup": 79.59589001286966 + }, + { + "name": "arc_distance_parakeet_comprehensions", + "cold_time": 0.445512056350708, + "warm_time": 0.091605186462402344, + "all_warm_times": [ + 0.09160518646240234, + 0.09614086151123047, + 0.09435701370239258, + 0.0921640396118164 + ], + "std_warm_times": 0.0018073388402672606, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance/arc_distance_parakeet.py", + "rank": 4, + "speedup": 74.850838061527256 + }, + { + "name": "arc_distance_numpy_broadcast", + "cold_time": null, + "warm_time": 0.0934300422668457, + "all_warm_times": [ + 0.0934300422668457 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance/arc_distance_python.py", + "rank": 5, + "speedup": 73.38886734001235 + }, + { + "name": "arc_distance_theano_alloc", + "cold_time": 0.11582088470458984, + "warm_time": 0.10689902305603027, + "all_warm_times": [ + 0.10854315757751465, + 0.10689902305603027, + 0.10750484466552734, + 0.10844302177429199 + ], + "std_warm_times": 0.00068110330342396961, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance/arc_distance_theano.py", + "rank": 6, + "speedup": 64.142073346165077 + }, + { + "name": "arc_distance_numpy_tile", + "cold_time": null, + "warm_time": 0.17447614669799805, + "all_warm_times": [ + 0.17447614669799805 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance/arc_distance_python.py", + "rank": 7, + "speedup": 39.29892485166834 + }, + { + "name": "arc_distance_python_nested_for_loops", + "cold_time": null, + "warm_time": 6.856724977493286, + "all_warm_times": [ + 6.856724977493286 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/arc_distance/arc_distance_python.py", + "rank": 8, + "speedup": 1.0 + } + ], + "runtime_errors": [], + "import_errors": [ + { + "name": "arc_distance_numba", + "error_type": "AttributeError", + "error_message": "'NoneType' object has no attribute 'core'", + "traceback": "Traceback (most recent call last):\n File \"run_benchmarks.py\", line 98, in find_benchmarks\n module = __import__(abs_module_name, fromlist=\"dummy\")\n File \"/Users/ogrisel/code/python-benchmarks/arc_distance/arc_distance_numba.py\", line 5, in \n from numba import autojit\n File \"/usr/local/lib/python2.7/site-packages/numba/__init__.py\", line 18, in \n from numba import utils, typesystem\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 102, in \n context = get_minivect_context()\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 100, in get_minivect_context\n return NumbaContext()\n File \"/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py\", line 140, in __init__\n self.llvm_module = llvm.core.Module.new('default_module')\nAttributeError: 'NoneType' object has no attribute 'core'\n" + } + ] + }, + { + "group_name": "growcut", + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/growcut", + "records": [ + { + "name": "growcut_parakeet", + "cold_time": 0.42096495628356934, + "warm_time": 0.0046639442443847656, + "all_warm_times": [ + 0.00531005859375, + 0.004951000213623047, + 0.004663944244384766, + 0.004747152328491211 + ], + "std_warm_times": 0.00024926502102072084, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/growcut/growcut_parakeet.py", + "rank": 1, + "speedup": 2147.5241795317452 + }, + { + "name": "growcut_cython", + "cold_time": 0.009152889251708984, + "warm_time": 0.0062019824981689453, + "all_warm_times": [ + 0.007035017013549805, + 0.006947040557861328, + 0.006201982498168945, + 0.007946968078613281 + ], + "std_warm_times": 0.00061913661359338341, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/growcut/growcut_cython.pyx", + "rank": 2, + "speedup": 1614.9566755083997 + }, + { + "name": "growcut_pythran", + "cold_time": 0.011638879776000977, + "warm_time": 0.0097451210021972656, + "all_warm_times": [ + 0.01582193374633789, + 0.009745121002197266, + 0.0120391845703125, + 0.011751174926757812 + ], + "std_warm_times": 0.0021962731413242773, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/growcut/growcut_pythran.py", + "rank": 3, + "speedup": 1027.789499437295 + }, + { + "name": "growcut_python", + "cold_time": null, + "warm_time": 10.0159330368042, + "all_warm_times": [ + 10.0159330368042 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/growcut/growcut_python.py", + "rank": 4, + "speedup": 1.0 + } + ], + "runtime_errors": [], + "import_errors": [ + { + "name": "growcut_numba", + "error_type": "AttributeError", + "error_message": "'NoneType' object has no attribute 'core'", + "traceback": "Traceback (most recent call last):\n File \"run_benchmarks.py\", line 98, in find_benchmarks\n module = __import__(abs_module_name, fromlist=\"dummy\")\n File \"/Users/ogrisel/code/python-benchmarks/growcut/growcut_numba.py\", line 2, in \n from numba import autojit\n File \"/usr/local/lib/python2.7/site-packages/numba/__init__.py\", line 18, in \n from numba import utils, typesystem\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 102, in \n context = get_minivect_context()\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 100, in get_minivect_context\n return NumbaContext()\n File \"/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py\", line 140, in __init__\n self.llvm_module = llvm.core.Module.new('default_module')\nAttributeError: 'NoneType' object has no attribute 'core'\n" + } + ] + }, + { + "group_name": "julia", + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/julia", + "records": [ + { + "name": "julia_pythran_for_loops", + "cold_time": 0.0029201507568359375, + "warm_time": 0.0024111270904541016, + "all_warm_times": [ + 0.0024111270904541016, + 0.0027158260345458984, + 0.002460002899169922, + 0.0024220943450927734 + ], + "std_warm_times": 0.00012462729745560191, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/julia/julia_pythran.py", + "rank": 1, + "speedup": 1865.0206664689015 + }, + { + "name": "julia_parakeet_for_loops", + "cold_time": 0.43265795707702637, + "warm_time": 0.003353118896484375, + "all_warm_times": [ + 0.003386974334716797, + 0.003654003143310547, + 0.003353118896484375, + 0.0035381317138671875 + ], + "std_warm_times": 0.00012080107339492268, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/julia/julia_parakeet.py", + "rank": 2, + "speedup": 1341.0803469852106 + }, + { + "name": "julia_cython_for_loops", + "cold_time": 0.004063129425048828, + "warm_time": 0.0037648677825927734, + "all_warm_times": [ + 0.0037648677825927734, + 0.004252195358276367, + 0.004394054412841797, + 0.004058837890625 + ], + "std_warm_times": 0.00023580495443110928, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/julia/julia_cython.pyx", + "rank": 3, + "speedup": 1194.4116268760686 + }, + { + "name": "julia_pyopencl", + "cold_time": null, + "warm_time": 0.010384082794189453, + "all_warm_times": [ + 0.010384082794189453 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/julia/julia_pyopencl.py", + "rank": 4, + "speedup": 433.0475731276117 + }, + { + "name": "julia_python_numpy", + "cold_time": null, + "warm_time": 0.18692898750305176, + "all_warm_times": [ + 0.18692898750305176 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/julia/julia_python.py", + "rank": 5, + "speedup": 24.056203980169304 + }, + { + "name": "julia_python_for_loops", + "cold_time": null, + "warm_time": 4.496801853179932, + "all_warm_times": [ + 4.496801853179932 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/julia/julia_python.py", + "rank": 6, + "speedup": 1.0 + } + ], + "runtime_errors": [], + "import_errors": [ + { + "name": "julia_numba", + "error_type": "AttributeError", + "error_message": "'NoneType' object has no attribute 'core'", + "traceback": "Traceback (most recent call last):\n File \"run_benchmarks.py\", line 98, in find_benchmarks\n module = __import__(abs_module_name, fromlist=\"dummy\")\n File \"/Users/ogrisel/code/python-benchmarks/julia/julia_numba.py\", line 2, in \n from numba import autojit\n File \"/usr/local/lib/python2.7/site-packages/numba/__init__.py\", line 18, in \n from numba import utils, typesystem\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 102, in \n context = get_minivect_context()\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 100, in get_minivect_context\n return NumbaContext()\n File \"/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py\", line 140, in __init__\n self.llvm_module = llvm.core.Module.new('default_module')\nAttributeError: 'NoneType' object has no attribute 'core'\n" + } + ] + }, + { + "group_name": "pairwise", + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise", + "records": [ + { + "name": "pairwise_theano_blas_float32", + "cold_time": 0.0011949539184570312, + "warm_time": 0.00081992149353027344, + "all_warm_times": [ + 0.0009999275207519531, + 0.0008628368377685547, + 0.0008511543273925781, + 0.0008199214935302734 + ], + "std_warm_times": 6.9048527315114595e-05, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_theano.py", + "rank": 1, + "speedup": 25834.77958708927 + }, + { + "name": "pairwise_theano_blas_float64", + "cold_time": 0.001216888427734375, + "warm_time": 0.0010321140289306641, + "all_warm_times": [ + 0.0014979839324951172, + 0.0010459423065185547, + 0.001032114028930664, + 0.0010790824890136719 + ], + "std_warm_times": 0.00019370569609799686, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_theano.py", + "rank": 2, + "speedup": 20523.401940401942 + }, + { + "name": "pairwise_python_numpy_dot", + "cold_time": null, + "warm_time": 0.0021979808807373047, + "all_warm_times": [ + 0.0021979808807373047 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_python.py", + "rank": 3, + "speedup": 9637.249918646274 + }, + { + "name": "pairwise_pyopencl_cpu", + "cold_time": null, + "warm_time": 0.0037348270416259766, + "all_warm_times": [ + 0.0037348270416259766 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_pyopencl.py", + "rank": 4, + "speedup": 5671.612320459623 + }, + { + "name": "pairwise_cython_for_loops", + "cold_time": 0.012512922286987305, + "warm_time": 0.012480020523071289, + "all_warm_times": [ + 0.01287698745727539, + 0.013123035430908203, + 0.012962102890014648, + 0.012480020523071289 + ], + "std_warm_times": 0.00023679340309741665, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_cython.pyx", + "rank": 5, + "speedup": 1697.3121979176617 + }, + { + "name": "pairwise_parakeet_inner_numpy", + "cold_time": 0.24580979347229004, + "warm_time": 0.013036012649536133, + "all_warm_times": [ + 0.01345515251159668, + 0.017564058303833008, + 0.01588582992553711, + 0.013036012649536133 + ], + "std_warm_times": 0.0018440458943548158, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_parakeet.py", + "rank": 6, + "speedup": 1624.9210271229219 + }, + { + "name": "pairwise_parakeet_nested_for_loops", + "cold_time": 0.18332195281982422, + "warm_time": 0.01314997673034668, + "all_warm_times": [ + 0.013323068618774414, + 0.01314997673034668, + 0.014306068420410156, + 0.013651132583618164 + ], + "std_warm_times": 0.00044162494779938205, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_parakeet.py", + "rank": 7, + "speedup": 1610.8386728311123 + }, + { + "name": "pairwise_parakeet_comprehensions", + "cold_time": 0.2990529537200928, + "warm_time": 0.013530969619750977, + "all_warm_times": [ + 0.014219999313354492, + 0.01638197898864746, + 0.013530969619750977, + 0.013609886169433594 + ], + "std_warm_times": 0.0011548846513050209, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_parakeet.py", + "rank": 8, + "speedup": 1565.4821242929888 + }, + { + "name": "pairwise_pythran_nested_for_loops", + "cold_time": 0.01808619499206543, + "warm_time": 0.01565098762512207, + "all_warm_times": [ + 0.016075849533081055, + 0.020102977752685547, + 0.01565098762512207, + 0.0169069766998291 + ], + "std_warm_times": 0.0017446559311014883, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_pythran.py", + "rank": 9, + "speedup": 1353.428395155762 + }, + { + "name": "pairwise_theano_broadcast_float32", + "cold_time": 0.05335593223571777, + "warm_time": 0.03354191780090332, + "all_warm_times": [ + 0.03354191780090332, + 0.03809690475463867, + 0.0337679386138916, + 0.0360410213470459 + ], + "std_warm_times": 0.0018570477180874286, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_theano.py", + "rank": 10, + "speedup": 631.52295553897 + }, + { + "name": "pairwise_theano_broadcast_float64", + "cold_time": 0.04522085189819336, + "warm_time": 0.042270183563232422, + "all_warm_times": [ + 0.044497013092041016, + 0.04326295852661133, + 0.044862985610961914, + 0.04227018356323242 + ], + "std_warm_times": 0.0010272508080647448, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_theano.py", + "rank": 11, + "speedup": 501.12134082371654 + }, + { + "name": "pairwise_python_broadcast_numpy", + "cold_time": null, + "warm_time": 0.15924406051635742, + "all_warm_times": [ + 0.15924406051635742 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_python.py", + "rank": 12, + "speedup": 133.01903377360694 + }, + { + "name": "pairwise_python_inner_numpy", + "cold_time": null, + "warm_time": 1.8430240154266357, + "all_warm_times": [ + 1.8430240154266357 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_python.py", + "rank": 13, + "speedup": 11.493334263020001 + }, + { + "name": "pairwise_python_nested_for_loops", + "cold_time": null, + "warm_time": 21.182491064071655, + "all_warm_times": [ + 21.182491064071655 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/pairwise/pairwise_python.py", + "rank": 14, + "speedup": 1.0 + } + ], + "runtime_errors": [], + "import_errors": [ + { + "name": "pairwise_numba", + "error_type": "AttributeError", + "error_message": "'NoneType' object has no attribute 'core'", + "traceback": "Traceback (most recent call last):\n File \"run_benchmarks.py\", line 98, in find_benchmarks\n module = __import__(abs_module_name, fromlist=\"dummy\")\n File \"/Users/ogrisel/code/python-benchmarks/pairwise/pairwise_numba.py\", line 5, in \n from numba import autojit\n File \"/usr/local/lib/python2.7/site-packages/numba/__init__.py\", line 18, in \n from numba import utils, typesystem\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 102, in \n context = get_minivect_context()\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 100, in get_minivect_context\n return NumbaContext()\n File \"/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py\", line 140, in __init__\n self.llvm_module = llvm.core.Module.new('default_module')\nAttributeError: 'NoneType' object has no attribute 'core'\n" + } + ] + }, + { + "group_name": "rosen_der", + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der", + "records": [ + { + "name": "rosen_der_loops_parakeet", + "cold_time": 0.2613508701324463, + "warm_time": 0.0041399002075195312, + "all_warm_times": [ + 0.004981040954589844, + 0.004180908203125, + 0.004189968109130859, + 0.004139900207519531 + ], + "std_warm_times": 0.00035158542307875315, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der/rosen_der_parakeet.py", + "rank": 1, + "speedup": 2459.2993549873299 + }, + { + "name": "rosen_der_pythran", + "cold_time": 0.0047760009765625, + "warm_time": 0.0051150321960449219, + "all_warm_times": [ + 0.005486011505126953, + 0.005609989166259766, + 0.005115032196044922, + 0.008510828018188477 + ], + "std_warm_times": 0.0013577046061005772, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der/rosen_der_pythran.py", + "rank": 2, + "speedup": 1990.4574438333177 + }, + { + "name": "rosen_der_cython", + "cold_time": 0.008260965347290039, + "warm_time": 0.0053920745849609375, + "all_warm_times": [ + 0.005686044692993164, + 0.005606889724731445, + 0.005408048629760742, + 0.0053920745849609375 + ], + "std_warm_times": 0.0001264674464093316, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der/rosen_der_cython.pyx", + "rank": 3, + "speedup": 1888.1886275203397 + }, + { + "name": "rosen_der_theano_float32", + "cold_time": 0.012048006057739258, + "warm_time": 0.0064139366149902344, + "all_warm_times": [ + 0.008077859878540039, + 0.006413936614990234, + 0.007899045944213867, + 0.00681614875793457 + ], + "std_warm_times": 0.00070411827156742219, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der/rosen_der_theano.py", + "rank": 4, + "speedup": 1587.3642851832578 + }, + { + "name": "rosen_der_theano_float64", + "cold_time": 0.015202999114990234, + "warm_time": 0.0079228878021240234, + "all_warm_times": [ + 0.010712146759033203, + 0.007922887802124023, + 0.010877847671508789, + 0.0081939697265625 + ], + "std_warm_times": 0.0013728872848571068, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der/rosen_der_theano.py", + "rank": 5, + "speedup": 1285.0433029400258 + }, + { + "name": "rosen_der_numpy_parakeet", + "cold_time": 0.3740379810333252, + "warm_time": 0.0090508460998535156, + "all_warm_times": [ + 0.009679079055786133, + 0.009091854095458984, + 0.00919485092163086, + 0.009050846099853516 + ], + "std_warm_times": 0.00025087522763551386, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der/rosen_der_parakeet.py", + "rank": 6, + "speedup": 1124.8952636847373 + }, + { + "name": "rosen_der_numpy", + "cold_time": null, + "warm_time": 0.04478788375854492, + "all_warm_times": [ + 0.04478788375854492 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der/rosen_der_python.py", + "rank": 7, + "speedup": 227.3216114642222 + }, + { + "name": "rosen_der_python", + "cold_time": null, + "warm_time": 10.181253910064697, + "all_warm_times": [ + 10.181253910064697 + ], + "std_warm_times": 0.0, + "source_url": "https://github.com/numfocus/python-benchmarks/tree/master/rosen_der/rosen_der_python.py", + "rank": 8, + "speedup": 1.0 + } + ], + "runtime_errors": [], + "import_errors": [ + { + "name": "rosen_der_numba", + "error_type": "AttributeError", + "error_message": "'NoneType' object has no attribute 'core'", + "traceback": "Traceback (most recent call last):\n File \"run_benchmarks.py\", line 98, in find_benchmarks\n module = __import__(abs_module_name, fromlist=\"dummy\")\n File \"/Users/ogrisel/code/python-benchmarks/rosen_der/rosen_der_numba.py\", line 5, in \n from numba import autojit\n File \"/usr/local/lib/python2.7/site-packages/numba/__init__.py\", line 18, in \n from numba import utils, typesystem\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 102, in \n context = get_minivect_context()\n File \"/usr/local/lib/python2.7/site-packages/numba/utils.py\", line 100, in get_minivect_context\n return NumbaContext()\n File \"/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py\", line 140, in __init__\n self.llvm_module = llvm.core.Module.new('default_module')\nAttributeError: 'NoneType' object has no attribute 'core'\n" + } + ] + } + ], + "benchmark_environment": {} +} \ No newline at end of file diff --git a/report/css/bootstrap-responsive.css b/css/bootstrap-responsive.css similarity index 100% rename from report/css/bootstrap-responsive.css rename to css/bootstrap-responsive.css diff --git a/report/css/bootstrap-responsive.min.css b/css/bootstrap-responsive.min.css similarity index 100% rename from report/css/bootstrap-responsive.min.css rename to css/bootstrap-responsive.min.css diff --git a/report/css/bootstrap.css b/css/bootstrap.css similarity index 100% rename from report/css/bootstrap.css rename to css/bootstrap.css diff --git a/report/css/bootstrap.min.css b/css/bootstrap.min.css similarity index 100% rename from report/css/bootstrap.min.css rename to css/bootstrap.min.css diff --git a/report/css/custom.css b/css/custom.css similarity index 100% rename from report/css/custom.css rename to css/custom.css diff --git a/growcut/__init__.py b/growcut/__init__.py deleted file mode 100644 index 9c2b50d..0000000 --- a/growcut/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# Authors: Serge Guelton -# License: MIT -import numpy as np - -def make_env(N=50): - dtype = np.double - image = np.zeros((N, N, 3), dtype=dtype) - state = np.zeros((N, N, 2), dtype=dtype) - state_next = np.empty_like(state) - - # colony 1 is strength 1 at position 0,0 - # colony 0 is strength 0 at all other positions - state[0, 0, 0] = 1 - state[0, 0, 1] = 1 - - window_radius = 10 - - return (image, state, state_next, window_radius), {} diff --git a/growcut/growcut_cython.pyx b/growcut/growcut_cython.pyx deleted file mode 100644 index a4db3f0..0000000 --- a/growcut/growcut_cython.pyx +++ /dev/null @@ -1,75 +0,0 @@ -# Authors: Stefan van der Walt, Nathan Faggian, Aron Ahmadia -# https://github.com/stefanv/growcut_py -from __future__ import division - -import numpy as np -cimport cython -cimport numpy as cnp - -cdef extern from "math.h" nogil: - double sqrt(double) - - -@cython.boundscheck(False) -@cython.wraparound(False) -cdef inline double distance(double[:, :, ::1] image, - Py_ssize_t r0, Py_ssize_t c0, - Py_ssize_t r1, Py_ssize_t c1) nogil: - cdef: - double s = 0, d - int i - - for i in range(3): - d = image[r0, c0, i] - image[r1, c1, i] - s += d * d - - return sqrt(s) - - -cdef double s3 = sqrt(3) - -cdef inline double g(double d) nogil: - return 1 - (d / s3) - -@cython.boundscheck(False) -@cython.wraparound(False) -def growcut_cython(double[:, :, ::1] image, double[:, :, ::1] state, double[:, :, ::1] state_next, Py_ssize_t window_radius): - - cdef: - Py_ssize_t i, j, ii, jj, width, height - double gc, attack_strength, defense_strength, winning_colony - int changes - - height, width = image.shape[0], image.shape[1] - - changes = 0 - - for j in range(width): - for i in range(height): - - winning_colony = state[i, j, 0] - defense_strength = state[i, j, 1] - - for jj in xrange(max(0, j - window_radius), min(j + window_radius + 1, width)): - for ii in xrange(max(0, i - window_radius), min(i + window_radius + 1, height)): - if ii == i and jj == j: - continue - - # p -> current cell, (i, j) - # q -> attacker, (ii, jj) - - gc = g(distance(image, i, j, ii, jj)) - - attack_strength = gc * state[ii, jj, 1] - - if attack_strength > defense_strength: - defense_strength = attack_strength - winning_colony = state[ii, jj, 0] - changes += 1 - - state_next[i, j, 0] = winning_colony - state_next[i, j, 1] = defense_strength - - return changes - -benchmarks = ( growcut_cython, ) diff --git a/growcut/growcut_numba.py b/growcut/growcut_numba.py deleted file mode 100644 index 31e9e1a..0000000 --- a/growcut/growcut_numba.py +++ /dev/null @@ -1,8 +0,0 @@ -from growcut import growcut_python -from numba import autojit - - -benchmarks = ( - ("growcut_numba", - autojit(growcut_python.growcut_python)), -) diff --git a/growcut/growcut_parakeet.py b/growcut/growcut_parakeet.py deleted file mode 100644 index 5577e62..0000000 --- a/growcut/growcut_parakeet.py +++ /dev/null @@ -1,8 +0,0 @@ -from growcut import growcut_python -from parakeet import jit - - -benchmarks = ( - ("growcut_parakeet", - jit(growcut_python.growcut_python)), -) diff --git a/growcut/growcut_python.py b/growcut/growcut_python.py deleted file mode 100644 index ac0ab09..0000000 --- a/growcut/growcut_python.py +++ /dev/null @@ -1,60 +0,0 @@ -# Authors: Nathan Faggian, Stefan van der Walt, Aron Ahmadia, Olivier Grisel -# https://github.com/stefanv/growcut_py -import numpy as np - - -def window_floor(idx, radius): - if radius > idx: - return 0 - else: - return idx - radius - - -def window_ceil(idx, ceil, radius): - if idx + radius > ceil: - return ceil - else: - return idx + radius - - -def growcut_python(image, state, state_next, window_radius): - changes = 0 - sqrt_3 = np.sqrt(3.0) - - height = image.shape[0] - width = image.shape[1] - - for j in xrange(width): - for i in xrange(height): - - winning_colony = state[i, j, 0] - defense_strength = state[i, j, 1] - - for jj in xrange(window_floor(j, window_radius), - window_ceil(j + 1, width, window_radius)): - for ii in xrange(window_floor(i, window_radius), - window_ceil(i + 1, height, window_radius)): - if ii != i or jj != j: - d = image[i, j, 0] - image[ii, jj, 0] - s = d * d - for k in range(1, 3): - d = image[i, j, k] - image[ii, jj, k] - s += d * d - gval = 1.0 - np.sqrt(s) / sqrt_3 - - attack_strength = gval * state[ii, jj, 1] - - if attack_strength > defense_strength: - defense_strength = attack_strength - winning_colony = state[ii, jj, 0] - changes += 1 - - state_next[i, j, 0] = winning_colony - state_next[i, j, 1] = defense_strength - - return changes - - -benchmarks = ( - growcut_python, -) diff --git a/growcut/growcut_pythran.py b/growcut/growcut_pythran.py deleted file mode 100644 index c53755e..0000000 --- a/growcut/growcut_pythran.py +++ /dev/null @@ -1,30 +0,0 @@ -from growcut import growcut_python -from pythran import compile_pythrancode -from inspect import getsource -import imp - -# grab imports -imports = 'import numpy as np' -exports = ''' -#pythran export growcut_python(float[][][], float[][][], float[][][], int) -''' -modname = 'growcut_pythran' - -# grab the source from the original functions -sources = map(getsource, - (growcut_python.window_floor, - growcut_python.window_ceil, - growcut_python.growcut_python) - ) -source = '\n'.join(sources) - -# compile to a native module -native = compile_pythrancode( - modname, '\n'.join([imports, exports, source])) - -# load it -native = imp.load_dynamic(modname, native) - -benchmarks = ( - ("growcut_pythran", native.growcut_python), -) diff --git a/images/arc_distance_logscale.png b/images/arc_distance_logscale.png new file mode 100644 index 0000000..1c7096b Binary files /dev/null and b/images/arc_distance_logscale.png differ diff --git a/images/arc_distance_zoom_5x_best.png b/images/arc_distance_zoom_5x_best.png new file mode 100644 index 0000000..0a744c8 Binary files /dev/null and b/images/arc_distance_zoom_5x_best.png differ diff --git a/images/gemm_logscale.png b/images/gemm_logscale.png new file mode 100644 index 0000000..edeb732 Binary files /dev/null and b/images/gemm_logscale.png differ diff --git a/images/gemm_zoom_5x_best.png b/images/gemm_zoom_5x_best.png new file mode 100644 index 0000000..74c6e85 Binary files /dev/null and b/images/gemm_zoom_5x_best.png differ diff --git a/images/growcut.png b/images/growcut.png new file mode 100644 index 0000000..3424c9c Binary files /dev/null and b/images/growcut.png differ diff --git a/images/growcut_logscale.png b/images/growcut_logscale.png new file mode 100644 index 0000000..f798635 Binary files /dev/null and b/images/growcut_logscale.png differ diff --git a/images/growcut_zoom_100x_best.png b/images/growcut_zoom_100x_best.png new file mode 100644 index 0000000..890ca0f Binary files /dev/null and b/images/growcut_zoom_100x_best.png differ diff --git a/images/growcut_zoom_10x_best.png b/images/growcut_zoom_10x_best.png new file mode 100644 index 0000000..a4a6303 Binary files /dev/null and b/images/growcut_zoom_10x_best.png differ diff --git a/images/growcut_zoom_50x_best.png b/images/growcut_zoom_50x_best.png new file mode 100644 index 0000000..8fa0bc7 Binary files /dev/null and b/images/growcut_zoom_50x_best.png differ diff --git a/images/growcut_zoom_5x_best.png b/images/growcut_zoom_5x_best.png new file mode 100644 index 0000000..08f9711 Binary files /dev/null and b/images/growcut_zoom_5x_best.png differ diff --git a/images/julia.png b/images/julia.png new file mode 100644 index 0000000..3e50b87 Binary files /dev/null and b/images/julia.png differ diff --git a/images/julia_logscale.png b/images/julia_logscale.png new file mode 100644 index 0000000..07ce311 Binary files /dev/null and b/images/julia_logscale.png differ diff --git a/images/julia_zoom_100x_best.png b/images/julia_zoom_100x_best.png new file mode 100644 index 0000000..da01468 Binary files /dev/null and b/images/julia_zoom_100x_best.png differ diff --git a/images/julia_zoom_10x_best.png b/images/julia_zoom_10x_best.png new file mode 100644 index 0000000..0210ee1 Binary files /dev/null and b/images/julia_zoom_10x_best.png differ diff --git a/images/julia_zoom_50x_best.png b/images/julia_zoom_50x_best.png new file mode 100644 index 0000000..3fa35b0 Binary files /dev/null and b/images/julia_zoom_50x_best.png differ diff --git a/images/julia_zoom_5x_best.png b/images/julia_zoom_5x_best.png new file mode 100644 index 0000000..49a89e3 Binary files /dev/null and b/images/julia_zoom_5x_best.png differ diff --git a/images/pairwise.png b/images/pairwise.png new file mode 100644 index 0000000..bf7acd1 Binary files /dev/null and b/images/pairwise.png differ diff --git a/images/pairwise_logscale.png b/images/pairwise_logscale.png new file mode 100644 index 0000000..d8df142 Binary files /dev/null and b/images/pairwise_logscale.png differ diff --git a/images/pairwise_zoom_100x_best.png b/images/pairwise_zoom_100x_best.png new file mode 100644 index 0000000..0eda822 Binary files /dev/null and b/images/pairwise_zoom_100x_best.png differ diff --git a/images/pairwise_zoom_10x_best.png b/images/pairwise_zoom_10x_best.png new file mode 100644 index 0000000..246a864 Binary files /dev/null and b/images/pairwise_zoom_10x_best.png differ diff --git a/images/pairwise_zoom_50x_best.png b/images/pairwise_zoom_50x_best.png new file mode 100644 index 0000000..061d302 Binary files /dev/null and b/images/pairwise_zoom_50x_best.png differ diff --git a/images/pairwise_zoom_5x_best.png b/images/pairwise_zoom_5x_best.png new file mode 100644 index 0000000..794da2b Binary files /dev/null and b/images/pairwise_zoom_5x_best.png differ diff --git a/images/rosen_der_logscale.png b/images/rosen_der_logscale.png new file mode 100644 index 0000000..cc30120 Binary files /dev/null and b/images/rosen_der_logscale.png differ diff --git a/images/rosen_der_zoom_5x_best.png b/images/rosen_der_zoom_5x_best.png new file mode 100644 index 0000000..021bffd Binary files /dev/null and b/images/rosen_der_zoom_5x_best.png differ diff --git a/report/img/glyphicons-halflings-white.png b/img/glyphicons-halflings-white.png similarity index 100% rename from report/img/glyphicons-halflings-white.png rename to img/glyphicons-halflings-white.png diff --git a/report/img/glyphicons-halflings.png b/img/glyphicons-halflings.png similarity index 100% rename from report/img/glyphicons-halflings.png rename to img/glyphicons-halflings.png diff --git a/index.html b/index.html new file mode 100644 index 0000000..bcd16e7 --- /dev/null +++ b/index.html @@ -0,0 +1,1203 @@ + + + + + + + + + + + +
+
+ +
+ +

Results +

+ + + +
+

arc_distance + (source code) + +

+ +

+ + Plot for arc_distance + + Plot for arc_distance + +

+ + ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankFunction nameCold time (s)Warm time (s): best (stddev)Speedup
#1arc_distance_pythran_nested_for_loops + 0.084 + + 0.079 + (0.003)86.9
#2arc_distance_parakeet_for_loops + 0.378 + + 0.082 + (0.001)84.0
#3arc_distance_theano_broadcast + 0.090 + + 0.086 + (0.000)79.6
#4arc_distance_parakeet_comprehensions + 0.446 + + 0.092 + (0.002)74.9
#5arc_distance_numpy_broadcast + N/A + + 0.093 + (0.000)73.4
#6arc_distance_theano_alloc + 0.116 + + 0.107 + (0.001)64.1
#7arc_distance_numpy_tile + N/A + + 0.174 + (0.000)39.3
#8arc_distance_python_nested_for_loops + N/A + + 6.857 + (0.000)1.0
+ + +

+There were + + + +1 import error(s) + + + + + + + +while running this benchmark. +

+ + +
+ + +
+

growcut + (source code) + +

+ +

+ + Plot for growcut + + Plot for growcut + +

+ + ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankFunction nameCold time (s)Warm time (s): best (stddev)Speedup
#1growcut_parakeet + 0.421 + + 0.005 + (0.000)2147.5
#2growcut_cython + 0.009 + + 0.006 + (0.001)1615.0
#3growcut_pythran + 0.012 + + 0.010 + (0.002)1027.8
#4growcut_python + N/A + + 10.016 + (0.000)1.0
+ + +

+There were + + + +1 import error(s) + + + + + + + +while running this benchmark. +

+ + +
+ + +
+

julia + (source code) + +

+ +

+ + Plot for julia + + Plot for julia + +

+ + ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankFunction nameCold time (s)Warm time (s): best (stddev)Speedup
#1julia_pythran_for_loops + 0.003 + + 0.002 + (0.000)1865.0
#2julia_parakeet_for_loops + 0.433 + + 0.003 + (0.000)1341.1
#3julia_cython_for_loops + 0.004 + + 0.004 + (0.000)1194.4
#4julia_pyopencl + N/A + + 0.010 + (0.000)433.0
#5julia_python_numpy + N/A + + 0.187 + (0.000)24.1
#6julia_python_for_loops + N/A + + 4.497 + (0.000)1.0
+ + +

+There were + + + +1 import error(s) + + + + + + + +while running this benchmark. +

+ + +
+ + +
+

pairwise + (source code) + +

+ +

+ + Plot for pairwise + + Plot for pairwise + +

+ + ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankFunction nameCold time (s)Warm time (s): best (stddev)Speedup
#1pairwise_theano_blas_float32 + 0.001 + + 0.001 + (0.000)25834.8
#2pairwise_theano_blas_float64 + 0.001 + + 0.001 + (0.000)20523.4
#3pairwise_python_numpy_dot + N/A + + 0.002 + (0.000)9637.2
#4pairwise_pyopencl_cpu + N/A + + 0.004 + (0.000)5671.6
#5pairwise_cython_for_loops + 0.013 + + 0.012 + (0.000)1697.3
#6pairwise_parakeet_inner_numpy + 0.246 + + 0.013 + (0.002)1624.9
#7pairwise_parakeet_nested_for_loops + 0.183 + + 0.013 + (0.000)1610.8
#8pairwise_parakeet_comprehensions + 0.299 + + 0.014 + (0.001)1565.5
#9pairwise_pythran_nested_for_loops + 0.018 + + 0.016 + (0.002)1353.4
#10pairwise_theano_broadcast_float32 + 0.053 + + 0.034 + (0.002)631.5
#11pairwise_theano_broadcast_float64 + 0.045 + + 0.042 + (0.001)501.1
#12pairwise_python_broadcast_numpy + N/A + + 0.159 + (0.000)133.0
#13pairwise_python_inner_numpy + N/A + + 1.843 + (0.000)11.5
#14pairwise_python_nested_for_loops + N/A + + 21.182 + (0.000)1.0
+ + +

+There were + + + +1 import error(s) + + + + + + + +while running this benchmark. +

+ + +
+ + +
+

rosen_der + (source code) + +

+ +

+ + Plot for rosen_der + + Plot for rosen_der + +

+ + ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RankFunction nameCold time (s)Warm time (s): best (stddev)Speedup
#1rosen_der_loops_parakeet + 0.261 + + 0.004 + (0.000)2459.3
#2rosen_der_pythran + 0.005 + + 0.005 + (0.001)1990.5
#3rosen_der_cython + 0.008 + + 0.005 + (0.000)1888.2
#4rosen_der_theano_float32 + 0.012 + + 0.006 + (0.001)1587.4
#5rosen_der_theano_float64 + 0.015 + + 0.008 + (0.001)1285.0
#6rosen_der_numpy_parakeet + 0.374 + + 0.009 + (0.000)1124.9
#7rosen_der_numpy + N/A + + 0.045 + (0.000)227.3
#8rosen_der_python + N/A + + 10.181 + (0.000)1.0
+ + +

+There were + + + +1 import error(s) + + + + + + + +while running this benchmark. +

+ + +
+ + +

Error Summary +

+ + + + +
+

arc_distance +

+ + +
+

Benchmark loading errors +

+ +
+
arc_distance_numba +
+
AttributeError: 'NoneType' object has no attribute 'core'
+
+Traceback (most recent call last):
+  File "run_benchmarks.py", line 98, in find_benchmarks
+    module = __import__(abs_module_name, fromlist="dummy")
+  File "/Users/ogrisel/code/python-benchmarks/arc_distance/arc_distance_numba.py", line 5, in 
+    from numba import autojit
+  File "/usr/local/lib/python2.7/site-packages/numba/__init__.py", line 18, in 
+    from numba import utils, typesystem
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 102, in 
+    context = get_minivect_context()
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 100, in get_minivect_context
+    return NumbaContext()
+  File "/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py", line 140, in __init__
+    self.llvm_module = llvm.core.Module.new('default_module')
+AttributeError: 'NoneType' object has no attribute 'core'
+
+
+ +
+ + + + +
+ + + + +
+

growcut +

+ + +
+

Benchmark loading errors +

+ +
+
growcut_numba +
+
AttributeError: 'NoneType' object has no attribute 'core'
+
+Traceback (most recent call last):
+  File "run_benchmarks.py", line 98, in find_benchmarks
+    module = __import__(abs_module_name, fromlist="dummy")
+  File "/Users/ogrisel/code/python-benchmarks/growcut/growcut_numba.py", line 2, in 
+    from numba import autojit
+  File "/usr/local/lib/python2.7/site-packages/numba/__init__.py", line 18, in 
+    from numba import utils, typesystem
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 102, in 
+    context = get_minivect_context()
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 100, in get_minivect_context
+    return NumbaContext()
+  File "/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py", line 140, in __init__
+    self.llvm_module = llvm.core.Module.new('default_module')
+AttributeError: 'NoneType' object has no attribute 'core'
+
+
+ +
+ + + + +
+ + + + +
+

julia +

+ + +
+

Benchmark loading errors +

+ +
+
julia_numba +
+
AttributeError: 'NoneType' object has no attribute 'core'
+
+Traceback (most recent call last):
+  File "run_benchmarks.py", line 98, in find_benchmarks
+    module = __import__(abs_module_name, fromlist="dummy")
+  File "/Users/ogrisel/code/python-benchmarks/julia/julia_numba.py", line 2, in 
+    from numba import autojit
+  File "/usr/local/lib/python2.7/site-packages/numba/__init__.py", line 18, in 
+    from numba import utils, typesystem
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 102, in 
+    context = get_minivect_context()
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 100, in get_minivect_context
+    return NumbaContext()
+  File "/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py", line 140, in __init__
+    self.llvm_module = llvm.core.Module.new('default_module')
+AttributeError: 'NoneType' object has no attribute 'core'
+
+
+ +
+ + + + +
+ + + + +
+

pairwise +

+ + +
+

Benchmark loading errors +

+ +
+
pairwise_numba +
+
AttributeError: 'NoneType' object has no attribute 'core'
+
+Traceback (most recent call last):
+  File "run_benchmarks.py", line 98, in find_benchmarks
+    module = __import__(abs_module_name, fromlist="dummy")
+  File "/Users/ogrisel/code/python-benchmarks/pairwise/pairwise_numba.py", line 5, in 
+    from numba import autojit
+  File "/usr/local/lib/python2.7/site-packages/numba/__init__.py", line 18, in 
+    from numba import utils, typesystem
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 102, in 
+    context = get_minivect_context()
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 100, in get_minivect_context
+    return NumbaContext()
+  File "/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py", line 140, in __init__
+    self.llvm_module = llvm.core.Module.new('default_module')
+AttributeError: 'NoneType' object has no attribute 'core'
+
+
+ +
+ + + + +
+ + + + +
+

rosen_der +

+ + +
+

Benchmark loading errors +

+ +
+
rosen_der_numba +
+
AttributeError: 'NoneType' object has no attribute 'core'
+
+Traceback (most recent call last):
+  File "run_benchmarks.py", line 98, in find_benchmarks
+    module = __import__(abs_module_name, fromlist="dummy")
+  File "/Users/ogrisel/code/python-benchmarks/rosen_der/rosen_der_numba.py", line 5, in 
+    from numba import autojit
+  File "/usr/local/lib/python2.7/site-packages/numba/__init__.py", line 18, in 
+    from numba import utils, typesystem
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 102, in 
+    context = get_minivect_context()
+  File "/usr/local/lib/python2.7/site-packages/numba/utils.py", line 100, in get_minivect_context
+    return NumbaContext()
+  File "/usr/local/lib/python2.7/site-packages/numba/minivect/miniast.py", line 140, in __init__
+    self.llvm_module = llvm.core.Module.new('default_module')
+AttributeError: 'NoneType' object has no attribute 'core'
+
+
+ +
+ + + + +
+ + + +

Runtime Environment +

+ +

Hardware

+ +
    +
  • Platform: Darwin-13.0.0-x86_64-i386-64bit
  • +
  • CPU type: i386
  • +
  • CPU count: 4
  • +
+ +

Software

+
    +
  • Python version: 2.7.5
  • +
+ + + +
+
+
+ + + + \ No newline at end of file diff --git a/report/js/bootstrap.js b/js/bootstrap.js similarity index 100% rename from report/js/bootstrap.js rename to js/bootstrap.js diff --git a/report/js/bootstrap.min.js b/js/bootstrap.min.js similarity index 100% rename from report/js/bootstrap.min.js rename to js/bootstrap.min.js diff --git a/julia/__init__.py b/julia/__init__.py deleted file mode 100644 index e671153..0000000 --- a/julia/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# Authors: Serge Guelton -# License: MIT - -def make_env(cr=0.285, ci=0.01, N=200, bound=1.5, lim=1000., cutoff=1e6): - return (cr, ci, N, bound, lim, cutoff), {} diff --git a/julia/julia_cython.pyx b/julia/julia_cython.pyx deleted file mode 100644 index dcd4a20..0000000 --- a/julia/julia_cython.pyx +++ /dev/null @@ -1,62 +0,0 @@ -#----------------------------------------------------------------------------- -# Copyright (c) 2012, 2013, Enthought, Inc. -# All rights reserved. Distributed under the terms of the 2-clause BSD -# licence. See LICENSE.txt for details. -# -# Author: Kurt W. Smith -# Date: 26 March 2012 -#----------------------------------------------------------------------------- - -# --- Python std lib imports ------------------------------------------------- -import numpy as np - -# --- Cython cimports -------------------------------------------------------- -cimport cython -from libc.stdint cimport uint32_t, int32_t -from cython.parallel cimport prange - -# --- Ctypedefs -------------------------------------------------------- -ctypedef float real_t -ctypedef uint32_t uint_t -ctypedef int32_t int_t - -#----------------------------------------------------------------------------- -# Cython functions -#----------------------------------------------------------------------------- -cdef real_t abs_sq(real_t zr, real_t zi) nogil: - return zr * zr + zi * zi - -cdef uint_t kernel(real_t zr, real_t zi, - real_t cr, real_t ci, - real_t lim, real_t cutoff) nogil: - cdef: - uint_t count = 0 - real_t lim_sq = lim * lim - - while abs_sq(zr, zi) < lim_sq and count < cutoff: - zr, zi = zr * zr - zi * zi + cr, 2 * zr * zi + ci - count += 1 - return count - -@cython.boundscheck(False) -@cython.wraparound(False) -def julia_cython_for_loops(real_t cr, real_t ci, - uint_t N, real_t bound=1.5, - real_t lim=1000., real_t cutoff=1e6): - cdef: - uint_t[:,::1] julia - real_t[::1] grid - int_t i, j - real_t x - - julia = np.empty((N, N), dtype=np.uint32) - grid = np.asarray(np.linspace(-bound, bound, N), dtype=np.float32) - for i in prange(N, nogil=True): - x = grid[i] - for j in range(N): - julia[i,j] = kernel(x, grid[j], cr, ci, lim, cutoff) - return julia - -benchmarks = ( - julia_cython_for_loops, -) diff --git a/julia/julia_numba.py b/julia/julia_numba.py deleted file mode 100644 index fa7ef95..0000000 --- a/julia/julia_numba.py +++ /dev/null @@ -1,8 +0,0 @@ -from julia import julia_python -from numba import autojit - - -benchmarks = ( - ("julia_numba_for_loops", - autojit(julia_python.julia_python_for_loops)), -) diff --git a/julia/julia_parakeet.py b/julia/julia_parakeet.py deleted file mode 100644 index 87e8d16..0000000 --- a/julia/julia_parakeet.py +++ /dev/null @@ -1,15 +0,0 @@ -from julia import julia_python -from parakeet import jit - -benchmarks = ( - ("julia_parakeet_for_loops", - jit(julia_python.julia_python_for_loops)), - - # Can't run the NumPy version under Parakeet since the following - # features are not supported: - # - np.seterr - # - np.ogrid - # - complex numbers - #("julia_parakeet_numpy", - # jit(julia_python.julia_python_numpy)), -) diff --git a/julia/julia_pyopencl.py b/julia/julia_pyopencl.py deleted file mode 100644 index 2bd8909..0000000 --- a/julia/julia_pyopencl.py +++ /dev/null @@ -1,71 +0,0 @@ -# Authors: James Bergstra -# License: MIT - -import numpy as np -import pyopencl as cl - -mf = cl.mem_flags - -PROFILING = 0 - -_cache = {} - -def julia_cpu_prepare(cr, ci, N, bound, lim, cutoff): - ctx = cl.create_some_context() - if PROFILING: - queue = cl.CommandQueue( - ctx, - properties=cl.command_queue_properties.PROFILING_ENABLE) - else: - queue = cl.CommandQueue(ctx) - - grid_x = np.linspace(-bound, bound, N) - x0 = grid_x[0] - dx = grid_x[1] - grid_x[0] - limlim = lim ** 2 - - prg = cl.Program(ctx, """ - __kernel void foo(__global long *outbuf) - { - int ii = get_global_id(0); - int jj = get_global_id(1); - - double zr = %(x0)s + ii * %(dx)s; - double zi = %(x0)s + jj * %(dx)s; - long count = 0; - - while (((zr*zr + zi*zi) < %(limlim)s) && (count < %(cutoff)s)) - { - double tmp = zr * zr - zi * zi + %(cr)s; - zi = 2. * zr * zi + %(ci)s; - zr = tmp; - count += 1; - } - outbuf[ii * %(N)s + jj] = count; - } - - """ % locals()).build() - - return prg.foo, queue, ctx - - -def julia_pyopencl(cr, ci, N, bound=1.5, lim=4., cutoff=1e6): - output = np.empty((N, N), dtype='int64') - args = (cr, ci, N, bound, lim, cutoff) - try: - f, queue, ctx = _cache[args] - except: - f, queue, ctx = julia_cpu_prepare(*args) - _cache[args] = f, queue, ctx - dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, output.nbytes) - ev = f(queue, (N, N), None, dest_buf) - if PROFILING: - ev.wait() - print 'computation time', 1e-9 * (ev.profile.end - ev.profile.start) - cl.enqueue_copy(queue, output, dest_buf) - return output - - -benchmarks = ( - julia_pyopencl, -) diff --git a/julia/julia_python.py b/julia/julia_python.py deleted file mode 100644 index 671e4f1..0000000 --- a/julia/julia_python.py +++ /dev/null @@ -1,52 +0,0 @@ -# Authors: Kurt W. Smith, Serge Guelton -# License: MIT - -import numpy as np - -def kernel(zr, zi, cr, ci, lim, cutoff): - ''' Computes the number of iterations `n` such that - |z_n| > `lim`, where `z_n = z_{n-1}**2 + c`. - ''' - count = 0 - while ((zr*zr + zi*zi) < (lim*lim)) and count < cutoff: - zr, zi = zr * zr - zi * zi + cr, 2 * zr * zi + ci - count += 1 - return count - -def julia_python_for_loops(cr, ci, N, bound=1.5, lim=1000., cutoff=1e6): - ''' Pure Python calculation of the Julia set for a given `c`. No NumPy - array operations are used. - ''' - julia = np.empty((N, N), dtype=np.uint32) - grid_x = np.linspace(-bound, bound, N) - #"omp parallel for private(i, x, j, y)" - for i, x in enumerate(grid_x): - for j, y in enumerate(grid_x): - julia[i,j] = kernel(x, y, cr, ci, lim, cutoff=cutoff) - return julia - -def julia_python_numpy(cr, ci, N, bound=1.5, lim=4., cutoff=1e6): - ''' Pure Python calculation of the Julia set for a given `c` using NumPy - array operations. - ''' - c = cr + 1j * ci - orig_err = np.seterr() - np.seterr(over='ignore', invalid='ignore') - julia = np.zeros((N, N), dtype=np.uint32) - X, Y = np.ogrid[-bound:bound:N*1j, -bound:bound:N*1j] - iterations = X + Y * 1j - count = 1 - while not np.all(julia) and count < cutoff: - mask = np.logical_not(julia) & (np.abs(iterations) >= lim) - julia[mask] = count - count += 1 - iterations = iterations**2 + c - if count == cutoff: - julia[np.logical_not(julia)] = count - np.seterr(**orig_err) - return julia - -benchmarks = ( - julia_python_for_loops, - julia_python_numpy, -) diff --git a/julia/julia_pythran.py b/julia/julia_pythran.py deleted file mode 100644 index 98441e1..0000000 --- a/julia/julia_pythran.py +++ /dev/null @@ -1,37 +0,0 @@ -from julia import julia_python -from pythran import compile_pythrancode -from inspect import getsource -import re, imp - -# grab imports -imports = 'import numpy as np' -exports = ''' -#pythran export julia_python_for_loops(float, float, int, float, float, float) -''' -modname = 'julia_pythran' - -# grab the source from the original functions -sources = map(getsource, - (julia_python.julia_python_for_loops, - julia_python.kernel, - ) - ) -source = '\n'.join(sources) - -# patch them -source = re.sub(r'cutoff=cutoff', 'cutoff', source) -source = re.sub(r'dtype=np.uint32', 'np.uint32', source) -source = re.sub(r'#"omp', '"omp', source) - -# compile to a native module -native = compile_pythrancode(modname, - '\n'.join([imports, exports, source]), - cxxflags=['-O2', '-fopenmp']) - -# load it -native = imp.load_dynamic(modname, native) - -benchmarks = ( - ("julia_pythran_for_loops", - native.julia_python_for_loops), -) diff --git a/pairwise/__init__.py b/pairwise/__init__.py deleted file mode 100644 index ce70b6f..0000000 --- a/pairwise/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# Authors: Olivier Grisel -# License: MIT - -import numpy as np - - -def make_env(shape=(300, 150), seed=0, dtype=np.double): - rng = np.random.RandomState(seed) - data = np.asarray(rng.normal(size=shape), dtype=dtype) - return (data,), {} diff --git a/pairwise/pairwise_cython.pyx b/pairwise/pairwise_cython.pyx deleted file mode 100644 index bfa5884..0000000 --- a/pairwise/pairwise_cython.pyx +++ /dev/null @@ -1,28 +0,0 @@ -# Authors: Jake Vanderplas, Olivier Grisel -# License: MIT - -import numpy as np -cimport cython -from libc.math cimport sqrt - -@cython.boundscheck(False) -@cython.wraparound(False) -def pairwise_cython_for_loops(double[:, ::1] data): - cdef int n_samples = data.shape[0] - cdef int n_features = data.shape[1] - cdef double tmp, d - cdef double[:, ::1] distances = np.empty((n_samples, n_samples), - dtype=np.float64) - for i in range(n_samples): - for j in range(n_samples): - d = 0.0 - for k in range(n_features): - tmp = data[i, k] - data[j, k] - d += tmp * tmp - distances[i, j] = sqrt(d) - return np.asarray(distances) - - -benchmarks = ( - pairwise_cython_for_loops, -) \ No newline at end of file diff --git a/pairwise/pairwise_numba.py b/pairwise/pairwise_numba.py deleted file mode 100644 index e735625..0000000 --- a/pairwise/pairwise_numba.py +++ /dev/null @@ -1,11 +0,0 @@ -# Authors: Olivier Grisel -# License: MIT - -from pairwise import pairwise_python -from numba import autojit - - -benchmarks = ( - ("pairwise_numba_nested_for_loops", - autojit(pairwise_python.pairwise_python_nested_for_loops)), -) diff --git a/pairwise/pairwise_parakeet.py b/pairwise/pairwise_parakeet.py deleted file mode 100644 index 65295fd..0000000 --- a/pairwise/pairwise_parakeet.py +++ /dev/null @@ -1,18 +0,0 @@ -# Authors: Olivier Grisel -# License: MIT - -from pairwise import pairwise_python -from parakeet import jit -import numpy as np - -def pairwise_parakeet_comprehensions(data): - return np.array([[np.sqrt(np.sum((a-b)**2)) for b in data] for a in data]) - -benchmarks = ( - ("pairwise_parakeet_nested_for_loops", - jit(pairwise_python.pairwise_python_nested_for_loops)), - ("pairwise_parakeet_inner_numpy", - jit(pairwise_python.pairwise_python_inner_numpy)), - ("pairwise_parakeet_comprehensions", - jit(pairwise_parakeet_comprehensions)), -) diff --git a/pairwise/pairwise_pyopencl.py b/pairwise/pairwise_pyopencl.py deleted file mode 100644 index 6e4e40d..0000000 --- a/pairwise/pairwise_pyopencl.py +++ /dev/null @@ -1,105 +0,0 @@ -# Authors: James Bergstra -# License: MIT - -import numpy as np -import time -import pyopencl as cl -import numpy - -mf = cl.mem_flags - -PROFILING = 0 - -ctx = cl.create_some_context() -if PROFILING: - queue = cl.CommandQueue( - ctx, - properties=cl.command_queue_properties.PROFILING_ENABLE) -else: - queue = cl.CommandQueue(ctx) - -_cache = {} - -def pairwise_pyopencl_cpu_prepare(shp, dtype): - N, D = shp - ctype = { - 'float32': 'float', - 'float64': 'double', - }[str(dtype)] - - odd_d = "" if 0 == D % 2 else """ - __global %(ctype)s * a1 = (__global %(ctype)s*) (a); - %(ctype)s diff = a1[(n0 + 1) * %(D)s - 1] - a1[(m0 + 1) * %(D)s - 1]; - buf.s0 += diff * diff; - """ - - prg = cl.Program(ctx, """ - __kernel void lower(__global %(ctype)s2 *a, __global %(ctype)s *c) - { - for(int n0 = get_global_id(0); n0 < %(N)s; n0 += get_global_size(0)) - { - for(int m0 = get_global_id(1); m0 < %(N)s; m0 += get_global_size(1)) - { - if (n0 < m0) continue; - __global %(ctype)s2 *an = a + n0 * %(D)s / 2; - __global %(ctype)s2 *am = a + m0 * %(D)s / 2; - %(ctype)s2 buf = 0; - for (int d = 0; d < %(D)s/2; ++d) - { - %(ctype)s2 diff = am[d] - an[d]; - buf += diff * diff; - } - %(odd_d)s; - c[m0 * %(N)s + n0] = sqrt(buf.s0 + buf.s1); - } - } - } - __kernel void upper(__global %(ctype)s *a, __global %(ctype)s *c) - { - for(int n0 = get_global_id(0); n0 < %(N)s; n0 += get_global_size(0)) - { - for(int m0 = get_global_id(1); m0 < %(N)s; m0 += get_global_size(1)) - { - if (n0 >= m0) continue; - c[m0 * %(N)s + n0] = c[n0 * %(N)s + m0]; - } - } - } - """ % locals()).build() - - return prg.lower, prg.upper - - -comptimes = [] -def pairwise_pyopencl_cpu(data): - data = np.asarray(data, order='C') - N, D = data.shape - try: - lower, upper = _cache[(data.shape, data.dtype)] - except: - lower, upper = pairwise_pyopencl_cpu_prepare(data.shape, data.dtype) - _cache[(data.shape, data.dtype)] = lower, upper - data_buf = cl.Buffer(ctx, mf.COPY_HOST_PTR, hostbuf=data) - dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, N * N * data.dtype.itemsize) - try: - rval, _ = cl.enqueue_map_buffer(queue, dest_buf, cl.map_flags.READ, - offset=0, shape=(N, N), dtype=data.dtype) - need_copy = False - except TypeError: #OSX's OCL needs this? - rval = np.empty((N, N), dtype=data.dtype) - need_copy = True - lower(queue, (N, 1), (1, 1), data_buf, dest_buf) - upper(queue, (4, 4), (1, 1), data_buf, dest_buf) - if need_copy: - cl.enqueue_copy(queue, rval, dest_buf) - else: - queue.finish() - if PROFILING: - comptimes.append(1e-9 * (ev.profile.end - ev.profile.start)) - print 'computation time', min(comptimes) - return rval - - -benchmarks = ( - pairwise_pyopencl_cpu, -) diff --git a/pairwise/pairwise_python.py b/pairwise/pairwise_python.py deleted file mode 100644 index 21698fe..0000000 --- a/pairwise/pairwise_python.py +++ /dev/null @@ -1,45 +0,0 @@ -# Authors: Jake Vanderplas, Alex Rubinsteyn, Olivier Grisel -# License: MIT - -import numpy as np - - -def pairwise_python_nested_for_loops(data): - n_samples, n_features = data.shape - distances = np.empty((n_samples, n_samples), dtype=data.dtype) - #"omp parallel for private(j, d, k, tmp)" - for i in range(n_samples): - for j in range(n_samples): - d = 0.0 - for k in range(n_features): - tmp = data[i, k] - data[j, k] - d += tmp * tmp - distances[i, j] = np.sqrt(d) - return distances - - -def pairwise_python_inner_numpy(data): - n_samples = data.shape[0] - result = np.empty((n_samples, n_samples), dtype=data.dtype) - for i in xrange(n_samples): - for j in xrange(n_samples): - result[i, j] = np.sqrt(np.sum((data[i, :] - data[j, :]) ** 2)) - return result - - -def pairwise_python_broadcast_numpy(data): - return np.sqrt(((data[:, None, :] - data) ** 2).sum(axis=2)) - - -def pairwise_python_numpy_dot(data): - X_norm_2 = (data ** 2).sum(axis=1) - dists = np.sqrt(2 * X_norm_2 - np.dot(data, data.T)) - return dists - - -benchmarks = ( - pairwise_python_nested_for_loops, - pairwise_python_inner_numpy, - pairwise_python_broadcast_numpy, - pairwise_python_numpy_dot, -) diff --git a/pairwise/pairwise_pythran.py b/pairwise/pairwise_pythran.py deleted file mode 100644 index 28d6796..0000000 --- a/pairwise/pairwise_pythran.py +++ /dev/null @@ -1,34 +0,0 @@ -# Authors: Serge "Sans Paille" Guelton -# License: MIT - -from pairwise import pairwise_python -from pythran import compile_pythrancode -from inspect import getsource -import re -import imp - -# grab imports -imports = 'import numpy as np' -exports = '#pythran export pairwise_python_nested_for_loops(float[][])' -modname = 'pairwise_pythran' - -# grab the source from the original function -source = getsource(pairwise_python.pairwise_python_nested_for_loops) - -# a few rewriting rules to prune unsupported features -source = re.sub(r'dtype=data.dtype', 'np.double', source) -source = re.sub(r'#"omp', '"omp', source) - -# compile to a native module -native = compile_pythrancode(modname, - '\n'.join([imports, exports, source]), - cxxflags=['-O2', '-fopenmp'] - ) - -# load it -native = imp.load_dynamic(modname, native) - -benchmarks = ( - ("pairwise_pythran_nested_for_loops", - native.pairwise_python_nested_for_loops), -) diff --git a/pairwise/pairwise_theano.py b/pairwise/pairwise_theano.py deleted file mode 100644 index 367f545..0000000 --- a/pairwise/pairwise_theano.py +++ /dev/null @@ -1,38 +0,0 @@ -# Authors: James Bergstra -# License: MIT -import theano -import theano.tensor as TT - - -def pairwise_theano_tensor_prepare(dtype): - X = TT.matrix(dtype=str(dtype)) - dists = TT.sqrt( - TT.sum( - TT.sqr(X[:, None, :] - X), - axis=2)) - name = 'pairwise_theano_broadcast_' + dtype - rval = theano.function([X], - theano.Out(dists, borrow=True), - allow_input_downcast=True, name=name) - rval.__name__ = name - return rval - - -def pairwise_theano_blas_prepare(dtype): - X = TT.matrix(dtype=str(dtype)) - X_norm_2 = (X ** 2).sum(axis=1) - dists = TT.sqrt(2 * X_norm_2 - TT.dot(X, X.T)) - name = 'pairwise_theano_blas_' + dtype - rval = theano.function([X], - theano.Out(dists, borrow=True), - allow_input_downcast=True, name=name) - rval.__name__ = name - return rval - - -benchmarks = ( - pairwise_theano_tensor_prepare('float32'), - pairwise_theano_tensor_prepare('float64'), - pairwise_theano_blas_prepare('float32'), - pairwise_theano_blas_prepare('float64'), -) diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 0e1e2ae..0000000 --- a/requirements.txt +++ /dev/null @@ -1,14 +0,0 @@ -numpy -cython -numba -treelike -parakeet -Theano -networkx -ply -pythran -cython -memory_profiler -jinja2 -ghp-import - diff --git a/rosen_der/__init__.py b/rosen_der/__init__.py deleted file mode 100644 index 04529d1..0000000 --- a/rosen_der/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Authors: Serge Guelton -# License: MIT -'''Compute the derivative of the Rosenbrock function - -This functions tests the ability of compiler to fuse numpy operators, use -negative indexing and handle memory view instead of making copies when slicing. - -see also http://en.wikipedia.org/wiki/Rosenbrock_function -''' - -import numpy as np - - -def make_env(N=1000000): - rng = np.random.RandomState(42) - x = rng.rand(N) - return (x,), {} diff --git a/rosen_der/rosen_der_cython.pyx b/rosen_der/rosen_der_cython.pyx deleted file mode 100644 index 2c1f244..0000000 --- a/rosen_der/rosen_der_cython.pyx +++ /dev/null @@ -1,23 +0,0 @@ -# Authors: Serge Guelton -# License: MIT - -import numpy as np -cimport cython - -@cython.boundscheck(False) -@cython.wraparound(False) -def rosen_der_cython(double[:] x): - cdef int n = x.shape[0] - cdef int i - cdef double[:] der = np.zeros_like(x) - - der[0] = -400*x[0]*(x[1]-x[0]**2) - 2*(1-x[0]) - for i in range(1,n-1): - der[i] = (200*(x[i] - x[i - 1]**2) - - 400 * (x[i + 1] - x[i]**2)*x[i] - - 2 * (1 - x[i])) - der[n - 1] = 200 * (x[-1] - x[-2]**2) - return der - - -benchmarks = (rosen_der_cython,) diff --git a/rosen_der/rosen_der_numba.py b/rosen_der/rosen_der_numba.py deleted file mode 100644 index 63bbf31..0000000 --- a/rosen_der/rosen_der_numba.py +++ /dev/null @@ -1,12 +0,0 @@ -# Authors: Serge Guelton -# License: MIT - -from rosen_der import rosen_der_python -from numba import autojit - - -# segfaults... -#benchmarks = ( -# ("rosen_der_numba", -# autojit(rosen_der_python.rosen_der_python)), -#) diff --git a/rosen_der/rosen_der_parakeet.py b/rosen_der/rosen_der_parakeet.py deleted file mode 100644 index 1799b37..0000000 --- a/rosen_der/rosen_der_parakeet.py +++ /dev/null @@ -1,10 +0,0 @@ -# Authors: Serge Guelton -# License: MIT - -from rosen_der import rosen_der_python -from parakeet import jit - -benchmarks = ( - ("rosen_der_loops_parakeet", jit(rosen_der_python.rosen_der_python)), - ("rosen_der_numpy_parakeet", jit(rosen_der_python.rosen_der_numpy)) - ) diff --git a/rosen_der/rosen_der_python.py b/rosen_der/rosen_der_python.py deleted file mode 100644 index b4d5dce..0000000 --- a/rosen_der/rosen_der_python.py +++ /dev/null @@ -1,33 +0,0 @@ -# Authors: Travis E. Oliphant (numpy version), Serge Guelton (python version) -# License: BSD -# Source: https://github.com/scipy/scipy/blob/master/scipy/optimize/optimize.py -import numpy - - -def rosen_der_numpy(x): - xm = x[1:-1] - xm_m1 = x[:-2] - xm_p1 = x[2:] - der = numpy.zeros_like(x) - der[1:-1] = (+ 200 * (xm - xm_m1 ** 2) - - 400 * (xm_p1 - xm ** 2) * xm - - 2 * (1 - xm)) - der[0] = -400 * x[0] * (x[1] - x[0] ** 2) - 2 * (1 - x[0]) - der[-1] = 200 * (x[-1] - x[-2] ** 2) - return der - - -def rosen_der_python(x): - n = x.shape[0] - der = numpy.zeros_like(x) - - for i in range(1, n - 1): - der[i] = (+ 200 * (x[i] - x[i - 1] ** 2) - - 400 * (x[i + 1] - - x[i] ** 2) * x[i] - - 2 * (1 - x[i])) - der[0] = -400 * x[0] * (x[1] - x[0] ** 2) - 2 * (1 - x[0]) - der[-1] = 200 * (x[-1] - x[-2] ** 2) - return der - -benchmarks = (rosen_der_numpy, rosen_der_python) diff --git a/rosen_der/rosen_der_pythran.py b/rosen_der/rosen_der_pythran.py deleted file mode 100644 index 52271c6..0000000 --- a/rosen_der/rosen_der_pythran.py +++ /dev/null @@ -1,35 +0,0 @@ -# Authors: Serge Guelton -# License: MIT - -from rosen_der import rosen_der_python -from pythran import compile_pythrancode -from inspect import getsource -import imp - -# grab imports -imports = 'import numpy' -exports = ''' -#pythran export rosen_der_numpy(float []) -''' -modname = 'rosen_der_pythran' - -# grab the source from the original functions -sources = map(getsource, - (rosen_der_python.rosen_der_numpy,) - ) -source = '\n'.join(sources) - -# patch them - -# compile to a native module -native = compile_pythrancode(modname, - '\n'.join([imports, exports, source]), - cxxflags=['-O2', '-fopenmp']) - -# load it -native = imp.load_dynamic(modname, native) - -benchmarks = ( - ("rosen_der_pythran", - native.rosen_der_numpy), -) diff --git a/rosen_der/rosen_der_theano.py b/rosen_der/rosen_der_theano.py deleted file mode 100644 index 330cc68..0000000 --- a/rosen_der/rosen_der_theano.py +++ /dev/null @@ -1,31 +0,0 @@ -# Authors: Travis E. Oliphant (numpy version), Serge Guelton (python version) -# James Bergstra (theano version) -# License: BSD -# Source: https://github.com/scipy/scipy/blob/master/scipy/optimize/optimize.py -import theano -from theano import tensor as TT - - -def rosen_der_theano_prepare(dtype): - x = TT.vector(dtype=dtype) - xm = x[1:-1] - xm_m1 = x[:-2] - xm_p1 = x[2:] - der = TT.zeros_like(x) - der = TT.set_subtensor( - der[1:-1], - (+ 200 * (xm - xm_m1 ** 2) - - 400 * (xm_p1 - xm ** 2) * xm - - 2 * (1 - xm))) - der = TT.set_subtensor( - der[0], - -400 * x[0] * (x[1] - x[0] ** 2) - 2 * (1 - x[0])) - der = TT.set_subtensor( - der[-1], - 200 * (x[-1] - x[-2] ** 2)) - rval = theano.function([x], der, allow_input_downcast=True) - rval.__name__ = 'rosen_der_theano_' + dtype - return rval - -benchmarks = (rosen_der_theano_prepare('float32'), - rosen_der_theano_prepare('float64')) diff --git a/run_benchmarks.py b/run_benchmarks.py deleted file mode 100644 index 6af8799..0000000 --- a/run_benchmarks.py +++ /dev/null @@ -1,365 +0,0 @@ -# Authors: Olivier Grisel -# License: MIT -from __future__ import print_function - -import argparse -try: - from collections import OrderedDict -except: - from ordereddict import OrderedDict -import json -import os -import traceback -from time import time -import logging - -from jinja2 import Template -import numpy as np -import matplotlib.pyplot as plt - -# imports for machine stats -import multiprocessing -import platform - -# use this to check whether benchmark needs warmup -from types import FunctionType - -try: - # Use automated Cython support when available - import pyximport - pyximport.install(setup_args={'include_dirs': np.get_include()}) -except ImportError: - pass - -log = logging.getLogger("run_benchmarks") - -REPORT_FILENAME = 'report/index.html' -DATA_FILENAME = 'report/benchmark_results.json' - -GROUP_URL_PATTERN = ("https://github.com/numfocus/python-benchmarks/" - "tree/master/%s") - -MODULE_URL_PATTERN = ("https://github.com/numfocus/python-benchmarks/" - "tree/master/%s") - -ABOUT_URL = ("https://github.com/numfocus/python-benchmarks/blob/master/" - "README.md#motivation") - -GITHUB_REPO_URL = "https://github.com/numfocus/python-benchmarks" - - -MAIN_REPORT_TEMPLATE_FILENAME = "templates/index.html" - -LOG_FORMAT = '%(asctime)s %(levelname)-8s %(name)-8s %(message)s' - - -def find_benchmarks(folders=None, platforms=None): - """Collect benchmarks collable and shared environment initializers.""" - - benchmark_groups = [] - - if folders is None: - here = os.path.dirname(os.path.abspath(__file__)) - dir_content = os.listdir(here) - folders = [f for f in dir_content - if (os.path.isdir(f) and - os.path.exists(os.path.join(f, '__init__.py')))] - folders.sort() - - for folder in folders: - group_name = os.path.basename(folder) - collected_benchmarks = [] - modules_in_error = [] - - pkg = __import__(group_name, fromlist="dummy") - - benchmark_groups.append(OrderedDict([ - ('name', group_name), - ('make_env', getattr(pkg, 'make_env', None)), - ('benchmarks', collected_benchmarks), - ('import_errors', modules_in_error), - ])) - - for module_filename in sorted(os.listdir(folder)): - module_name, ext = os.path.splitext(module_filename) - if ext and ext not in ('.py', '.so', '.dll', '.pyx'): - continue - - if not module_name.startswith(group_name + "_"): - continue - - platform_name = module_name[len(group_name) + 1:] - if platforms is not None and platform_name not in platforms: - continue - - abs_module_name = "%s.%s" % (group_name, module_name) - - try: - module = __import__(abs_module_name, fromlist="dummy") - except Exception as e: - error_type = type(e).__name__ - error_message = str(e) - log.error("Failed to load %s: %s: %s", abs_module_name, - type(e).__name__, e) - tb = traceback.format_exc() - loading_error = OrderedDict([ - ('name', module_name), - ('error_type', error_type), - ('error_message', error_message), - ('traceback', tb), - ]) - modules_in_error.append(loading_error) - module = None - - module_source = "%s/%s" % (group_name, module_filename) - for benchmark in getattr(module, 'benchmarks', ()): - if callable(benchmark): - collected_benchmarks.append( - (module_source, benchmark.__name__, benchmark)) - elif isinstance(benchmark, tuple) and len(benchmark) == 2: - collected_benchmarks.append((module_source,) + benchmark) - else: - raise ValueError("Found invalid benchmark %r in %s" % - benchmark, module_name) - return benchmark_groups - - - -def run_benchmark(name, func, args, kwargs, memory=False, n_runs=5, - slow_threshold=1): - """Call a function with the provided arguments""" - # TODO: find a way to use memory_profiler on non-python, builtin functions - def time_once(): - tic = time() - func(*args, **kwargs) - toc = time() - return toc - tic - - first_timing = time_once() - # if we're running a user-defined pure Python function, assume there's no warmup - if isinstance(func, FunctionType): - cold = None - warm = first_timing - all_warm_timings = [first_timing] - else: - # Give a warm/cold time for every benchmark, even if there's no JIT - # Take the best time of several runs for fast executions - other_timings = [] - for i in range(n_runs - 1): - t = time_once() - other_timings.append(t) - - all_warm_timings = other_timings - best_warm_timing = np.min(all_warm_timings) - cold = first_timing - warm = best_warm_timing - - return OrderedDict([ - ('name', name), - ('cold_time', cold), - ('warm_time', warm), - ('all_warm_times', all_warm_timings), - ('std_warm_times', np.std(all_warm_timings)), - ]) - - -def run_benchmarks(folders=None, platforms=None, catch_errors=True, - memory=True): - collected = find_benchmarks(folders=folders, platforms=platforms) - - bench_results = [] - - for group in collected: - log.info("Running benchmark group %s", group['name']) - make_env = group.get('make_env') - args, kwargs = make_env() if make_env is not None else ((), {}) - - records = [] - runtime_errors = [] - for module_source, name, func in group['benchmarks']: - log.info("Benchmarking %s", name) - module_source_url = MODULE_URL_PATTERN % module_source - try: - record = run_benchmark(name, func, args, kwargs, memory=memory) - record['source_url'] = module_source_url - records.append(record) - log.info("%s: cold: %s, warm: %s", - name, record['cold_time'], record['warm_time']) - except Exception as e: - if catch_errors: - error_type = type(e).__name__ - error_message = str(e) - tb = traceback.format_exc() - runtime_error = OrderedDict([ - ('name', name), - ('source_url', module_source_url), - ('error_type', error_type), - ('error_message', error_message), - ('traceback', tb), - ]) - runtime_errors.append(runtime_error) - log.warn("Could not run %s: %s: %s", name, - error_type, e) - log.debug(tb) - else: - raise - - # TODO: add special support for PyPy with a sub-process - - # Rerank records by ascending warm time: - if len(records) > 0: - records.sort(key=lambda r: r['warm_time']) - slowest_time = records[-1]['warm_time'] - for rank, record in enumerate(records): - record['rank'] = rank + 1 # start at 1 instead of 0 - record['speedup'] = slowest_time / record['warm_time'] - - bench_results.append(OrderedDict([ - ('group_name', group['name']), - ('source_url', GROUP_URL_PATTERN % group['name']), - ('records', records), - ('runtime_errors', runtime_errors), - ('import_errors', group['import_errors']), - ])) - return bench_results - - -def plot_group(group, width=0.5, zoom_scale=None, log_scale=False, - figsize=(12, 6), folder="report/images"): - records = group['records'] - if len(records) == 0: - return - - name = group['group_name'] - for r in records: - r['max_time'] = r['cold_time'] or r['warm_time'] - - labels = [r['name'][len(name) + 1:] for r in records] - best_time = records[0]['warm_time'] - warm_time = np.asarray([r['warm_time'] for r in records]) - std = np.asarray([r['std_warm_times'] for r in records]) - max_time = np.asarray([r['cold_time'] or r['warm_time'] for r in records]) - - if log_scale: - bottom = best_time / 2. - else: - bottom = 0.0 - - plt.figure(figsize=figsize) - ind = np.arange(len(labels)) - p1 = plt.bar(ind, max_time, width, color='g', alpha=0.2, log=log_scale, - bottom=bottom) - p2 = plt.bar(ind, warm_time, width, yerr=[np.zeros(len(std)), std], - color='g', ecolor='g', alpha=0.4, log=log_scale, - bottom=bottom) - - title = group['group_name'] - if log_scale: - title += " (log scale)" - elif zoom_scale: - title += " (zoom %dx best time)" % zoom_scale - plt.title(title) - plt.ylabel('Time (s)') - plt.xticks(ind + width / 2., labels, rotation=10) - - if log_scale: - plt.yscale('log') - plt.ylim(bottom, None) - else: - if zoom_scale: - plt.ylim((0, warm_time[0] * zoom_scale)) - else: - plt.ylim(0, max(max_time) * 1.1) - - plt.legend((p2[0], p1[0]), - ('Execution time', 'Cold startup overhead'), - loc='upper left') - - # Save the image in the report folder - if not os.path.exists(folder): - os.makedirs(folder) - - if log_scale: - suffix = "_logscale" - elif zoom_scale: - suffix = "_zoom_%dx_best" % zoom_scale if zoom_scale else "" - else: - suffix = "" - - filename = "%s%s.png" % (group['group_name'], suffix) - filepath = os.path.join(folder, filename) - plt.savefig(filepath) - - # Make it available to the template engine - group.setdefault('plot_filenames', []).append(filename) - - -def build_report(bench_data, report_filename=REPORT_FILENAME, - data_filename=DATA_FILENAME): - for group in bench_data['benchmark_results']: - plot_group(group, zoom_scale=5, log_scale=False) - plot_group(group, zoom_scale=None, log_scale=True) - with open(MAIN_REPORT_TEMPLATE_FILENAME, 'rb') as f: - rendered = Template(f.read()).render( - bench_results=bench_data['benchmark_results'], - bech_env=bench_data['benchmark_environment'], - about_url=ABOUT_URL, - github_repo_url=GITHUB_REPO_URL, - json_data_url=os.path.basename(bench_data_filename), - sysinfo = { - 'platform': platform.platform(), - 'python_version': platform.python_version(), - 'processor' : platform.processor(), - 'cpu_count' : multiprocessing.cpu_count() - } - ) - report_filename = 'report/index.html' - log.info("Writing report to: %s", report_filename) - with open(report_filename, 'wb') as f: - f.write(rendered) - - -def parse_args(args): - parser = argparse.ArgumentParser() - parser.add_argument('--no-catch-errors', action='store_true', - default=False) - parser.add_argument('--folders', nargs='*', default=None) - parser.add_argument('--platforms', nargs='*', default=None) - parser.add_argument('--ignore-data', action='store_true', default=False) - parser.add_argument('--log-level', default='INFO') - parser.add_argument('--open-report', action='store_true', - default=False) - return parser.parse_args(args) - -if __name__ == "__main__": - import sys - options = parse_args(sys.argv[1:]) - - log_level = getattr(logging, options.log_level.upper(), logging.INFO) - logging.basicConfig(level=log_level, format=LOG_FORMAT) - - bench_data_filename = DATA_FILENAME - if os.path.exists(bench_data_filename) and not options.ignore_data: - log.info("Loading bench data from: %s", bench_data_filename) - with open(bench_data_filename, 'rb') as f: - bench_data = json.load(f) - else: - bench_results = run_benchmarks( - catch_errors=not options.no_catch_errors, - folders=options.folders, - platforms=options.platforms, - ) - bench_environment = {} # TODO - bench_data = OrderedDict([ - ('benchmark_results', bench_results), - ('benchmark_environment', bench_environment), - ]) - log.info("Writing bench data to: %s", bench_data_filename) - with open(bench_data_filename, 'wb') as f: - json.dump(bench_data, f, indent=2) - report_filename = os.path.abspath('report/index.html') - build_report(bench_data, data_filename=bench_data_filename, - report_filename=report_filename) - if options.open_report: - import webbrowser - webbrowser.open("file://" + report_filename) diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index 2805970..0000000 --- a/templates/index.html +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - - - - - - -
-
-
- - - -
-
- -

Results -

- -{% for result in bench_results %} - -
-

{{ result.group_name }} - (source code) - -

- -

- {% for filename in result.plot_filenames %} - Plot for {{ result.group_name }} - {% endfor %} -

- - -- - - - - - - - - - - - - - - - - - -{% for record in result.records %} - - - - - - - - -{% endfor %} - -
RankFunction nameCold time (s)Warm time (s): best (stddev)Speedup
#{{ record.rank }}{{ record.name }}{% if record.cold_time %} - {{ "{:0.3f}".format(record.cold_time) }} - {% else %} - N/A - {% endif %} - {{ "{:0.3f}".format(record.warm_time) }} - ({{ "{:0.3f}".format(record.std_warm_times)}}){{ "{:0.1f}".format(record.speedup) }}
- -{%if result.import_errors or result.runtime_errors %} -

-There were - -{%if result.import_errors %} - -{{ result.import_errors|length }} import error(s) - -{% endif %} - -{%if result.import_errors and result.runtime_errors %} -and -{% endif %} - -{%if result.runtime_errors %} - -{{ result.runtime_errors|length }} execution error(s) - -{% endif %} - -while running this benchmark. -

-{% else %} - -

- All methods were benchmarked without any error. -

- -{% endif %} - -
-{% endfor %} - -

Error Summary -

- -{% for result in bench_results %} -{%if result.import_errors or result.runtime_errors %} - -
-

{{ result.group_name }} -

- -{%if result.import_errors %} -
-

Benchmark loading errors -

- {% for import_error in result.import_errors %} -
-
{{ import_error.name }} -
-
{{ import_error.error_type }}: {{ import_error.error_message }}
-
-{{ import_error.traceback }}
-
- {% endfor %} -
-{% endif %} - -{%if result.runtime_errors %} -
-

Benchmark execution errors -

- {% for runtime_error in result.runtime_errors %} -
-
{{ runtime_error.name }} -
-
{{ runtime_error.error_type }}: {{ runtime_error.error_message|e }}
-
-{{ runtime_error.traceback|e }}
-
- {% endfor %} -
-{% endif %} - -
-{% endif %} -{% endfor %} - -

Runtime Environment -

- -

Hardware

- -
    -
  • Platform: {{sysinfo.platform}}
  • -
  • CPU type: {{sysinfo.processor}}
  • -
  • CPU count: {{sysinfo.cpu_count}}
  • -
- -

Software

-
    -
  • Python version: {{sysinfo.python_version}}
  • -
- - - -
-
-
- - - -