Commit 636b008a authored by Pierre Augier's avatar Pierre Augier
Browse files

Improve test JIT (brocken for Cython!)

parent cc0dc757ea09
clean:
rm -rf __cython__ __numba__ __pythran__ __python__
all:
TRANSONIC_BACKEND="pythran" transonic -np *.py
TRANSONIC_BACKEND="python" transonic -np *.py
TRANSONIC_BACKEND="cython" transonic -np *.py
TRANSONIC_BACKEND="numba" transonic -np *.py
meld_pythran:
meld __pythran__ saved__backend__/pythran
meld_python:
meld __python__ saved__backend__/python
meld_cython:
meld __cython__ saved__backend__/cython
meld_numba:
meld __numba__ saved__backend__/numba
......@@ -2,40 +2,46 @@ import numpy as np
from transonic import boost, Array
MV2d = Array[np.int64, "2d", "memview"]
MV1d = Array[np.int64, "1d", "memview"]
T_index = np.int32
# we use a type variable because it can be replaced by a fused type.
T = np.int64
A1d_i = Array[T_index, "1d"]
A1d = Array[T, "1d"]
A2d = Array[T, "2d"]
V1d_i = Array[T_index, "1d", "memview"]
V1d = Array[T, "1d", "memview"]
V2d = Array[T, "2d", "memview"]
T0 = "int[:, :]"
T1 = "int[:]"
@boost
def row_sum(arr: A2d, columns: A1d_i):
return arr.T[columns].sum(0)
@boost(boundscheck=False, wraparound=False)
def row_sum_loops(arr: MV2d, columns: MV1d):
def row_sum_loops(arr: V2d, columns: V1d_i):
# locals type annotations are used only for Cython
i: int
j: int
sum_: int
res: MV1d = np.empty(arr.shape[0], dtype=np.int64)
i: T_index
j: T_index
sum_: T
# arr.dtype not supported for memoryview
dtype = type(arr[0, 0])
res: V1d = np.empty(arr.shape[0], dtype=dtype)
for i in range(arr.shape[0]):
sum_ = 0
sum_ = dtype(0)
for j in range(columns.shape[0]):
sum_ += arr[i, columns[j]]
res[i] = sum_
return res
@boost
def row_sum_transpose(arr: T0, columns: T1):
return arr.T[columns].sum(0)
if __name__ == "__main__":
from util import check, bench
functions = [row_sum_loops, row_sum_transpose]
functions = [row_sum, row_sum_loops]
arr = np.arange(1_000_000).reshape(1_000, 1_000)
columns = np.arange(1, 1000, 2)
columns = np.arange(1, 1000, 2, dtype=T_index)
check(functions, arr, columns)
bench(functions, arr, columns)
......@@ -3,19 +3,19 @@ import cython
import numpy as np
cimport numpy as np
ctypedef fused __row_sum_arr:
np.ndarray[np.int64_t, ndim=2]
ctypedef fused __row_sum_columns:
np.ndarray[np.int32_t, ndim=1]
cpdef row_sum(__row_sum_arr arr, __row_sum_columns columns)
ctypedef fused __row_sum_loops_arr:
np.int64_t[:, :]
ctypedef fused __row_sum_loops_columns:
np.int64_t[:]
np.int32_t[:]
@cython.locals(i=cython.int, j=cython.int, sum_=cython.int, res=np.int64_t[:])
@cython.locals(i=np.int32_t, j=np.int32_t, sum_=np.int64_t, res=np.int64_t[:])
cpdef row_sum_loops(__row_sum_loops_arr arr, __row_sum_loops_columns columns)
ctypedef fused __row_sum_transpose_arr:
np.ndarray[np.int_t, ndim=2]
ctypedef fused __row_sum_transpose_columns:
np.ndarray[np.int_t, ndim=1]
cpdef row_sum_transpose(__row_sum_transpose_arr arr, __row_sum_transpose_columns columns)
......@@ -6,21 +6,23 @@ except ImportError:
import numpy as np
def row_sum(arr, columns):
return arr.T[columns].sum(0)
@cython.boundscheck(False)
@cython.wraparound(False)
def row_sum_loops(arr, columns):
# locals type annotations are used only for Cython
res = np.empty(arr.shape[0], dtype=np.int64)
# arr.dtype not supported for memoryview
dtype = type(arr[(0, 0)])
res = np.empty(arr.shape[0], dtype=dtype)
for i in range(arr.shape[0]):
sum_ = 0
sum_ = dtype(0)
for j in range(columns.shape[0]):
sum_ += arr[(i, columns[j])]
res[i] = sum_
return res
def row_sum_transpose(arr, columns):
return arr.T[columns].sum(0)
__transonic__ = ("0.3.3",)
......@@ -4,22 +4,24 @@ import numpy as np
# __protected__ @njit
def row_sum(arr, columns):
return arr.T[columns].sum(0)
# __protected__ @njit
def row_sum_loops(arr, columns):
# locals type annotations are used only for Cython
res = np.empty(arr.shape[0], dtype=np.int64)
# arr.dtype not supported for memoryview
dtype = type(arr[(0, 0)])
res = np.empty(arr.shape[0], dtype=dtype)
for i in range(arr.shape[0]):
sum_ = 0
sum_ = dtype(0)
for j in range(columns.shape[0]):
sum_ += arr[(i, columns[j])]
res[i] = sum_
return res
# __protected__ @njit
def row_sum_transpose(arr, columns):
return arr.T[columns].sum(0)
__transonic__ = ("0.3.3",)
__transonic__ = ("0.3.3.post0",)
import numpy as np
def row_sum(arr, columns):
return arr.T[columns].sum(0)
def row_sum_loops(arr, columns):
# locals type annotations are used only for Cython
res = np.empty(arr.shape[0], dtype=np.int64)
# arr.dtype not supported for memoryview
dtype = type(arr[(0, 0)])
res = np.empty(arr.shape[0], dtype=dtype)
for i in range(arr.shape[0]):
sum_ = 0
sum_ = dtype(0)
for j in range(columns.shape[0]):
sum_ += arr[(i, columns[j])]
res[i] = sum_
return res
def row_sum_transpose(arr, columns):
return arr.T[columns].sum(0)
__transonic__ = ("0.3.3",)
__transonic__ = ("0.3.3.post0",)
import numpy as np
def row_sum(arr, columns):
return arr.T[columns].sum(0)
def row_sum_loops(arr, columns):
# locals type annotations are used only for Cython
res = np.empty(arr.shape[0], dtype=np.int64)
# arr.dtype not supported for memoryview
dtype = type(arr[(0, 0)])
res = np.empty(arr.shape[0], dtype=dtype)
for i in range(arr.shape[0]):
sum_ = 0
sum_ = dtype(0)
for j in range(columns.shape[0]):
sum_ += arr[(i, columns[j])]
res[i] = sum_
return res
def row_sum_transpose(arr, columns):
return arr.T[columns].sum(0)
__transonic__ = ("0.3.3",)
__transonic__ = ("0.3.3.post0",)
export row_sum_loops(int64[:, :], int64[:])
export row_sum(int64[:, :], int32[:])
export row_sum_transpose(int[:, :], int[:])
export row_sum_loops(int64[:, :], int32[:])
export __transonic__
......@@ -2,27 +2,33 @@ import numpy as np
from transonic import boost, Array
MV1d = Array[np.int64, "1d", "memview"]
MV2d = Array[np.int64, "2d", "memview"]
A1d = "int[:]"
A2d = "int[:, :]"
T_index = np.int32
# we use a type variable because it can be replaced by a fused type.
T = np.int64
A1d_i = Array[T_index, "1d"]
A1d = Array[T, "1d"]
A2d = Array[T, "2d"]
V1d_i = Array[T_index, "1d", "memview"]
V1d = Array[T, "1d", "memview"]
V2d = Array[T, "2d", "memview"]
@boost
def row_sum(arr: A2d, columns: A1d):
def row_sum(arr: A2d, columns: A1d_i):
return arr.T[columns].sum(0)
@boost(boundscheck=False, wraparound=False)
def row_sum_loops(arr: MV2d, columns: MV1d):
def row_sum_loops(arr: V2d, columns: V1d_i):
# locals type annotations are used only for Cython
i: int
j: int
sum_: int
res: MV1d = np.empty(arr.shape[0], dtype=np.int64)
i: T_index
j: T_index
sum_: T
# arr.dtype not supported for memoryview
dtype = type(arr[0, 0])
res: V1d = np.empty(arr.shape[0], dtype=dtype)
for i in range(arr.shape[0]):
sum_ = 0
sum_ = dtype(0)
for j in range(columns.shape[0]):
sum_ += arr[i, columns[j]]
res[i] = sum_
......@@ -35,7 +41,7 @@ if __name__ == "__main__":
functions = [row_sum, row_sum_loops]
arr = np.arange(1_000_000).reshape(1_000, 1_000)
columns = np.arange(1, 1000, 2)
columns = np.arange(1, 1000, 2, dtype=T_index)
check(functions, arr, columns)
bench(functions, arr, columns)
......@@ -30,31 +30,31 @@ To compile this file with different backends, one can run:
TRANSONIC_BACKEND="numba" transonic row_sum_boost.py
TRANSONIC_BACKEND="pythran" transonic row_sum_boost.py -pf "-march=native -DUSE_XSIMD"
Then, on my PC, I get::
Then, on my PC (meige8pcpa79), I get::
TRANSONIC_BACKEND="python" python row_sum_boost.py
Checks passed: results are consistent
Python
row_sum 1.2e-03 s
row_sum_loops 1.0e-01 s
row_sum 2.0e-03 s
row_sum_loops 1.6e-01 s
TRANSONIC_BACKEND="cython" python row_sum_boost.py
Checks passed: results are consistent
Cython
row_sum 1.3e-03 s
row_sum_loops 3.8e-04 s
row_sum 2.0e-03 s
row_sum_loops 5.2e-04 s
TRANSONIC_BACKEND="numba" python row_sum_boost.py
Checks passed: results are consistent
Numba
row_sum 1.1e-03 s
row_sum_loops 2.6e-04 s
row_sum 1.9e-03 s
row_sum_loops 4.4e-04 s
TRANSONIC_BACKEND="pythran" python row_sum_boost.py
Checks passed: results are consistent
Pythran
row_sum 8.2e-04 s
row_sum_loops 2.6e-04 s
row_sum 1.1e-03 s
row_sum_loops 4.2e-04 s
The fastest solutions are in this case the Numba and Pythran backends for the
implementation with explicit loops.
......@@ -63,9 +63,8 @@ As usual, Pythran gives quite good results with the high-level implementation,
but in this case, it is still more than twice slower than the implementation
with loops.
There are rooms for improvements for the Cython backend (in particular,
:code:`@cython.boundscheck(False) @cython.wraparound(False)` are currently not
used), which could explain the lower performance of Cython.
Cython does not accelerate high-level Numpy code but gives good results for the
implementation with loops.
Just-in-time compilation
------------------------
......
......@@ -25,6 +25,7 @@ mpi =
test =
pytest
pytest-cov
pytest-xdist
# git+https://github.com/zonca/pytest-ipynb#egg=pytest-ipynb
numpy
pythran
......
......@@ -46,6 +46,9 @@ def test_jit():
func1(a, b)
sleep(0.1)
wait_for_all_extensions()
func1(a, b)
def test_fib():
from .for_test_justintime import fib, use_fib
......
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