{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Numba 0.46.0 Release Demo\n", "=======================\n", "\n", "This notebook contains a demonstration of new features present in the 0.46.0 release of Numba. Whilst release notes are produced as part of the [`CHANGE_LOG`](https://github.com/numba/numba/blob/fed07c578cb1b478ac29a439876da68170738f11/CHANGE_LOG#L1-L170), there's nothing like seeing code in action! It should be noted that this release does not contain a huge amount of changes to user facing support. A lot of the changes to the code base this time around were to continue to enhance Numba's use as a compiler toolkit and add features for advanced users/developers.\n", "\n", "Some exciting news... The Numba team finally started working on, the colloquially named, \"scumba\" project, to add SciPy support in Numba, the [project is called `numba-scipy`](https://github.com/numba/numba-scipy) (it's expected that there may be other `numba-XYZ` projects). This project also demonstrates a new feature added in this release, that Numba now has a formal way to register a project with Numba itself via an auto-discovery mechanism. Read more about this mechanism [here](http://numba.pydata.org/numba-doc/latest/extending/entrypoints.html). A demonstration of ``numba-scipy`` appears later in this notebook.\n", "\n", "For users of Numba, demonstrations of new features include:\n", "* [The using SciPy in Numba Jitted functions](#🎉-Using-SciPy-from-Numba-🎉)\n", "* [Newly supported NumPy functions/features](#Newly-supported-NumPy-functions/features)\n", "* [A few new miscellaneous features!](#Miscellaneous-features)\n", "\n", "In addition, predominantly for library developers/compiler engineers, new features include:\n", "* The addition of the `'inline'` kwarg to both the `@numba.jit` family of decorators and `@numba.extending.overload`.\n", "* A new compiler API to permit extension and definition of:\n", " * The compiler itself.\n", " * The compiler pipeline.\n", " * Compiler passes.\n", "* Support for module at a time `jit` application.\n", " \n", "These are demonstrated in a separate [notebook here](https://mybinder.org/v2/gh/numba/numba-examples/master?filepath=notebooks%2FNumba_046_developers_release_demo.ipynb).\n", "\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 tuple(int(x) for x in __version__.split('.')[:2]) >= (0, 46)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "🎉 Using SciPy from Numba 🎉\n", "=========================\n", "\n", "As noted above, the 0.46 release cycle saw the Numba core developers start work on a new community driven project called `numba-scipy`. This project adds support for using SciPy functions in Numba JIT'd code, at present it's in its very infancy but, with thanks to external contributors, some functionality is already present ([docs are here](https://numba-scipy.readthedocs.io/)). Below is an example of using `scipy.special.*` functions in JIT code." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from scipy import special\n", "\n", "@njit\n", "def call_scipy_in_jitted_code():\n", " print(\"special.beta(1.2, 3.4)\", special.beta(1.2, 3.4))\n", " print(\"special.j0(5.6) \", special.j0(5.6))\n", " \n", "call_scipy_in_jitted_code()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above also nicely highlights the automatic extension registration working ([docs are here](http://numba.pydata.org/numba-doc/dev/extending/entrypoints.html)), note how `numba-scipy` did not need to be imported to make use of the `scipy.special` functions, all that was needed was to install `numba-scipy` package in the current Python environment.\n", "\n", "It should be noted that contributions to `numba-scipy` are welcomed, a good place to start is the [contributing guide](https://numba-scipy.readthedocs.io/en/latest/developer/contributing.html) to get set up and then the guide to [`@overload`ing](http://numba.pydata.org/numba-doc/latest/extending/overloading-guide.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Newly supported NumPy functions/features\n", "=====\n", "This release contains a number of newly supported NumPy functions, all written by contributors from the Numba community:\n", "* The long awaited support for `np.cross` is added along with the extension `numba.numpy_extensions.cross2d` for cases where both inputs have `shape[-1] == 2`.\n", "* The repeatedly requested `np.array_equal` is now supported.\n", "* Also now supported are:\n", " * `np.count_nonzero`\n", " * `np.append`\n", " * `np.triu_indices`\n", " * `np.tril_indices`\n", " * `np.triu_indices_from`\n", " * `np.tril_indices_from`\n", " \n", "A quick demo of the above:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from numba import numpy_extensions\n", "\n", "@njit\n", "def numpy_new():\n", "\n", " arr = np.array([[0, 2], [3 ,0]])\n", " \n", " # np.count_nonzero\n", " print(\"np.count_nonzero:\\n\", np.count_nonzero(arr))\n", " \n", " # np.append\n", " print(\"np.append:\\n\", np.append(arr, arr))\n", "\n", " # np.array_equal\n", " print(\"np.array_equal:\\n\", np.array_equal(arr, arr))\n", " \n", " # np.tri{u,l}_indices\n", " print(\"np.triu_indices:\\n\",np.triu_indices(4, k=2))\n", " print(\"np.tril_indices:\\n\",np.tril_indices(3, k=2))\n", " \n", " # np.tri{u,l}_indices_from\n", " print(\"np.triu_indices_from:\\n\",np.triu_indices_from(arr, k=0))\n", " print(\"np.tril_indices_from:\\n\",np.tril_indices_from(arr, k=2))\n", " \n", " # np.cross\n", " a = np.array([[1, 2, 3], [4, 5, 6]])\n", " b = np.array([[4, 5, 6], [1, 2, 3]])\n", " print(\"np.cross\", np.cross(a, b))\n", " \n", " # np.cross, works fine unless `shape[-1] == 2` for both inputs\n", " # where it becomes impossible to statically determine the shape\n", " # of the return type, in this case replace `np.cross` with the\n", " # `numba.numpy_extensions.cross2d` function. e.g.\n", " c = np.array([[1, 2], [4, 5]])\n", " d = np.array([[4, 5], [1, 2]])\n", " print(\"numpy_extensions.cross2d\", numpy_extensions.cross2d(c, d))\n", " \n", "numpy_new()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`dtype` support in `np.sum`\n", "---------------------------------------\n", "Numba 0.46 has support added for the `dtype` kwarg in `np.sum` and `np.ndarray.sum`, this has been repeatedly requested and was kindly implemented by a member of the Numba community. A quick demo:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@njit\n", "def np_sum_demo():\n", " x = np.arange(10)\n", " x_sum = x.sum(dtype=np.complex128)\n", " \n", " y = np.arange(24).reshape((4, 6)).astype(np.uint8)\n", " y_sum = np.sum(y, axis=1, dtype=np.uint16)\n", " \n", " return (x_sum, y_sum)\n", "\n", "print(np_sum_demo())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NumPy unicode array support\n", "-----------------------\n", "With thanks to another contributor from the Numba community, Numba can now consume and operate on NumPy arrays with a unicode dtype." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from numba.typed import List\n", "@njit\n", "def unicode_array_demo(arr):\n", " acc = List()\n", " for i in (13, 20, 12, 1, 0, 28, 8, 18, 28, 27, 26):\n", " acc.append(str(arr[i]))\n", " return ''.join(acc)\n", "\n", "arr = np.array([chr(x) for x in range(ord('a'), ord('a') + 26)] + ['⚡', '🐍', chr(32)])\n", "unicode_array_demo(arr)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Miscellaneous features\n", "===============\n", "Some new features were added that don't fit anywhere in particular but are still very useful...\n", "\n", "Just one in this section for 0.46, `.count()` is supported on Unicode strings (also contributed by a Numba community member!)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "@njit\n", "def demo_misc():\n", " print(\"n🐍u🐍m🐍b🐍a⚡\".count(\"🐍\")) # count the snakes\n", "\n", "demo_misc()" ] } ], "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.3" } }, "nbformat": 4, "nbformat_minor": 2 }