Commit 7a7ddbd3 authored by Pierre Augier's avatar Pierre Augier
Browse files

Rewrite the comparison Numba / Pythran with Transonic!

parent fb6302e061fb
......@@ -9,16 +9,16 @@ setup.py & more than one backend at runtime
Good example: https://github.com/martibosch/pylandstats/pull/1
- ``make_backend_files(backend_default="cython")``
- More than one backend at runtime
- [done?] ``make_backend_files(backend_default="cython")``
- [done?] More than one backend at runtime
- [done] "python" backend (equivalent to NO_REPLACE)
- Warnings if file not compiled
- ``TRANSONIC_BACKEND`` changes only ``backend_default``
- [done?] ``TRANSONIC_BACKEND`` changes only ``backend_default``
- Examples setup.py in documentation
Specify backend in code
-----------------------
[done?] Specify backend in code
-------------------------------
.. code:: python
......@@ -31,7 +31,7 @@ Specify backend in code
And same with ``boost``.
- Rewrite the comparison Numba / Pythran with Transonic
- [done] Rewrite the comparison Numba / Pythran with Transonic
Cython backend (beta version)
-----------------------------
......
......@@ -15,19 +15,7 @@ def laplace_numpy(image):
return thresh
@jit(native=True, xsimd=True)
def laplace_pythran(image):
"""Laplace operator in NumPy for 2D images."""
laplacian = (
image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:]
- 4*image[1:-1, 1:-1]
)
thresh = np.abs(laplacian) > 0.05
return thresh
@jit(native=True, xsimd=True)
def laplace_pythran_loops(image):
def laplace_loops(image):
"""Laplace operator for 2D images."""
h = image.shape[0]
w = image.shape[1]
......@@ -41,31 +29,17 @@ def laplace_pythran_loops(image):
return laplacian
@numba.jit(nopython=True, cache=True, fastmath=True)
def laplace_numba(image):
"""Laplace operator in NumPy for 2D images. Numba accelerated."""
laplacian = (
image[:-2, 1:-1] + image[2:, 1:-1] + image[1:-1, :-2] + image[1:-1, 2:]
- 4*image[1:-1, 1:-1]
)
thresh = np.abs(laplacian) > 0.05
return thresh
@numba.jit(nopython=True, cache=True, fastmath=True)
def laplace_numba_loops(image):
"""Laplace operator for 2D images. Numba accelerated."""
h = image.shape[0]
w = image.shape[1]
laplacian = np.empty((h - 2, w - 2))
for i in range(1, h - 1):
for j in range(1, w - 1):
laplacian[i-1, j-1] = (
np.abs(image[i-1, j] + image[i+1, j] + image[i, j-1]
+ image[i, j+1] - 4*image[i, j]) > 0.05
)
return laplacian
laplace_transonic_pythran = jit(native=True, xsimd=True)(laplace_numpy)
laplace_transonic_python = jit(backend="python")(laplace_numpy)
laplace_transonic_numba = jit(backend="numba")(laplace_numpy)
laplace_numba = numba.jit(nopython=True, cache=True, fastmath=True)(laplace_numpy)
laplace_transonic_pythran_loops = jit(native=True, xsimd=True)(laplace_loops)
laplace_transonic_python_loops = jit(backend="python")(laplace_loops)
laplace_transonic_numba_loops = jit(backend="numba")(laplace_loops)
laplace_numba_loops = numba.jit(nopython=True, cache=True, fastmath=True)(
laplace_loops
)
if __name__ == "__main__":
from skimage.data import astronaut
......@@ -74,14 +48,23 @@ if __name__ == "__main__":
image = astronaut()
image = rgb2gray(image)
laplace_pythran(image)
laplace_pythran_loops(image)
laplace_transonic_python(image)
laplace_transonic_pythran(image)
laplace_transonic_pythran_loops(image)
laplace_transonic_numba(image)
laplace_transonic_numba_loops(image)
laplace_numba(image)
laplace_numba_loops(image)
wait_for_all_extensions()
# recall these functions to warm them
laplace_transonic_numba(image)
laplace_transonic_numba_loops(image)
from transonic.util import timeit
from transonic import __version__
import pythran
......@@ -93,7 +76,7 @@ if __name__ == "__main__":
if norm is None:
norm = result
result /= norm
print(f"{call:30s}: {result:.2f}")
print(f"{call.split('(')[0]:33s}: {result:.2f}")
return ret
print(
......@@ -102,8 +85,12 @@ if __name__ == "__main__":
f"numba {numba.__version__}\n"
)
norm = bench("laplace_pythran(image)")
bench("laplace_pythran_loops(image)", norm=norm)
norm = bench("laplace_transonic_pythran(image)")
print(f"norm = {norm:.2e} s")
bench("laplace_transonic_pythran_loops(image)", norm=norm)
bench("laplace_numba(image)", norm=norm)
bench("laplace_transonic_numba(image)", norm=norm)
bench("laplace_numba_loops(image)", norm=norm)
bench("laplace_transonic_numba_loops(image)", norm=norm)
bench("laplace_numpy(image)", norm=norm)
bench("laplace_transonic_python(image)", norm=norm)
......@@ -12,8 +12,8 @@ Note that it can be very convenient to use type hints **and**
.. literalinclude:: using_jit_diff_types.py
If the environment variable :code:`TRANSONIC_COMPILE_AT_IMPORT` is set, transonic
compiles at import time the functions with type hints.
If the environment variable :code:`TRANSONIC_COMPILE_AT_IMPORT` is set,
transonic compiles at import time the functions with type hints.
Comparison Numba vs Transonic
--------------------------------
......@@ -28,15 +28,20 @@ which gives:
.. code::
transonic 0.3.3
transonic 0.3.3.post0
pythran 0.9.3post1
numba 0.45.1
laplace_pythran(image) : 1.00
laplace_pythran_loops(image) : 1.38
laplace_numba(image) : 8.86
laplace_numba_loops(image) : 1.36
laplace_numpy(image) : 10.18
laplace_transonic_pythran : 1.00
norm = 1.47e-04 s
laplace_transonic_pythran_loops : 1.06
laplace_numba : 8.32
laplace_transonic_numba : 8.81
laplace_numba_loops : 1.02
laplace_transonic_numba_loops : 1.05
laplace_numpy : 7.19
laplace_transonic_python : 7.21
The warmup is much longer for Transonic-Pythran but remember that it is a
cached JIT so it is an issue only for the first call of the function. When we
......@@ -44,7 +49,4 @@ reimport the module, there is no warmup.
Then we see that **Pythran is very good to optimize high-level NumPy code!** In
contrast (with my setup and on my computer), Numba has not been able to
optimize this function.
However, Numba is good to speedup the code with loops, but even with this code,
it is still slightly slower than Pythran with the high-level NumPy code.
optimize this function. However, Numba is good to speedup the code with loops!
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment