{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Non-required imports" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.core.display import display, HTML\n", "display(HTML(\"\"))\n", "%config IPCompleter.use_jedi = False ### IN CASE TAB-AUTO COMPLETE IS SLOW!!!\n", "%config InlineBackend.figure_format = 'retina'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Required imports" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import numba\n", "import math" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Simple example" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.random.seed(313)\n", "x,y = np.random.normal(size=(2,int(1e5)))\n", "x0,y0 = -8,-10" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def distance(x,y,x0,y0):\n", " r = np.empty_like(x)\n", " for i,(xi,yi) in enumerate(zip(x,y)):\n", " r[i] = math.sqrt((xi-x0)**2+(yi-y0)**2)\n", " return r\n", "\n", "distance_jit = numba.jit(distance)\n", "\n", "# Run one time to compile code\n", "_ = distance_jit(x,y,x0,y0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('Python:')\n", "%timeit distance(x,y,x0,y0)\n", "print('\\nNumba:')\n", "%timeit distance_jit(x,y,x0,y0)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Numba works with: most of numpy and some of scipy!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Use numpy if you can!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def distance_np(x,y,x0,y0):\n", " return np.sqrt(((x-x0)**2+(y-y0)**2))\n", "\n", "\n", "distance_np_jit = numba.jit(distance_np, parallel=True)\n", "\n", "# Run one time to compile\n", "_ = distance_np_jit(x,y,x0,y0)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('Numpy:')\n", "%timeit distance_np(x,y,x0,y0)\n", "print('\\nNumba & Numpy:')\n", "%timeit distance_np_jit(x,y,x0,y0)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Few options:\n", "\n", "See: \n", "https://numba.pydata.org/numba-doc/dev/user/jit.html" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "signature = 'float64(float64)' # input & output types; no other options than specified are allowed\n", "parallel = True\n", "fastmath = True # strict IEEE 754 compliance, or not.\n", "cache = True # Keep compiled version of the code on disk.\n", "target = 'cpu' or 'cuda' #or 'parallel'.\n", "nogil = True # removes the Global Intepreter Lock.\n", "\n", "nopython = True # Prevent Numba from falling back to Python code." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import pylab as plt" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def func(x):\n", " df = pd.DataFrame(data=x, columns=['x'])\n", " return df['x'].mean() \n", "\n", "\n", "\n", "jit_func = numba.jit(func, nopython=False)\n", "jit_func_np = numba.jit(func, nopython=True)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "jit_func(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mean_x = jit_func_np(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Recommended use:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "@jit()\n", "def func(x,y):\n", " for i,(xi,yi) in enumerate(zip(x,y)):\n", " x[i],y[i] = xi**yi,yi-xi\n", " return x,y\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Example with signature and options" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "@jit('Tuple((float64[:],float64[:]))(float64[:],float64[:])', nopython=True, )\n", "def func(x,y):\n", " for i,(xi,yi) in enumerate(zip(x,y)):\n", " x[i],y[i] = xi**yi,yi-xi\n", " return x,y\n", "\n", "\n", "@jit('(float64[:],float64[:])', nopython=True, )\n", "def func(x,y):\n", " for i,(xi,yi) in enumerate(zip(x,y)):\n", " x[i],y[i] = xi**yi,yi-xi\n", " return x,y\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### What is a decorator" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def decorator(func):\n", " \n", " def decorate(arg):\n", " return func(arg)+' hello'\n", " \n", " return decorate" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@decorator\n", "def num2str(num):\n", " return str(num)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "num2str(10)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Advanced Options" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Vectorization of functions (e.g. create numpy-like functions):\n", "https://numba.pydata.org/numba-doc/dev/user/vectorize.html" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from numba import vectorize\n", "\n", "@vectorize\n", "def f(x, y):\n", " return x * y\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(f.__init__)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@jit\n", "def jit_f(x, y):\n", " return x * y" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(jit_f.__init__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### @jitclass:\n", "https://numba.pydata.org/numba-doc/dev/user/jitclass.html" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Numba & Scipy" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from scipy import LowLevelCallable\n", "import scipy.integrate as si" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "def integrand(x,sigma,mu):\n", " gauss = 1/np.sqrt(np.pi*sigma**2) * np.exp(- 0.5 * ((x - mu)/(sigma)**2) ) \n", " return gauss \n", "\n", "\n", "sigma = 2.0\n", "mu = 1.0\n", "\n", "\n", "jit_integrand = jit(integrand)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%timeit integral, error = si.quad(integrand,-np.inf,np.inf,args=(sigma,mu)) \n", "%timeit integral, error = si.quad(jit_integrand,-np.inf,np.inf,args=(sigma,mu)) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Even faster: wrap the jitted function in a LowLevelCallable" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "from numba.types import intc, CPointer, float64\n", "from numba import jit,cfunc,cfunc,carray\n", "\n", "def jit_integrand_function(integrand_function):\n", " jitted_function = numba.jit(integrand_function, nopython=True)\n", "\n", " @cfunc(float64(intc, CPointer(float64)))\n", " def wrapped(n, xx):\n", " values = carray(xx,n)\n", " return jitted_function(values)\n", " return LowLevelCallable(wrapped.ctypes)\n", "\n", "\n", "\n", "\n", "@jit_integrand_function\n", "def LLC_integrand(args):\n", " x,sigma,mu = args\n", " gauss = 1/np.sqrt(np.pi*sigma**2) * np.exp(- 0.5 * ((x - mu)/(sigma)**2) ) \n", " return gauss \n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%timeit integral, error = si.quad(jit_integrand,-np.inf,np.inf,args=(sigma,mu)) \n", "%timeit integral, error = si.quad(LLC_integrand,-np.inf,np.inf,args=(sigma,mu)) \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Way around LowLevelCallable wrapper" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def integrand(x):\n", " return np.exp(-x**2)\n", "cfunced = numba.cfunc(\"float64(float64)\")(integrand)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%timeit integral, error = si.quad(cfunced.ctypes,-np.inf,np.inf) \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# For more, check out: \n", "https://numba.pydata.org/numba-doc/dev/index.html#" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.4" } }, "nbformat": 4, "nbformat_minor": 2 }