{ "metadata": { "name": "", "signature": "sha256:105d83276a3e465a46a5ba91c094fd514b8fa6781ca3b82fafb0b745dc16cd15" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#VIII-Benchmarks\n", "\n", "\n", "Lecturer:*Jos\u00e9 Pedro Silva*[1](http://www-num.math.uni-wuppertal.de/en/amna/people/jose-pedro-silva.html) - [silva_at_math.uni-wuppertal.de](mailto:silva_at_math.uni-wuppertal.de)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*The first benchmark in this notebook first appeared as a*\n", "[*post*](http://jakevdp.github.io/blog/2012/08/24/numba-vs-cython/)\n", "*by Jake Vanderplas on the blog*\n", "[*Pythonic Perambulations*](http://jakevdp.github.io)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "###Index\n", "\n", "- [Pairwise Distance](#Pairwise-Distance)\n", " - [NumPy Broadcasting](#Numpy-broadcasting)\n", " - [Pure Python](#Pure-python)\n", " - [Numba](#Numba)\n", " - [Cython](#Cython)\n", " - [Parakeet](#Parakeet)\n", " - [Fortran/F2Py](#Fortran-f2py)\n", " - [SciPy Euclidean Distance](#Scipy-pairwise-distances)\n", " - [Scikit-learn Distance](#Scikitlearn-pairwise-distances)\n", "\n", "- [1D Black-Scholes](#1D Black-Scholes)\n", " - [Pure Python](#1DBS-PurePython)\n", " - [Numba](#1DBS-Numba)\n", " - [Cython](#1DBS-Cython)\n", " - [Matlab](#1DBS-MATLAB)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Pairwise distance" ] }, { "cell_type": "code", "collapsed": false, "input": [ "import numpy as np\n", "import matplotlib as mpl\n", "import matplotlib.pyplot as plt\n", "X = np.random.random((1000, 3))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [ "def parse_cap(s):\n", " return cap.stdout.split(' ')[-4:-2]\n", "Benchs = ['python\\nloop', 'numpy\\nbroadc.', 'sklearn', 'fortran/\\nf2py', 'scipy', 'cython', 'numba','parakeet']\n", "Benchmarks = dict((bench,0) for bench in Benchs)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 2 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll start by defining the array which we'll use for the benchmarks: one thousand points in\n", "three dimensions." ] }, { "cell_type": "code", "collapsed": false, "input": [ "np.show_config()" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "lapack_opt_info:\n", " libraries = ['mkl_lapack95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n", " library_dirs = ['/home/jpsilva/anaconda/lib']\n", " define_macros = [('SCIPY_MKL_H', None)]\n", " include_dirs = ['/home/jpsilva/anaconda/include']\n", "blas_opt_info:\n", " libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n", " library_dirs = ['/home/jpsilva/anaconda/lib']\n", " define_macros = [('SCIPY_MKL_H', None)]\n", " include_dirs = ['/home/jpsilva/anaconda/include']\n", "openblas_lapack_info:\n", " NOT AVAILABLE\n", "lapack_mkl_info:\n", " libraries = ['mkl_lapack95_lp64', 'mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n", " library_dirs = ['/home/jpsilva/anaconda/lib']\n", " define_macros = [('SCIPY_MKL_H', None)]\n", " include_dirs = ['/home/jpsilva/anaconda/include']\n", "blas_mkl_info:\n", " libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n", " library_dirs = ['/home/jpsilva/anaconda/lib']\n", " define_macros = [('SCIPY_MKL_H', None)]\n", " include_dirs = ['/home/jpsilva/anaconda/include']\n", "mkl_info:\n", " libraries = ['mkl_intel_lp64', 'mkl_intel_thread', 'mkl_core', 'iomp5', 'pthread']\n", " library_dirs = ['/home/jpsilva/anaconda/lib']\n", " define_macros = [('SCIPY_MKL_H', None)]\n", " include_dirs = ['/home/jpsilva/anaconda/include']\n" ] } ], "prompt_number": 3 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Numpy Function With Broadcasting" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll start with a typical numpy broadcasting approach to this problem. Numpy\n", "broadcasting is an abstraction that allows loops over array indices to be\n", "executed in compiled C. For many applications, this is extremely fast and efficient.\n", "Unfortunately, there is a problem with broadcasting approaches that comes up here:\n", "it ends up allocating hidden temporary arrays which can eat up memory and cause\n", "computational overhead. Nevertheless, it's a good comparison to have. The function\n", "looks like this:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "\n", "def pairwise_numpy(X):\n", " return np.sqrt(((X[:, None, :] - X) ** 2).sum(-1))\n", "%timeit pairwise_numpy(X)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 6 }, { "cell_type": "code", "collapsed": false, "input": [ "Benchmarks['numpy\\nbroadc.'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "10 loops, best of 3: 39.8 ms per loop\n", "\n" ] } ], "prompt_number": 7 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Pure Python Function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A loop-based solution avoids the overhead associated with temporary arrays,\n", "and can be written like this:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def pairwise_python(X):\n", " M = X.shape[0]\n", " N = X.shape[1]\n", " D = np.empty((M, M), dtype=np.float)\n", " for i in range(M):\n", " for j in range(M):\n", " d = 0.0\n", " for k in range(N):\n", " tmp = X[i, k] - X[j, k]\n", " d += tmp * tmp\n", " D[i, j] = np.sqrt(d)\n", " return D" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 8 }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "%timeit pairwise_python(X)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 9 }, { "cell_type": "code", "collapsed": false, "input": [ "Benchmarks['python\\nloop'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "1 loops, best of 3: 2.6 s per loop\n", "\n" ] } ], "prompt_number": 10 }, { "cell_type": "markdown", "metadata": {}, "source": [ "As we see, it is over 100 times slower than the numpy broadcasting approach!\n", "This is due to Python's dynamic type checking, which can drastically slow down\n", "nested loops. With these two solutions, we're left with a tradeoff between\n", "efficiency of computation and efficiency of memory usage. This is where tools\n", "like Numba and Cython become vital" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Numba Wrapper" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Numba](http://numba.pydata.org/) is an LLVM compiler for python code, which\n", "allows code written in Python to be converted to highly efficient compiled code\n", "in real-time. \n", "Numba is extremely simple to use. We just wrap our python function with ``autojit`` (JIT stands\n", "for \"just in time\" compilation) to automatically create an efficient, compiled version of the function:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Note** Somehow, importing pylab breaks numba" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "\n", "import numba\n", "from numba import double, jit,autojit\n", "\n", "@jit\n", "def pairwise_numba(X):\n", " M = X.shape[0]\n", " N = X.shape[1]\n", " D = np.empty((M, M))#, dtype=np.float)\n", " for i in range(M):\n", " for j in range(M):\n", " d = 0.0\n", " for k in range(N):\n", " tmp = X[i, k] - X[j, k]\n", " d += tmp * tmp\n", " D[i, j] = np.sqrt(d)\n", " return D\n", "\n", "%timeit pairwise_numba(X)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 14 }, { "cell_type": "code", "collapsed": false, "input": [ "Benchmarks['numba'] = parse_cap(cap)\n", "print numba.__version__, cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "0.15.1 1 loops, best of 3: 2.94 s per loop\n", "\n" ] } ], "prompt_number": 15 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Optimized Cython Function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "[Cython](http://cython.org) is another package which is built to convert Python-like statements\n", "into compiled code. The language is actually a superset of Python which acts as a sort of\n", "hybrid between Python and C. By adding type annotations to Python code and running\n", "it through the Cython interpreter, we obtain fast compiled code. Here is a\n", "highly-optimized Cython version of the pairwise distance function, which we compile\n", "using IPython's Cython magic:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%load_ext cythonmagic" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 16 }, { "cell_type": "code", "collapsed": false, "input": [ "%%cython\n", "\n", "import numpy as np\n", "cimport cython\n", "from libc.math cimport sqrt\n", "\n", "@cython.boundscheck(False)\n", "@cython.wraparound(False)\n", "def pairwise_cython(double[:, ::1] X):\n", " cdef int M = X.shape[0]\n", " cdef int N = X.shape[1]\n", " cdef double tmp, d\n", " cdef double[:, ::1] D = np.empty((M, M), dtype=np.float64)\n", " for i in range(M):\n", " for j in range(M):\n", " d = 0.0\n", " for k in range(N):\n", " tmp = X[i, k] - X[j, k]\n", " d += tmp * tmp\n", " D[i, j] = sqrt(d)\n", " return np.asarray(D)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 17 }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "%timeit pairwise_cython(X)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 18 }, { "cell_type": "code", "collapsed": false, "input": [ "Benchmarks['cython'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100 loops, best of 3: 7.02 ms per loop\n", "\n" ] } ], "prompt_number": 20 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Cython version, despite all the optimization, is more or less the same as\n", "the result of the simple Numba decorator! \n", "By comparison, the Numba version is a simple, unadorned wrapper around plainly-written Python code." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Parakeet" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**[Parakeet](http://www.parakeetpython.com/)** is a runtime accelerator for an array-oriented subset of Python. If you're doing a lot of number crunching in Python, Parakeet may be able to significantly speed up your code.\n", "\n", "To accelerate a function, wrap it with Parakeet's @jit decorator:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "\n", "from parakeet import jit\n", "\n", "pairwise_parakeet = jit(pairwise_python)\n", "\n", "%timeit pairwise_parakeet(X)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 21 }, { "cell_type": "code", "collapsed": false, "input": [ "Benchmarks['parakeet'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "1 loops, best of 3: 5.83 ms per loop\n", "\n" ] } ], "prompt_number": 22 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Fortran/F2Py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another option for fast computation is to write a Fortran function directly, and use\n", "the ``f2py`` package to interface with the function. We can write the function\n", "as follows:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%file pairwise_fort.f\n", "\n", " subroutine pairwise_fort(X,D,m,n)\n", " integer :: n,m\n", " double precision, intent(in) :: X(m,n)\n", " double precision, intent(out) :: D(m,m) \n", " integer :: i,j,k\n", " double precision :: r \n", " do i = 1,m \n", " do j = 1,m \n", " r = 0\n", " do k = 1,n \n", " r = r + (X(i,k) - X(j,k)) * (X(i,k) - X(j,k)) \n", " end do \n", " D(i,j) = sqrt(r) \n", " end do \n", " end do \n", " end subroutine pairwise_fort" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Overwriting pairwise_fort.f\n" ] } ], "prompt_number": 23 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can then use the shell interface to compile the Fortran function. In order\n", "to hide the output of this operation, we direct it into ``/dev/null`` (note: I\n", "tested this on Linux, and it may have to be modified for Mac or Windows)." ] }, { "cell_type": "code", "collapsed": false, "input": [ "!f2py -c --help-fcompiler" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Gnu95FCompiler instance properties:\r\n", " archiver = ['/usr/bin/gfortran', '-cr']\r\n", " compile_switch = '-c'\r\n", " compiler_f77 = ['/usr/bin/gfortran', '-Wall', '-g', '-ffixed-form', '-\r\n", " fno-second-underscore', '-fPIC', '-O3', '-funroll-loops']\r\n", " compiler_f90 = ['/usr/bin/gfortran', '-Wall', '-g', '-fno-second-\r\n", " underscore', '-fPIC', '-O3', '-funroll-loops']\r\n", " compiler_fix = ['/usr/bin/gfortran', '-Wall', '-g', '-ffixed-form', '-\r\n", " fno-second-underscore', '-Wall', '-g', '-fno-second-\r\n", " underscore', '-fPIC', '-O3', '-funroll-loops']\r\n", " libraries = ['gfortran']\r\n", " library_dirs = []\r\n", " linker_exe = ['/usr/bin/gfortran', '-Wall', '-Wall']\r\n", " linker_so = ['/usr/bin/gfortran', '-Wall', '-g', '-Wall', '-g', '-\r\n", " shared']\r\n", " object_switch = '-o '\r\n", " ranlib = ['/usr/bin/gfortran']\r\n", " version = LooseVersion ('4.9.1-16')\r\n", " version_cmd = ['/usr/bin/gfortran', '--version']\r\n", "Fortran compilers found:\r\n", " --fcompiler=gnu95 GNU Fortran 95 compiler (4.9.1-16)\r\n", "Compilers available for this platform, but not found:\r\n", " --fcompiler=absoft Absoft Corp Fortran Compiler\r\n", " --fcompiler=compaq Compaq Fortran Compiler\r\n", " --fcompiler=g95 G95 Fortran Compiler\r\n", " --fcompiler=gnu GNU Fortran 77 compiler\r\n", " --fcompiler=intel Intel Fortran Compiler for 32-bit apps\r\n", " --fcompiler=intele Intel Fortran Compiler for Itanium apps\r\n", " --fcompiler=intelem Intel Fortran Compiler for 64-bit apps\r\n", " --fcompiler=lahey Lahey/Fujitsu Fortran 95 Compiler\r\n", " --fcompiler=nag NAGWare Fortran 95 Compiler\r\n", " --fcompiler=pathf95 PathScale Fortran Compiler\r\n", " --fcompiler=pg Portland Group Fortran Compiler\r\n", " --fcompiler=vast Pacific-Sierra Research Fortran 90 Compiler\r\n", "Compilers not available on this platform:\r\n", " --fcompiler=hpux HP Fortran 90 Compiler\r\n", " --fcompiler=ibm IBM XL Fortran Compiler\r\n", " --fcompiler=intelev Intel Visual Fortran Compiler for Itanium apps\r\n", " --fcompiler=intelv Intel Visual Fortran Compiler for 32-bit apps\r\n", " --fcompiler=intelvem Intel Visual Fortran Compiler for 64-bit apps\r\n", " --fcompiler=mips MIPSpro Fortran Compiler\r\n", " --fcompiler=none Fake Fortran compiler\r\n", " --fcompiler=sun Sun or Forte Fortran 95 Compiler\r\n", "For compiler details, run 'config_fc --verbose' setup command.\r\n", "Removing build directory /tmp/tmpPT3h4C\r\n" ] } ], "prompt_number": 25 }, { "cell_type": "code", "collapsed": false, "input": [ "!f2py -c --help-compiler" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "List of available compilers:\r\n", " --compiler=bcpp Borland C++ Compiler\r\n", " --compiler=cygwin Cygwin port of GNU C Compiler for Win32\r\n", " --compiler=emx EMX port of GNU C Compiler for OS/2\r\n", " --compiler=intel Intel C Compiler for 32-bit applications\r\n", " --compiler=intele Intel C Itanium Compiler for Itanium-based applications\r\n", " --compiler=intelem Intel C Compiler for 64-bit applications\r\n", " --compiler=mingw32 Mingw32 port of GNU C Compiler for Win32\r\n", " --compiler=msvc Microsoft Visual C++\r\n", " --compiler=pathcc PathScale Compiler for SiCortex-based applications\r\n", " --compiler=unix standard UNIX-style compiler\r\n", "Removing build directory /tmp/tmp9W2_Rb\r\n" ] } ], "prompt_number": 26 }, { "cell_type": "code", "collapsed": false, "input": [ "# Compile the Fortran with f2py.\n", "# We'll direct the output into /dev/null so it doesn't fill the screen\n", "#!f2py -c --compiler=intel pairwise_fort.f -m pairwise_fort > /dev/null\n", "!f2py -c --fcompiler=gnu95 pairwise_fort.f -m pairwise_fort > /dev/null" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 27 }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can import the resulting code into Python to time the execution\n", "of the function. To make sure we're being fair, we'll first convert\n", "the test array to Fortran-ordering so that no conversion needs to\n", "happen in the background:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "\n", "from pairwise_fort import pairwise_fort\n", "XF = np.asarray(X, order='F')\n", "%timeit pairwise_fort(XF)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 28 }, { "cell_type": "code", "collapsed": false, "input": [ "Benchmarks['fortran/\\nf2py'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100 loops, best of 3: 6.13 ms per loop\n", "\n" ] } ], "prompt_number": 29 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The result is nearly a factor of two slower than the Cython and Numba versions." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Scipy Pairwise Distances" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "\n", "from scipy.spatial.distance import cdist\n", "%timeit cdist(X, X)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 30 }, { "cell_type": "code", "collapsed": false, "input": [ "Benchmarks['scipy'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100 loops, best of 3: 5.67 ms per loop\n", "\n" ] } ], "prompt_number": 31 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Scikit-learn Pairwise Distances" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Scikit-learn contains the ``euclidean_distances`` function, works on sparse\n", "matrices as well as numpy arrays, and is implemented in Cython:" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "\n", "from sklearn.metrics import euclidean_distances\n", "%timeit euclidean_distances(X, X)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 32 }, { "cell_type": "code", "collapsed": false, "input": [ "Benchmarks['sklearn'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100 loops, best of 3: 9.75 ms per loop\n", "\n" ] } ], "prompt_number": 33 }, { "cell_type": "markdown", "metadata": {}, "source": [ "``euclidean_distances`` is several times slower than the Numba pairwise function\n", "on dense arrays." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Comparing the Results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "As a summary of the results, we'll create a bar-chart to visualize the timings:\n" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%matplotlib inline" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 34 }, { "cell_type": "code", "collapsed": false, "input": [ "labels = Benchmarks.keys()\n", "timings = [np.timedelta64(int(float(value[0])),str(value[1]))/np.timedelta64(1, 's') for value in Benchmarks.values()]\n", "x = np.arange(len(labels))\n", "ax = plt.axes(xticks=x, yscale='log')\n", "ax.bar(x - 0.3, timings, width=0.6, alpha=0.4, bottom=1E-6)\n", "ax.grid()\n", "ax.set_xlim(-0.5, len(labels) - 0.5)\n", "ax.set_ylim(0.5*min(timings), 1.1*max(timings))\n", "ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda i, loc: labels[int(i)]))\n", "ax.set_ylabel('time (s)')\n", "ax.set_title(\"Pairwise Distance Timings\")" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 35, "text": [ "" ] }, { "metadata": {}, "output_type": "display_data", "svg": [ "\n", "\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text": [ "" ] } ], "prompt_number": 35 }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that this is log-scaled, so the vertical space between two\n", "grid lines indicates a factor of 10 difference in computation time. As Pure Python takes more time by two orders of magnitude we'll now remove it from the benchmarks for a better comparison." ] }, { "cell_type": "code", "collapsed": false, "input": [ "labels = [val for val in Benchmarks.iterkeys() if val != 'python\\nloop']\n", "timings = [np.timedelta64(int(float(value[0])),str(value[1]))/np.timedelta64(1, 's')\\\n", " for k, value in Benchmarks.items() if k != 'python\\nloop']\n", "x = np.arange(len(labels))\n", "ax = plt.axes(xticks=x, yscale='log')\n", "ax.bar(x - 0.3, timings, width=0.6, alpha=0.4, bottom=1E-6)\n", "ax.grid()\n", "ax.set_xlim(-0.5, len(labels) - 0.5)\n", "ax.set_ylim(0.5*min(timings), 1.1*max(timings))\n", "ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda i, loc: labels[int(i)]))\n", "ax.set_ylabel('time (s)')\n", "ax.set_title(\"Pairwise Distance Timings\")" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 33, "text": [ "" ] }, { "metadata": {}, "output_type": "display_data", "svg": [ "\n", "\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text": [ "" ] } ], "prompt_number": 33 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "**1D European Option using Black-Scholes Formula**" ] }, { "cell_type": "code", "collapsed": false, "input": [ "#Restart notebook!" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 37 }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "We'll now benchmark a simple function which returns the price of a 1D European Option using the closed form solution with the following parameters:\n", "\n", "- $S_0$ = 100\n", "- $K$ = 100\n", "- $T$ = 1 (years)\n", "- $\\sigma$ = 0.3 \n", "- $r$ = 0.03\n", "- dividend = 0\n", "- option type = -1 (+1 for call, -1 for put)" ] }, { "cell_type": "code", "collapsed": false, "input": [ "S0 = 100\n", "K = 100\n", "T = 1\n", "vol = 0.3\n", "r = 0.03\n", "q = 0\n", "optype = -1" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 36 }, { "cell_type": "code", "collapsed": false, "input": [ "from numpy import log, sqrt, zeros, exp, arange\n", "from scipy.special import erf\n", "\n", "def parse_cap(s):\n", " return cap.stdout.split(' ')[-4:-2]\n", "\n", "benchs = ['python','numba','cython','matlab']\n", "BS_bench = dict(zip(benchs,zeros(4)))" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 37 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Pure Python" ] }, { "cell_type": "code", "collapsed": false, "input": [ "def std_norm_cdf(x):\n", " return 0.5*(1+erf(x/sqrt(2.0)))\n", "\n", "def black_scholes(s, k, t, v, rf, div, cp):\n", " \"\"\"Price an option using the Black-Scholes model.\n", " \n", " s : initial stock price\n", " k : strike price\n", " t : expiration time\n", " v : volatility\n", " rf : risk-free rate\n", " div : dividend\n", " cp : +1/-1 for call/put\n", " \"\"\"\n", " d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))\n", " d2 = d1 - v*sqrt(t)\n", " optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1) - \\\n", " cp*k*exp(-rf*t)*std_norm_cdf(cp*d2)\n", " return optprice" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 38 }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "%timeit black_scholes(S0, K, T, vol, r, q, optype)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 39 }, { "cell_type": "code", "collapsed": false, "input": [ "BS_bench['python'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "100000 loops, best of 3: 11.6 us per loop\n", "\n" ] } ], "prompt_number": 40 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Numba" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from numba import double\n", "from numba.decorators import jit, autojit\n", "import math\n", "\n", "@autojit\n", "def std_norm_cdf_numba(x):\n", " return 0.5*(1+math.erf(x/math.sqrt(2.0)))\n", "\n", "@autojit\n", "def black_scholes_numba(s, k, t, v, rf, div, cp):\n", " \"\"\"Price an option using the Black-Scholes model.\n", " \n", " s : initial stock price\n", " k : strike price\n", " t : expiration time\n", " v : volatility\n", " rf : risk-free rate\n", " div : dividend\n", " cp : +1/-1 for call/put\n", " \"\"\"\n", " d1 = (math.log(s/k)+(rf-div+0.5*v*v)*t)/(v*math.sqrt(t))\n", " d2 = d1 - v*math.sqrt(t)\n", " optprice = cp*s*math.exp(-div*t)*std_norm_cdf_numba(cp*d1) - \\\n", " cp*k*math.exp(-rf*t)*std_norm_cdf_numba(cp*d2)\n", " return optprice" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 41 }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "%timeit black_scholes_numba(S0, K, T, vol, r, q, optype)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 42 }, { "cell_type": "code", "collapsed": false, "input": [ "BS_bench['numba'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "1 loops, best of 3: 5.01 us per loop\n", "\n" ] } ], "prompt_number": 43 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Cython" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%load_ext cythonmagic" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "The cythonmagic extension is already loaded. To reload it, use:\n", " %reload_ext cythonmagic\n" ] } ], "prompt_number": 44 }, { "cell_type": "code", "collapsed": false, "input": [ "%%cython\n", "cimport cython\n", "from libc.math cimport exp, sqrt, pow, log, erf\n", "\n", "@cython.cdivision(True)\n", "cdef double std_norm_cdf(double x) nogil:\n", " return 0.5*(1+erf(x/sqrt(2.0)))\n", "\n", "@cython.cdivision(True)\n", "def black_scholes(double s, double k, double t, double v,\n", " double rf, double div, double cp):\n", " \"\"\"Price an option using the Black-Scholes model.\n", " \n", " s : initial stock price\n", " k : strike price\n", " t : expiration time\n", " v : volatility\n", " rf : risk-free rate\n", " div : dividend\n", " cp : +1/-1 for call/put\n", " \"\"\"\n", " cdef double d1, d2, optprice\n", " with nogil:\n", " d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))\n", " d2 = d1 - v*sqrt(t)\n", " optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1) - \\\n", " cp*k*exp(-rf*t)*std_norm_cdf(cp*d2)\n", " return optprice" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 45 }, { "cell_type": "code", "collapsed": false, "input": [ "%%capture cap\n", "%timeit black_scholes(S0, K, T, vol, r, q, optype)" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 46 }, { "cell_type": "code", "collapsed": false, "input": [ "BS_bench['cython'] = parse_cap(cap)\n", "print cap.stdout" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "1000000 loops, best of 3: 372 ns per loop\n", "\n" ] } ], "prompt_number": 47 }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "MATLAB" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We now analyse the corresponding **MATLAB** code which we'll use for comparison" ] }, { "cell_type": "code", "collapsed": false, "input": [ "!cat ../std_norm_cdf.m" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "function z = std_norm_cdf(x)\r\n", "z = 0.5*(1+erf(x/sqrt(2.0)));\r\n" ] } ], "prompt_number": 47 }, { "cell_type": "code", "collapsed": false, "input": [ "!cat ../black_scholes.m" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "function z = black_scholes(s, k, t, v, rf, div, cp)\r\n", " \r\n", "d1 = (log(s/k)+(rf-div+0.5*v*v)*t)/(v*sqrt(t));\r\n", "d2 = d1 - v*sqrt(t);\r\n", "optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1)-cp*k*exp(-rf*t)*std_norm_cdf(cp*d2);\r\n", "z = optprice;" ] } ], "prompt_number": 48 }, { "cell_type": "code", "collapsed": false, "input": [ "%matplotlib inline" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 49 }, { "cell_type": "code", "collapsed": false, "input": [ "BS_bench['matlab'] = [u'55',u'us']\n", "labels= BS_bench.keys()\n", "timings = [np.timedelta64(int(float(value[0])),str(value[1]))/np.timedelta64(1, 's') for value in BS_bench.values()]\n", "x = arange(len(labels))\n", "ax = plt.axes(xticks=x, yscale='log')\n", "ax.bar(x - 0.3, timings, width=0.6, alpha=0.4, bottom=1E-6)\n", "ax.grid()\n", "ax.set_xlim(-0.5, len(labels) - 0.5)\n", "ax.set_ylim(min(timings), 1.1*max(timings))\n", "ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda i, loc: labels[int(i)]))\n", "ax.set_ylabel('time ($s$)')\n", "ax.set_title(\"Black-Scholes Timings\")" ], "language": "python", "metadata": {}, "outputs": [ { "metadata": {}, "output_type": "pyout", "prompt_number": 50, "text": [ "" ] }, { "metadata": {}, "output_type": "display_data", "svg": [ "\n", "\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text": [ "" ] } ], "prompt_number": 50 }, { "cell_type": "markdown", "metadata": {}, "source": [ "*This post was written entirely as an IPython notebook.* \n", "*The full notebook can be downloaded* \n", "[*here*](https://raw.github.com/PoeticCapybara/Python-Introduction-Zittau/master/Lecture-8-Benchmarks.ipynb), \n", "*or viewed statically on* \n", "[*nbviewer*](http://nbviewer.ipython.org/urls/raw.github.com/PoeticCapybara/Python-Introduction-Zittau/master/Lecture-8-Benchmarks.ipynb)\n", "\n", "[Back to top](#top)" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%load_ext version_information\n", "%version_information numpy,numba,parakeet,cython,matplotlib,scipy,sklearn" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
SoftwareVersion
Python2.7.8 |Anaconda 2.1.0 (64-bit)| (default, Aug 21 2014, 18:22:21) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
IPython2.3.1
OSposix [linux2]
numpy1.9.1
numba0.15.1
parakeet0.23.2
cython0.21.1
matplotlib1.4.2
scipy0.14.0
sklearn0.15.2
Fri Dec 05 11:18:11 2014 CET
" ], "json": [ "{ \"Software versions\" : [{ \"module\" : \"Python\", \"version\" : \"2.7.8 |Anaconda 2.1.0 (64-bit)| (default, Aug 21 2014, 18:22:21) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]\" }, { \"module\" : \"IPython\", \"version\" : \"2.3.1\" }, { \"module\" : \"OS\", \"version\" : \"posix [linux2]\" }, { \"module\" : \"numpy\", \"version\" : \"1.9.1\" }, { \"module\" : \"numba\", \"version\" : \"0.15.1\" }, { \"module\" : \"parakeet\", \"version\" : \"0.23.2\" }, { \"module\" : \"cython\", \"version\" : \"0.21.1\" }, { \"module\" : \"matplotlib\", \"version\" : \"1.4.2\" }, { \"module\" : \"scipy\", \"version\" : \"0.14.0\" }, { \"module\" : \"sklearn\", \"version\" : \"0.15.2\" } ] }" ], "latex": [ "\\begin{tabular}{|l|l|}\\hline\n", "{\\bf Software} & {\\bf Version} \\\\ \\hline\\hline\n", "Python & 2.7.8 |Anaconda 2.1.0 (64-bit)| (default, Aug 21 2014, 18:22:21) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] \\\\ \\hline\n", "IPython & 2.3.1 \\\\ \\hline\n", "OS & posix [linux2] \\\\ \\hline\n", "numpy & 1.9.1 \\\\ \\hline\n", "numba & 0.15.1 \\\\ \\hline\n", "parakeet & 0.23.2 \\\\ \\hline\n", "cython & 0.21.1 \\\\ \\hline\n", "matplotlib & 1.4.2 \\\\ \\hline\n", "scipy & 0.14.0 \\\\ \\hline\n", "sklearn & 0.15.2 \\\\ \\hline\n", "\\hline \\multicolumn{2}{|l|}{Fri Dec 05 11:18:11 2014 CET} \\\\ \\hline\n", "\\end{tabular}\n" ], "metadata": {}, "output_type": "pyout", "prompt_number": 51, "text": [ "Software versions\n", "Python 2.7.8 |Anaconda 2.1.0 (64-bit)| (default, Aug 21 2014, 18:22:21) [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]\n", "IPython 2.3.1\n", "OS posix [linux2]\n", "numpy 1.9.1\n", "numba 0.15.1\n", "parakeet 0.23.2\n", "cython 0.21.1\n", "matplotlib 1.4.2\n", "scipy 0.14.0\n", "sklearn 0.15.2\n", "\n", "Fri Dec 05 11:18:11 2014 CET" ] } ], "prompt_number": 51 }, { "cell_type": "code", "collapsed": false, "input": [ "from IPython.core.display import HTML\n", "def css_styling():\n", " styles = open(\"./styles/custom.css\", \"r\").read()\n", " return HTML(styles)\n", "css_styling()" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "\n", "\n", "\n", "\n", "\n" ], "metadata": {}, "output_type": "pyout", "prompt_number": 1, "text": [ "" ] } ], "prompt_number": 1 }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }