TIPE – CPGE
Étude et optimisation des performances des
boucles en Python
Alassane Hammadoun Aly Sangho & Oumar Diakité
CPGE Béni Mellal – MPSI 2
Encadrants : ELFATTOUH et ELHASNAOUI
2025-2026
Résumé
Ce TIPE étudie l’influence de la structure des boucles en Python sur le temps d’exécution.
Nous comparons for, while, compréhensions et vectorisation NumPy. Les résultats montrent
des gains nets des compréhensions et des accélérations massives via NumPy. Ouvertures :
JIT (Numba, PyPy), Cython, modèle polyédrique.
1. Introduction
Python est expressif mais pénalisé par l’overhead interpréteur pour les boucles volumineuses.
Problématique : influence de la structure de boucle, du travail interne et de la vectorisation sur
le temps d’exécution.
2. Étude théorique
2.1 For (itérateur C) vs while (tests en Python), compréhensions optimisées.
2.2 Coût constant derrière O(n) expliquant des écarts sensibles.
2.3 Récursion : limite de profondeur et coût d’appel.
2.4 Vectorisation NumPy : boucles en C, SIMD/BLAS.
2.5 Modèle polyédrique : transformations de nids de boucles pour localité et parallélisme.
3. Démarche expérimentale
Trois expériences : (1) for/while/compréhension ; (2) travail interne ; (3) NumPy vs Python.
4. Résultats – Graphiques comparatifs
Figure 1. Comparaison des temps d’exécution en fonction de N.
Figure 2. Influence du travail interne par itération (N fixé).
5. Analyse et interprétation
While < for < compréhension (construction de liste). Quand l’opération interne domine, la
structure de boucle pèse moins. NumPy surclasse Python pur sur grands N.
6. Conclusion et ouvertures
Privilégier for aux while, compréhensions quand adapté, vectoriser (NumPy). Ouvertures : JIT
(Numba, PyPy), Cython, parallélisation, localité (polyédrique).
7. Bibliographie (sélection)
• Documentation Python 3 – [Link].
• NumPy – [Link] (vectorisation).
• Comparaisons Python vs NumPy (mesures publiques).
• Modèle polyédrique – ressources académiques, Polly/LLVM, Pluto.
8. Annexes – Codes des expériences (complets)
Annexe A – Expérience 1 : for vs while vs compréhension
import time
N = 1_000_000
# Boucle for
t0 = [Link]()
lst_for = []
for i in range(N):
lst_for.append(i)
t_for = [Link]() - t0
print(f"for: {t_for:.4f}s")
# Boucle while
t0 = [Link]()
lst_while = []
i = 0
while i < N:
lst_while.append(i)
i += 1
t_while = [Link]() - t0
print(f"while: {t_while:.4f}s")
# Compréhension de liste
t0 = [Link]()
lst_comp = [i for i in range(N)]
t_comp = [Link]() - t0
print(f"list comprehension: {t_comp:.4f}s")
Annexe B – Expérience 2 : influence des opérations internes
import time
N = 10_000
# Opération légère
t0 = [Link]()
s = 0
for _ in range(N):
s += 1
t_light = [Link]() - t0
print(f"léger: {t_light:.4f}s")
# Opération lourde (1000 multiplications par itération)
t0 = [Link]()
acc = 0.0
for _ in range(N):
x = 1.0001
for _ in range(1000):
x *= 1.0001
acc += x
t_heavy = [Link]() - t0
print(f"lourd: {t_heavy:.4f}s")
Annexe C – Expérience 3 : NumPy vectorisé vs boucle Python
import numpy as np
import time
N = 2_000_000
data_list = list(range(N))
data_array = [Link](data_list)
# Boucle Python
t0 = [Link]()
res_list = [x + 5 for x in data_list]
t_py = [Link]() - t0
print(f"boucle Python: {t_py:.4f}s")
# NumPy vectorisé
t0 = [Link]()
res_arr = data_array + 5
t_np = [Link]() - t0
print(f"NumPy: {t_np:.4f}s")