Vecteur de valeurs¶

In [1]:
#Python
import sys
sys.version
Out[1]:
'3.11.11 | packaged by conda-forge | (main, Dec  5 2024, 14:06:23) [MSC v.1942 64 bit (AMD64)]'
In [2]:
#numpy
import numpy
numpy.__version__
Out[2]:
'2.2.1'
In [3]:
#nombre de valeurs
n = 3000
In [4]:
#vecteur de valeurs
rng = numpy.random.default_rng(seed=2024)
v = rng.random(size=n)
v.shape
Out[4]:
(3000,)

Programme recherche extremum¶

In [5]:
#sans directive particulière
#side = 0 -> min ; side != 0 -> max
def extremum(x,side):
    #copie locale
    vec = numpy.copy(x)
    n = len(vec)
    #tri à bulles -- https://fr.wikipedia.org/wiki/Tri_à_bulles
    for i in range(n-1,0,-1):
        for j in range(0,i):
            if (vec[j+1] < vec[j]):
                temp = vec[j+1]
                vec[j+1] = vec[j]
                vec[j] = temp
    #déterminer l'extremum à renvoyer
    res = vec[0] if side == 0 else vec[-1]
    #renvoyer l'extremum
    return res
In [6]:
#obtenir le minimum
print(extremum(v,0))
0.00042384932857031377
In [7]:
#temps de calcul
%timeit extremum(v,0)
1.47 s ± 6.06 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Passage en cython (brut)¶

In [8]:
#importation de la librairie
import cython
In [9]:
#activer la possibilité de compiler en Cython
#le contenu des cellules du notebook
%load_ext Cython

La directive %%cython indique une cellule Cython, c.-à-d. le code sera compilé suivant Cython

In [10]:
%%cython

import numpy as np 

def cy_extremum_v1(x,side):
    #copie locale
    vec = np.copy(x)
    n = len(vec)
    #tri à bulles -- https://fr.wikipedia.org/wiki/Tri_à_bulles
    for i in range(n-1,0,-1):
        for j in range(0,i):
            if (vec[j+1] < vec[j]):
                temp = vec[j+1]
                vec[j+1] = vec[j]
                vec[j] = temp
    #déterminer l'extremum à renvoyer
    res = vec[0] if side == 0 else vec[-1]
    #renvoyer l'extremum
    return res
Content of stdout:
_cython_magic_e7fe84a444ec2fb634b4062456cd7c37a67abc33.c
   Cr‚ation de la bibliothŠque C:\Users\ricco\.ipython\cython\Users\ricco\.ipython\cython\_cython_magic_e7fe84a444ec2fb634b4062456cd7c37a67abc33.cp311-win_amd64.lib et de l'objet C:\Users\ricco\.ipython\cython\Users\ricco\.ipython\cython\_cython_magic_e7fe84a444ec2fb634b4062456cd7c37a67abc33.cp311-win_amd64.exp
G‚n‚ration de code en cours
Fin de la g‚n‚ration du code
In [11]:
print(cy_extremum_v1(v,0))
0.00042384932857031377
In [12]:
#temps de calcul
%timeit cy_extremum_v1(v,0)
1.11 s ± 16.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Passage en Cython (réécriture)¶

In [13]:
%%cython

import numpy as np

def cy_extremum_v2(double[:] x, int side):
    #copie locale
    cdef double [:] vec = np.copy(x) 
    cdef int n = len(vec)
    cdef int i, j
    #tri à bulles -- https://fr.wikipedia.org/wiki/Tri_à_bulles
    for i in range(n-1,0,-1):
        for j in range(0,i):
            if (vec[j+1] < vec[j]):
                temp = vec[j+1]
                vec[j+1] = vec[j]
                vec[j] = temp
    #déterminer l'extremum à renvoyer
    res = vec[0] if side == 0 else vec[-1]
    #renvoyer l'extremum
    return res
Content of stdout:
_cython_magic_817bed3a9a53291d91099a1f4bf6f28559c6ec9f.c
C:\Users\ricco\.ipython\cython\_cython_magic_817bed3a9a53291d91099a1f4bf6f28559c6ec9f.c(17563): warning C4244: '='ÿ: conversion de 'Py_ssize_t' en 'int', perte possible de donn‚es
   Cr‚ation de la bibliothŠque C:\Users\ricco\.ipython\cython\Users\ricco\.ipython\cython\_cython_magic_817bed3a9a53291d91099a1f4bf6f28559c6ec9f.cp311-win_amd64.lib et de l'objet C:\Users\ricco\.ipython\cython\Users\ricco\.ipython\cython\_cython_magic_817bed3a9a53291d91099a1f4bf6f28559c6ec9f.cp311-win_amd64.exp
G‚n‚ration de code en cours
Fin de la g‚n‚ration du code
In [14]:
#vérification
print(cy_extremum_v2(v,0))
0.00042384932857031377
In [15]:
#temps de calcul
%timeit cy_extremum_v2(v,0)
17.2 ms ± 47.7 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Passage Cython (bis) - Directives de compilation¶

In [16]:
%%cython

import numpy as np
cimport cython

@cython.boundscheck(False) # turn off bounds-checking for entire function
@cython.wraparound(False)  # turn off negative index wrapping for entire function
def cy_extremum_v3(double[:] x, int side):
    #copie locale
    cdef double [:] vec = np.copy(x) 
    cdef int n = len(vec)
    cdef int i, j
    #tri à bulles -- https://fr.wikipedia.org/wiki/Tri_à_bulles
    for i in range(n-1,0,-1):
        for j in range(0,i):
            if (vec[j+1] < vec[j]):
                temp = vec[j+1]
                vec[j+1] = vec[j]
                vec[j] = temp
    #déterminer l'extremum à renvoyer
    res = vec[0] if side == 0 else vec[-1]
    #renvoyer l'extremum
    return res
warning: C:\Users\ricco\.ipython\cython\_cython_magic_e490aa4b255cda2a5daf7f1c34104178cff02808.pyx:20:40: the result of using negative indices inside of code sections marked as 'wraparound=False' is undefined
Content of stdout:
_cython_magic_e490aa4b255cda2a5daf7f1c34104178cff02808.c
C:\Users\ricco\.ipython\cython\_cython_magic_e490aa4b255cda2a5daf7f1c34104178cff02808.c(17578): warning C4244: '='ÿ: conversion de 'Py_ssize_t' en 'int', perte possible de donn‚es
   Cr‚ation de la bibliothŠque C:\Users\ricco\.ipython\cython\Users\ricco\.ipython\cython\_cython_magic_e490aa4b255cda2a5daf7f1c34104178cff02808.cp311-win_amd64.lib et de l'objet C:\Users\ricco\.ipython\cython\Users\ricco\.ipython\cython\_cython_magic_e490aa4b255cda2a5daf7f1c34104178cff02808.cp311-win_amd64.exp
G‚n‚ration de code en cours
Fin de la g‚n‚ration du code
In [17]:
#vérification
print(cy_extremum_v3(v,0))
0.00042384932857031377
In [18]:
#temps de calcul
%timeit cy_extremum_v3(v,0)
8.56 ms ± 60.1 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)