Commit bc7861d9 authored by paugier's avatar paugier
Browse files

Mainly more Pythran

parent 9ae49ad3
## Timing:
We use [invoke](https://www.pyinvoke.org/) (`pip install invoke`) to build and run the benchmarks. After `inv build`, you should get something like this:
We use [invoke](https://www.pyinvoke.org/) (`pip install invoke`) to build and run the benchmarks.
See [how to get autocompletion with invoke](http://docs.pyinvoke.org/en/1.2/invoke.html?highlight=completion#cmdoption-print-completion-script).
After `inv build`, you should get something like this:
```bash
inv bench
......@@ -32,3 +36,22 @@ diff V1_numpy_loops/dtw_cort_dist_mat.py V6_pythran/dtw_cort_dist_mat.py
82a85
> @jit
```
For a longer benchmark:
```bash
inv bench --medium
V2_c_dtw/dtw_cort_dist_mat.py data_medium.npy
elapsed time = 60.530 s
V5_cython/dtw_cort_dist_mat.py data_medium.npy
elapsed time = 24.439 s
V6_pythran/dtw_cort_dist_mat.py data_medium.npy
elapsed time = 24.511 s
V6_pythran_aot/dtw_cort_dist_mat.py data_medium.npy
elapsed time = 24.563 s
V6_pythran_no_transonic/dtw_cort_dist_mat.py data_medium.npy
elapsed time = 24.586 s
V7_numba/dtw_cort_dist_mat.py data_medium.npy
elapsed time = 36.549 s
```
......@@ -3,4 +3,4 @@ all:
./dtw_cort_dist_mat.py -n 2
clean:
transonic -cc dtw_cort_dist_mat.py
\ No newline at end of file
transonic -cc dtw_cort_dist_mat.py -f
\ No newline at end of file
......@@ -6,7 +6,8 @@ from pathlib import Path
import numpy as np
from transonic import jit
from transonic import jit, wait_for_all_extensions
util = run_path(Path(__file__).absolute().parent.parent / "util.py")
......@@ -102,3 +103,5 @@ main = partial(util["main"], compute)
if __name__ == "__main__":
main()
# to be sure that the extension will be ready for the next execution
wait_for_all_extensions()
all:
transonic dtw_cort_dist_mat.py
clean:
rm -rf __pythran__
\ No newline at end of file
#!/usr/bin/env python3
from functools import partial
from runpy import run_path
from pathlib import Path
import numpy as np
from transonic import boost
util = run_path(Path(__file__).absolute().parent.parent / "util.py")
def serie_pair_index_generator(number):
""" generator for pair index (i, j) such that i < j < number
:param number: the upper bound
:returns: pairs (lower, greater)
:rtype: a generator
"""
return (
(_idx_greater, _idx_lower)
for _idx_greater in range(number)
for _idx_lower in range(number)
if _idx_lower < _idx_greater
)
def DTWDistance(s1, s2):
""" Computes the dtw between s1 and s2 with distance the absolute distance
:param s1: the first serie (ie an iterable over floats64)
:param s2: the second serie (ie an iterable over floats64)
:returns: the dtw distance
:rtype: float64
"""
len_s1 = len(s1)
len_s2 = len(s2)
_dtw_mat = np.empty([len_s1, len_s2])
_dtw_mat[0, 0] = abs(s1[0] - s2[0])
# two special cases : filling first row and columns
for j in range(1, len_s2):
dist = abs(s1[0] - s2[j])
_dtw_mat[0, j] = dist + _dtw_mat[0, j - 1]
for i in range(1, len_s1):
dist = abs(s1[i] - s2[0])
_dtw_mat[i, 0] = dist + _dtw_mat[i - 1, 0]
# filling the matrix
for i in range(1, len_s1):
for j in range(1, len_s2):
dist = abs(s1[i] - s2[j])
_dtw_mat[(i, j)] = dist + min(
_dtw_mat[i - 1, j], _dtw_mat[i, j - 1], _dtw_mat[i - 1, j - 1]
)
return _dtw_mat[len_s1 - 1, len_s2 - 1]
def cort(s1, s2):
""" Computes the cort between serie one and two (assuming they have the same length)
:param s1: the first serie (or any iterable over floats64)
:param s2: the second serie (or any iterable over floats64)
:returns: the cort distance
:rtype: float64
"""
num = 0.0
sum_square_x = 0.0
sum_square_y = 0.0
for t in range(len(s1) - 1):
slope_1 = s1[t + 1] - s1[t]
slope_2 = s2[t + 1] - s2[t]
num += slope_1 * slope_2
sum_square_x += slope_1 * slope_1
sum_square_y += slope_2 * slope_2
return num / (np.sqrt(sum_square_x * sum_square_y))
@boost
def compute(series: "float64[:, :]", nb_series: int):
gen = serie_pair_index_generator(nb_series)
_dist_mat_dtw = np.zeros((nb_series, nb_series), dtype=np.float64)
_dist_mat_cort = np.zeros((nb_series, nb_series), dtype=np.float64)
for t1, t2 in gen:
dist_dtw = DTWDistance(series[t1], series[t2])
_dist_mat_dtw[t1, t2] = dist_dtw
_dist_mat_dtw[t2, t1] = dist_dtw
dist_cort = 0.5 * (1 - cort(series[t1], series[t2]))
_dist_mat_cort[t1, t2] = dist_cort
_dist_mat_cort[t2, t1] = dist_cort
return _dist_mat_dtw, _dist_mat_cort
main = partial(util["main"], compute)
if __name__ == "__main__":
main()
import cProfile
import pstats
from time import time
from dtw_cort_dist_mat import main, compute
series, nb_series = main(only_init=True)
t0 = t0 = time()
a, b = compute(series, nb_series)
t_end = time()
print('\nelapsed time = {:.3f} s'.format(t_end - t0))
t0 = t0 = time()
cProfile.runctx("a, b = compute(series, nb_series)", globals(), locals(), "prof.pstats")
t_end = time()
s = pstats.Stats('prof.pstats')
s.sort_stats('time').print_stats(12)
print('\nelapsed time = {:.3f} s'.format(t_end - t0))
print(
'\nwith gprof2dot and graphviz (command dot):\n'
'gprof2dot -f pstats prof.pstats | dot -Tpng -o prof.png')
all:
pythran kernels_pythran.py
clean:
rm -rf *.so
\ No newline at end of file
#!/usr/bin/env python3
from functools import partial
from runpy import run_path
from pathlib import Path
from kernels_pythran import compute
util = run_path(Path(__file__).absolute().parent.parent / "util.py")
main = partial(util["main"], compute)
if __name__ == "__main__":
main()
import numpy as np
def serie_pair_index_generator(number):
" generator for pair index (i, j) such that i < j < number\n\n :param number: the upper bound\n :returns: pairs (lower, greater)\n :rtype: a generator\n "
return (
(_idx_greater, _idx_lower)
for _idx_greater in range(number)
for _idx_lower in range(number)
if (_idx_lower < _idx_greater)
)
def DTWDistance(s1, s2):
" Computes the dtw between s1 and s2 with distance the absolute distance\n\n :param s1: the first serie (ie an iterable over floats64)\n :param s2: the second serie (ie an iterable over floats64)\n :returns: the dtw distance\n :rtype: float64\n "
len_s1 = len(s1)
len_s2 = len(s2)
_dtw_mat = np.empty([len_s1, len_s2])
_dtw_mat[(0, 0)] = abs((s1[0] - s2[0]))
# two special cases : filling first row and columns
for j in range(1, len_s2):
dist = abs((s1[0] - s2[j]))
_dtw_mat[(0, j)] = dist + _dtw_mat[(0, (j - 1))]
for i in range(1, len_s1):
dist = abs((s1[i] - s2[0]))
_dtw_mat[(i, 0)] = dist + _dtw_mat[((i - 1), 0)]
# filling the matrix
for i in range(1, len_s1):
for j in range(1, len_s2):
dist = abs((s1[i] - s2[j]))
_dtw_mat[(i, j)] = dist + min(
_dtw_mat[((i - 1), j)],
_dtw_mat[(i, (j - 1))],
_dtw_mat[((i - 1), (j - 1))],
)
return _dtw_mat[((len_s1 - 1), (len_s2 - 1))]
def cort(s1, s2):
" Computes the cort between serie one and two (assuming they have the same length)\n\n :param s1: the first serie (or any iterable over floats64)\n :param s2: the second serie (or any iterable over floats64)\n :returns: the cort distance\n :rtype: float64\n\n "
num = 0.0
sum_square_x = 0.0
sum_square_y = 0.0
for t in range((len(s1) - 1)):
slope_1 = s1[(t + 1)] - s1[t]
slope_2 = s2[(t + 1)] - s2[t]
num += slope_1 * slope_2
sum_square_x += slope_1 * slope_1
sum_square_y += slope_2 * slope_2
return num / np.sqrt((sum_square_x * sum_square_y))
# pythran export compute(float64[:, :], int)
def compute(series, nb_series):
gen = serie_pair_index_generator(nb_series)
_dist_mat_dtw = np.zeros((nb_series, nb_series), dtype=np.float64)
_dist_mat_cort = np.zeros((nb_series, nb_series), dtype=np.float64)
for (t1, t2) in gen:
dist_dtw = DTWDistance(series[t1], series[t2])
_dist_mat_dtw[(t1, t2)] = dist_dtw
_dist_mat_dtw[(t2, t1)] = dist_dtw
dist_cort = 0.5 * (1 - cort(series[t1], series[t2]))
_dist_mat_cort[(t1, t2)] = dist_cort
_dist_mat_cort[(t2, t1)] = dist_cort
return (_dist_mat_dtw, _dist_mat_cort)
import cProfile
import pstats
from time import time
from dtw_cort_dist_mat import main, compute
series, nb_series = main(only_init=True)
t0 = t0 = time()
a, b = compute(series, nb_series)
t_end = time()
print('\nelapsed time = {:.3f} s'.format(t_end - t0))
t0 = t0 = time()
cProfile.runctx("a, b = compute(series, nb_series)", globals(), locals(), "prof.pstats")
t_end = time()
s = pstats.Stats('prof.pstats')
s.sort_stats('time').print_stats(12)
print('\nelapsed time = {:.3f} s'.format(t_end - t0))
print(
'\nwith gprof2dot and graphviz (command dot):\n'
'gprof2dot -f pstats prof.pstats | dot -Tpng -o prof.png')
......@@ -16,7 +16,10 @@
- [Pierre, Franck] 31_accelerators.ipynb (que retenir des exemples?)
- [Franck] pyfiles/dtw_cort_dist: option -t for testing (no plot) !!!
- [Franck] pyfiles/dtw_cort_dist:
- option -t for testing (no plot) !!!
- V10_numpy_vec
- [Pierre] Pythran without Transonic, (loop and vec) for Transonic and Numba
......
Supports Markdown
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