.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "gyexamples/plot_numba.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_gyexamples_plot_numba.py: .. _l-b-numpy-numba-ort: Compares numba, numpy, onnxruntime for simple functions ======================================================= The following benchmark is inspired from `bench_arrayexprs.py `_. It compares :epkg:`numba`, :epkg:`numpy` and :epkg:`onnxruntime` for simple functions. As expected, :epkg:`numba` is better than the other options. .. contents:: :local: The functions +++++++++++++ .. GENERATED FROM PYTHON SOURCE LINES 18-61 .. code-block:: default import numpy import pandas import matplotlib.pyplot as plt from numba import jit from typing import Any import numpy as np from tqdm import tqdm from cpyquickhelper.numbers.speed_measure import measure_time from mlprodict.npy import NDArray, onnxnumpy_np from mlprodict.npy.onnx_numpy_annotation import NDArrayType import mlprodict.npy.numpy_onnx_impl as npnx # @jit(nopython=True) def sum(a, b): return a + b # @jit(nopython=True) def sq_diff(a, b): return (a - b) * (a + b) # @jit(nopython=True) def rel_diff(a, b): return (a - b) / (a + b) # @jit(nopython=True) def square(a): # Note this is currently slower than `a ** 2 + b`, due to how LLVM # seems to lower the power intrinsic. It's still faster than the naive # lowering as `exp(2 * log(a))`, though return a ** 2 def cube(a): return a ** 3 .. GENERATED FROM PYTHON SOURCE LINES 62-66 ONNX version ++++++++++ The implementation uses the numpy API for ONNX to keep the same code. .. GENERATED FROM PYTHON SOURCE LINES 66-98 .. code-block:: default @onnxnumpy_np(signature=NDArrayType(("T:all", "T"), dtypes_out=('T',)), runtime="onnxruntime") def onnx_sum_32(a, b): return a + b @onnxnumpy_np(signature=NDArrayType(("T:all", "T"), dtypes_out=('T',)), runtime="onnxruntime") def onnx_sq_diff_32(a, b): return (a - b) * (a + b) @onnxnumpy_np(signature=NDArrayType(("T:all", "T"), dtypes_out=('T',)), runtime="onnxruntime") def onnx_rel_diff_32(a, b): return (a - b) / (a + b) @onnxnumpy_np(signature=NDArrayType(("T:all", ), dtypes_out=('T',)), runtime="onnxruntime") def onnx_square_32(a): return a ** 2 @onnxnumpy_np(signature=NDArrayType(("T:all", ), dtypes_out=('T',)), runtime="onnxruntime") def onnx_cube_32(a): return a ** 3 .. GENERATED FROM PYTHON SOURCE LINES 99-101 numba optimized ++++++++++++ .. GENERATED FROM PYTHON SOURCE LINES 101-109 .. code-block:: default jitter = jit(nopython=True) nu_sum = jitter(sum) nu_sq_diff = jitter(sq_diff) nu_rel_diff = jitter(rel_diff) nu_square = jitter(square) nu_cube = jitter(cube) .. GENERATED FROM PYTHON SOURCE LINES 110-112 Benchmark ++++++++ .. GENERATED FROM PYTHON SOURCE LINES 112-177 .. code-block:: default obs = [] for n in tqdm([10, 100, 1000, 10000, 100000, 1000000]): number = 100 if n < 1000000 else 10 for dtype in [numpy.float32, numpy.float64]: samples = [ [numpy.random.uniform(1.0, 2.0, size=n).astype(dtype)], [numpy.random.uniform(1.0, 2.0, size=n).astype(dtype) for i in range(2)]] for fct1, fct2, fct3, n_inputs in [ (sum, nu_sum, onnx_sum_32, 2), (sq_diff, nu_sq_diff, onnx_sq_diff_32, 2), (rel_diff, nu_rel_diff, onnx_rel_diff_32, 2), (square, nu_square, onnx_square_32, 1), (cube, nu_cube, onnx_cube_32, 1)]: sample = samples[n_inputs - 1] if n_inputs == 2: fct1(*sample) fct1(*sample) r = measure_time('fct1(a,b)', number=number, div_by_number=True, context={'fct1': fct1, 'a': sample[0], 'b': sample[1]}) r.update(dict(dtype=dtype, name='numpy', n=n, fct=fct1.__name__)) obs.append(r) fct2(*sample) fct2(*sample) r = measure_time('fct2(a,b)', number=number, div_by_number=True, context={'fct2': fct2, 'a': sample[0], 'b': sample[1]}) r.update(dict(dtype=dtype, name='numba', n=n, fct=fct1.__name__)) obs.append(r) fct3(*sample) fct3(*sample) r = measure_time('fct3(a,b)', number=number, div_by_number=True, context={'fct3': fct3, 'a': sample[0], 'b': sample[1]}) r.update(dict(dtype=dtype, name='onnx', n=n, fct=fct1.__name__)) obs.append(r) else: fct1(*sample) fct1(*sample) r = measure_time('fct1(a)', number=number, div_by_number=True, context={'fct1': fct1, 'a': sample[0]}) r.update(dict(dtype=dtype, name='numpy', n=n, fct=fct1.__name__)) obs.append(r) fct2(*sample) fct2(*sample) r = measure_time('fct2(a)', number=number, div_by_number=True, context={'fct2': fct2, 'a': sample[0]}) r.update(dict(dtype=dtype, name='numba', n=n, fct=fct1.__name__)) obs.append(r) fct3(*sample) fct3(*sample) r = measure_time('fct3(a)', number=number, div_by_number=True, context={'fct3': fct3, 'a': sample[0]}) r.update(dict(dtype=dtype, name='onnx', n=n, fct=fct1.__name__)) obs.append(r) df = pandas.DataFrame(obs) print(df) .. rst-class:: sphx-glr-script-out .. code-block:: none 0%| | 0/6 [00:00` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_numba.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_