{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Numba 0.52.0 Release Demo\n", "=======================\n", "\n", "This notebook contains a demonstration of new features present in the 0.52.0 release of Numba. Whilst release notes are produced as part of the [`CHANGE_LOG`](https://github.com/numba/numba/blob/release0.52/CHANGE_LOG), there's nothing like seeing code in action!\n", "\n", "This release contains a few new features, but it's mainly internals that have changed, with a particular focus on increasing run time performance! In this notebook the new CPU target features are demonstrated. The [CUDA target](https://numba.pydata.org/numba-doc/latest/cuda/index.html) also gained a lot of new features in 0.52.0 and [@gmarkall](https://github.com/gmarkall) has created a [demo notebook](https://mybinder.org/v2/gh/numba/numba-examples/master?filepath=notebooks%2FNumba_052_CUDA_Release_Demo.ipynb) especially for these!\n", "\n", "Key internal changes:\n", "\n", "* Intel kindly sponsored the development of an LLVM level reference count pruning compiler pass. This reduces pressure on the atomic locks used for reference counting in Numba and exposes a lot more inlining/optimisation opportunities ([@sklam](https://github.com/sklam)). This change has a large impact on performance and so has [its own notebook](https://mybinder.org/v2/gh/numba/numba-examples/master?filepath=notebooks%2FNumba_052_refpruner.ipynb) to help users understand what it's doing!\n", "* Intel also sponsored work to improve the performance of the ``numba.typed.List`` container ([@stuartarchibald](https://github.com/stuartarchibald)).\n", "* The optimisers in Numba have been lightly tuned and can now do more ([@stuartarchibald](https://github.com/stuartarchibald)).\n", "\n", "Highlights of core feature changes:\n", "\n", "* The ``inspect_cfg`` method on the JIT dispatcher object has been significantly enhanced ([@stuartarchibald](https://github.com/stuartarchibald)).\n", "* NumPy 1.19 support is added ([@stuartarchibald](https://github.com/stuartarchibald)).\n", "* A few new NumPy features have been added along with some extensions to existing support.\n", "\n", "Demonstrations of new features/changes:\n", "* [Performance improvement demonstration](#Performance-improvement-demonstration)\n", "* [``inspect_cfg`` enhancements](#CFG-inspection-enhancements)\n", "* [NumPy enhancements](#Newly-supported-NumPy-functions/features)\n", "\n", "First, import the necessary from Numba and NumPy..." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from numba import jit, njit, config, __version__, errors\n", "from numba.extending import overload\n", "import numba\n", "import numpy as np\n", "assert numba.version_info.short >= (0, 52)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Performance improvement demonstration\n", "==================================\n", "\n", "The performance of Numba JIT compiled functions is improved in quite a few important cases in 0.52. First, as mentioned above, [this notebook](https://mybinder.org/v2/gh/numba/numba-examples/master?filepath=notebooks%2FNumba_052_refpruner.ipynb) demonstrates the impact of the reference count pruning compiler pass, alternatively, just try 0.52.0 with your existing code and see if it makes a difference! Second, there have been some specific improvements, demonstrating a couple of them:\n", "\n", "#### Calling `str()`" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@njit\n", "def str_on_int(n):\n", " c = 0\n", " for i in range(n):\n", " c += len(str(n))\n", " return c\n", "\n", "\n", "sz = 100000\n", "str_on_int(sz)\n", "%timeit str_on_int.py_func(sz) # python function\n", "%timeit str_on_int(sz) # jit function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Reductions/`__getitem__` on `typed.List`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "# Reductions on typed.List\n", "from numba.typed import List\n", "\n", "n = 1000\n", "py_list = [float(x) for x in range(n)]\n", "nb_list = List(py_list)\n", "\n", "def sum_list(lst):\n", " acc = 0.0\n", " for item in lst:\n", " acc += item\n", " return acc\n", "\n", "jit_sum_list = njit(sum_list)\n", "fastmath_jit_sum_list = njit(fastmath=True)(sum_list)\n", "\n", "%timeit sum_list(py_list) # python function on a python list\n", "%timeit jit_sum_list(nb_list) # JIT function on typed list\n", "%timeit fastmath_jit_sum_list(nb_list) # \"fastmath\" JIT function on typed list" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "CFG inspection enhancements\n", "=========================\n", "The Numba dispatcher's [`inspect_cfg()` method](https://numba.readthedocs.io/en/stable/reference/jit-compilation.html#Dispatcher.inspect_cfg) has been enhanced with colorized output and support for Python code interleaving to provide a more visual way to debug/tune code. For a more advanced demonstration, this feature is used in [the notebook](https://mybinder.org/v2/gh/numba/numba-examples/master?filepath=notebooks%2FNumba_052_refpruner.ipynb) explaining the new reference count pruning pass. A quick demonstration of this feature:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@njit(debug=True) # Switch on debug to make python source available.\n", "def foo(n):\n", " acc = 0.\n", " for i in range(n):\n", " acc += np.sqrt(i)\n", " if acc > 1000:\n", " raise ValueError(\"Error!\")\n", " else:\n", " return acc\n", "\n", "foo(10)\n", "\n", "# Take a look at the docstring for all the options, the ones used here are:\n", "# strip_ir = remove LLVM IR apart from calls\n", "# interleave = add Python source into the LLVM CFG!\n", "foo.inspect_cfg(foo.signatures[0], strip_ir=True, interleave=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Newly supported NumPy functions/features\n", "====================================\n", "\n", "This release contains some updates to Numba's NumPy support, mostly contributed by the Numba community (with thanks!):\n", "* NumPy 1.19 ([@stuartarchibald](https://github.com/stuartarchibald)).\n", "* ``np.asfarray`` ([@guilhermeleobas](https://github.com/guilhermeleobas)).\n", "* \"subtyping\" in record arrays ([@luk-f-a](https://github.com/luk-f-a)).\n", "* ``np.split`` and ``np.array_split`` ([@ivirshup](https://github.com/ivirshup)).\n", "* ``operator.contains`` with ``ndarray`` ([@mugoh](https://github.com/mugoh)).\n", "* ``np.asarray_chkfinite`` ([@rishabhvarshney14](https://github.com/rishabhvarshney14)).\n", "* the ``ndarray`` allocators, ``empty``, ``ones`` and ``zeros``, accept a ``dtype`` specified as a string literal ([@stuartarchibald](https://github.com/stuartarchibald))." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "@njit\n", "def demo_numpy():\n", " # np.asfarray\n", " farray = np.asfarray(np.zeros(4,), dtype=np.int8)\n", " \n", " # np.split/np.array_split\n", " split = np.split(np.arange(10), 5)\n", " arr_split = np.array_split(np.arange(10), 3)\n", " arr_contains = 4 in np.arange(10), 11 in np.arange(10)\n", "\n", " # asarray_chkfinite\n", " caught = False\n", " try:\n", " np.asarray_chkfinite((0., np.inf, 1., np.nan,))\n", " except Exception: # inf and nan not accepted\n", " caught = True\n", "\n", " # String literal dtypes\n", " ones, zeros, empty = (np.ones((5,), 'int8'), np.zeros((3,), 'complex128'),\n", " np.empty((0,), 'float32'))\n", "\n", " return farray, split, arr_split, arr_contains, caught, ones, zeros, empty\n", " \n", "farray, split, arr_split, arr_contains, caught, ones, zeros, empty = demo_numpy()\n", "\n", "print((f\"farray: {farray}\\n\"\n", " f\"split: {split}\\n\"\n", " f\"array_split: {arr_split}\\n\"\n", " f\"array contains: {arr_contains}\\n\"\n", " f\"caught: {caught}\\n\"\n", " f\"ones: {ones}\\n\"\n", " f\"zeros: {zeros}\\n\"\n", " f\"empty: {empty}\\n\"))" ] } ], "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.8.2" } }, "nbformat": 4, "nbformat_minor": 2 }