{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\"FMP\"\n", "\"AudioLabs\"\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
\"B\"
\n", "

Numba

\n", "
\n", "\n", "
\n", "\n", "

\n", "This notebook gives a short introduction to the Python package Numba, which offers an open source jit (just-in-time) compiler that translates a subset of Python and NumPy code into fast machine code. \n", "

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introduction\n", "\n", "As described in the [main documentation](http://numba.pydata.org/), Numba translates Python functions to optimized machine code at runtime. The compiled numerical algorithms in Python can then approach the speeds of C or FORTRAN. Without the need of running a separate compilation step, Numba can be simply applied by adding decorators to the Python function. Since there are certain restriction on the Python code, we recommend to only use Numba for compiling functions that are performance-critical. Usually, this is only a small fraction of code. In the following we give a couple of illustrating example and refer to the [main documentation](http://numba.pydata.org/) for details.\n", "\n", "
\n", "Note: Using numba can really make a difference, since it may easily lead to accelerations of a factor between $10$ and $100$. However, using numba also comes at a cost, since it imposes significant restrictions on the programming. Also, debugging may become much harder, since numba often outputs hard-to-understand error messages. Therefore, we recommend to do the programming in two stages:\n", "\n", " \n", "\n", "
\n", "\n", "In particular, unknown data types of a function's argument variables may cause unexpected errors when using numba, which tries to infer the types at call time. For example, when initializing a variable with `var=None` in a function header may cause problems. We come back to this issue later in this notebook. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compiling with `jit`\n", "\n", "As a first example, we consider a function that performs an average filtering over a spectrogram. To illustrate the kind of accelerations introduced by Numba, we implement this filtering as a naive double loop." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:02:27.510441Z", "iopub.status.busy": "2024-02-15T09:02:27.510105Z", "iopub.status.idle": "2024-02-15T09:02:30.086479Z", "shell.execute_reply": "2024-02-15T09:02:30.085749Z" } }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "import os\n", "import numpy as np\n", "import librosa\n", "from matplotlib import pyplot as plt\n", "%matplotlib inline\n", "\n", "fn_wav = os.path.join('..', 'data', 'B', 'FMP_B_Note-C4_Piano.wav')\n", "x, Fs = librosa.load(fn_wav, sr=None)\n", "X = librosa.stft(x)\n", "Y = np.abs(X)\n", "\n", "def spectrogram_average_filter_naive(Y, filter_len):\n", " K, N = Y.shape\n", " filter_left = filter_len // 2\n", " filter_right = filter_len - filter_left - 1\n", " Y_pad = np.concatenate((np.zeros((K, filter_left)), Y, \n", " np.zeros((K, filter_right))), axis=1)\n", " Y_new = np.empty_like(Y)\n", " for k in range(K):\n", " for n in range(N):\n", " Y_new[k, n] = Y_pad[k, n:n+filter_len].sum() / filter_len\n", " return Y_new\n", "\n", "filter_length = 21\n", "Y_filt = spectrogram_average_filter_naive(Y, filter_length)\n", "\n", "plt.figure(figsize=(10, 3))\n", "\n", "plt.subplot(1, 2, 1)\n", "plt.imshow(np.log(1 + 100 * Y), aspect='auto', origin='lower', cmap='gray_r')\n", "plt.title('Original spectrogram')\n", "plt.colorbar()\n", "plt.subplot(1, 2, 2)\n", "plt.imshow(np.log(1 + 100 * Y_filt), aspect='auto', origin='lower', cmap='gray_r')\n", "plt.title('Smoothed spectrogram')\n", "plt.colorbar()\n", "plt.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the same function we use the `jit`-decorator to compile it. In the following code, we check that the outputs of the resulting function is the same as before and then report on the runtime." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:02:30.125428Z", "iopub.status.busy": "2024-02-15T09:02:30.125096Z", "iopub.status.idle": "2024-02-15T09:02:31.858156Z", "shell.execute_reply": "2024-02-15T09:02:31.857569Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Runtime for naive implementation: 0.22267 seconds\n", "Runtime for jit implementation: 0.00130 seconds\n" ] } ], "source": [ "from numba import jit\n", "import timeit\n", "\n", "@jit(nopython=True)\n", "def spectrogram_average_filter_jit(Y, filter_len):\n", " K, N = Y.shape\n", " \n", " filter_left = filter_len // 2\n", " filter_right = filter_len - filter_left - 1\n", "\n", " Y_pad = np.concatenate((np.zeros((K, filter_left)), Y, \n", " np.zeros((K, filter_right))), axis=1) \n", " Y_new = np.empty_like(Y)\n", " \n", " for k in range(K):\n", " for n in range(N):\n", " Y_new[k, n] = Y_pad[k, n:n+filter_len].sum() / filter_len\n", " \n", " return Y_new\n", "\n", "filter_length = 21\n", "Y_filt_naive = spectrogram_average_filter_naive(Y, filter_length)\n", "Y_filt_jit = spectrogram_average_filter_jit(Y, filter_length)\n", "assert np.allclose(Y_filt_naive, Y_filt_jit)\n", "\n", "execuctions = 3\n", "time_nai = timeit.timeit(lambda: spectrogram_average_filter_naive(Y, filter_length), \n", " number=execuctions) / execuctions\n", "time_jit = timeit.timeit(lambda: spectrogram_average_filter_jit(Y, filter_length), \n", " number=execuctions) / execuctions\n", "print('Runtime for naive implementation: %7.5f seconds' % time_nai)\n", "print('Runtime for jit implementation: %7.5f seconds' % time_jit)\n", "\n", "# An alternative for measuring running time:\n", "# %timeit spectrogram_average_filter_naive(Y, filter_length)\n", "# %timeit spectrogram_average_filter_jit(Y, filter_length)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parellel Computing\n", "\n", "On a standard computer, this the `jit`-compiled function may be about 100 times faster then the original one. With multiple CPU cores, one can obtain further accelerations by parallelizing the loops." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:02:31.860910Z", "iopub.status.busy": "2024-02-15T09:02:31.860657Z", "iopub.status.idle": "2024-02-15T09:02:34.469276Z", "shell.execute_reply": "2024-02-15T09:02:34.468061Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Runtime for naive implementation: 0.21584 seconds\n", "Runtime for jit implementation: 0.00130 seconds\n", "Runtime for parallel implementation (using 12 threads): 0.00056 seconds\n" ] } ], "source": [ "import numba\n", "from numba import jit, prange\n", "\n", "@jit(nopython=True, parallel=True)\n", "def spectrogram_average_filter_parallel(Y, filter_len):\n", " K, N = Y.shape\n", " filter_left = filter_len // 2\n", " filter_right = filter_len - filter_left - 1\n", " Y_pad = np.concatenate((np.zeros((K, filter_left)), Y, \n", " np.zeros((K, filter_right))), axis=1)\n", " Y_new = np.empty_like(Y)\n", " for k in prange(K):\n", " for n in prange(N):\n", " Y_new[k, n] = Y_pad[k, n:n+filter_len].sum() / filter_len\n", " return Y_new\n", "\n", "filter_length = 21\n", "Y_filt_naive = spectrogram_average_filter_naive(Y, filter_length)\n", "Y_filt_jit = spectrogram_average_filter_jit(Y, filter_length)\n", "Y_filt_parallel = spectrogram_average_filter_parallel(Y, filter_length)\n", "assert np.allclose(Y_filt_naive, Y_filt_parallel)\n", "\n", "execuctions=3\n", "time_nai = timeit.timeit(lambda: spectrogram_average_filter_naive(Y, filter_length), \n", " number=execuctions) / execuctions\n", "time_jit = timeit.timeit(lambda: spectrogram_average_filter_jit(Y, filter_length), \n", " number=execuctions) / execuctions\n", "time_par = timeit.timeit(lambda: spectrogram_average_filter_parallel(Y, filter_length), \n", " number=execuctions) / execuctions\n", "\n", "num_threads = numba.config.NUMBA_DEFAULT_NUM_THREADS\n", "\n", "print('Runtime for naive implementation: %7.5f seconds' % time_nai)\n", "print('Runtime for jit implementation: %7.5f seconds' % time_jit)\n", "print('Runtime for parallel implementation (using %d threads): %7.5f seconds' % (num_threads, time_par))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Loop-Based vs. Matrix-Based Implemetation\n", "\n", "The function implements the smoothing filter as a naive double-nested look. When using packages like NumPy, it is often much more efficient to use matrix operations while avoiding loop structures. Still the `jit`-compiled versions may be a bit faster." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:02:34.472989Z", "iopub.status.busy": "2024-02-15T09:02:34.472796Z", "iopub.status.idle": "2024-02-15T09:02:35.379059Z", "shell.execute_reply": "2024-02-15T09:02:35.378228Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Runtime for naive implementation: 0.21584 seconds\n", "Runtime for jit implementation: 0.00134 seconds\n", "Runtime for parallel implementation (using 12 threads): 0.00048 seconds\n", "Runtime for matrix implementation: 0.00304 seconds\n" ] } ], "source": [ "def spectrogram_average_filter_matrix(Y, filter_len):\n", " K, N = Y.shape\n", " filter_left = filter_len // 2\n", " filter_right = filter_len - filter_left - 1\n", " Y_pad = np.concatenate((np.zeros((K, filter_left)), Y, np.zeros((K, filter_right))), axis=1)\n", " Y_new = np.empty_like(Y)\n", " for n in range(N):\n", " Y_new[:, n] = np.mean(Y_pad[:, n:n+filter_len], axis=1)\n", " return Y_new\n", "\n", "filter_length = 21\n", "Y_filt_naive = spectrogram_average_filter_naive(Y, filter_length)\n", "Y_filt_jit = spectrogram_average_filter_jit(Y, filter_length)\n", "Y_filt_parallel = spectrogram_average_filter_parallel(Y, filter_length)\n", "Y_filt_matrix = spectrogram_average_filter_matrix(Y, filter_length)\n", "assert np.allclose(Y_filt_naive, Y_filt_matrix)\n", "\n", "execuctions = 3\n", "time_naive = timeit.timeit(lambda: spectrogram_average_filter_naive(Y, filter_length), \n", " number=execuctions) / execuctions\n", "time_jit = timeit.timeit(lambda: spectrogram_average_filter_jit(Y, filter_length), \n", " number=execuctions) / execuctions\n", "time_par = timeit.timeit(lambda: spectrogram_average_filter_parallel(Y, filter_length), \n", " number=execuctions) / execuctions\n", "time_mat = timeit.timeit(lambda: spectrogram_average_filter_matrix(Y, filter_length), \n", " number=execuctions) / execuctions\n", "\n", "num_threads = numba.config.NUMBA_DEFAULT_NUM_THREADS\n", "\n", "print('Runtime for naive implementation: %7.5f seconds' % time_nai)\n", "print('Runtime for jit implementation: %7.5f seconds' % time_jit)\n", "print('Runtime for parallel implementation (using %d threads): %7.5f seconds' % (num_threads, time_par))\n", "print('Runtime for matrix implementation: %7.5f seconds' % time_mat)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Deviations from Python Semantics\n", "\n", "Note that **not all features** of Python and Numpy are available when compiling with Numba, see the list of [supported Python features](https://numba.pydata.org/numba-doc/dev/reference/pysupported.html) and the list of [supported NumPy features](https://numba.pydata.org/numba-doc/dev/reference/numpysupported.html) for more details. For example, we cannot `jit`-compile the last version of our function `spectrogram_average_filter_matrix` due to the keyword `axis` used in the function `mean`." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:02:35.381752Z", "iopub.status.busy": "2024-02-15T09:02:35.381561Z", "iopub.status.idle": "2024-02-15T09:02:35.418717Z", "shell.execute_reply": "2024-02-15T09:02:35.417911Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Got a TypingError because of an unsupported numpy feature in numba.\n" ] } ], "source": [ "@jit(nopython=True)\n", "def spectrogram_average_filter_matrixJit(Y, filter_len):\n", " K, N = Y.shape\n", " \n", " filter_left = filter_len // 2\n", " filter_right = filter_len - filter_left\n", " \n", " Y_pad = np.concatenate((np.zeros((K, filter_left)), Y, np.zeros((K, filter_right))), axis=1)\n", " Y_new = np.empty_like(Y)\n", " \n", " for n in range(K):\n", " Y_new[:, n] = np.mean(Y_pad[:, n:n+filter_len], axis=1)\n", " \n", " return Y_new\n", "\n", "try:\n", " Y_filt_matrixJit = spectrogram_average_filter_matrixJit(Y, 12)\n", "except Exception as ex:\n", " print('Got a %s because of an unsupported numpy feature in numba.' % type(ex).__name__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In particular, the usage of data types that are determined during runtime may cause unexpected errors. In the following, we give some examples, which work for usual Python functions, but cause problems when using `jit`:\n", "\n", "\n", "* The command `np.zeros([n, n])` does not work when using `jit`. It needs to be replaced by `np.zeros((n, n))`.\n", "* `axis` keyword in numpy function $\\leadsto$ loop\n", "* optional argument used as index (argument `arg=None`) $\\leadsto$ use different variable name inside function\n", "* binary masking for multidimensional arrays $\\leadsto$ loop over indexes" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2024-02-15T09:02:35.421803Z", "iopub.status.busy": "2024-02-15T09:02:35.421499Z", "iopub.status.idle": "2024-02-15T09:02:35.431227Z", "shell.execute_reply": "2024-02-15T09:02:35.430656Z" } }, "outputs": [], "source": [ "def matrix_zeros_nojit(n=5):\n", " result1 = np.zeros([n, n])\n", " result2 = np.zeros((n, n), 'int')\n", " result3 = np.zeros((n, n)).astype('int')\n", " return result1, result2, result3\n", "\n", "@jit(nopython=True)\n", "def matrix_zeros_jit(n=5):\n", " result1 = np.zeros((n, n))\n", " result2 = np.zeros((n, n), np.int64)\n", " result3 = np.zeros((n, n)).astype(np.int32)\n", " return result1, result2, result3\n", "\n", "\n", "def average_axis0_nojit(x):\n", " result = np.mean(x, axis=0)\n", " return result\n", "\n", "@jit(nopython=True)\n", "def average_axis0_jit(x):\n", " result = np.empty(x.shape[1])\n", " for i in range(x.shape[1]):\n", " result[i] = np.mean(x[:, i])\n", " return result\n", "\n", "\n", "def optional_arg_nojit(x, idx=None):\n", " x = np.arange(3)\n", " if idx is None:\n", " idx = np.argmin(x)\n", " return x[idx]\n", "\n", "@jit(nopython=True)\n", "def optional_arg_jit(x, idx=None):\n", " if idx is None:\n", " _idx = np.argmin(x)\n", " else:\n", " _idx = idx\n", " return x[_idx]\n", "\n", "def treshold_nojit(x, tresh):\n", " x = x.copy()\n", " x[x > tresh] = 0\n", " return x\n", "\n", "@jit(nopython=True)\n", "def treshold_jit(x, tresh):\n", " x = x.copy()\n", " for idx1, idx2 in zip(*np.where(x > tresh)):\n", " x[idx1, idx2] = 0.0\n", " return x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Acknowledgment: This notebook was created by Frank Zalkow and Meinard Müller.\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n", "
\"C0\"\"C1\"\"C2\"\"C3\"\"C4\"\"C5\"\"C6\"\"C7\"\"C8\"
" ] } ], "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.16" } }, "nbformat": 4, "nbformat_minor": 1 }