Introduction
Lors de l’utilisation du module Python multiprocessing
, l’efficacité de l’exécution du code dépend souvent de la minimisation des frais généraux. L’optimisation de votre code multiprocesseur permet non seulement d’accélérer vos programmes, mais aussi de les rendre plus évolutifs et plus efficaces en termes de ressources. Dans ce tutoriel, nous aborderons les meilleures pratiques et techniques pour optimiser vos flux de travail multiprocessus en réduisant les frais généraux de communication interprocessus (IPC), en gérant efficacement les pools de processus et en tirant parti de la mémoire partagée lorsque c’est nécessaire.
Minimiser la surcharge de communication inter-processus
La communication inter-processus (IPC) peut être un goulot d’étranglement important pour les performances. Voici quelques stratégies pour réduire l’impact de la communication interprocessus:
Traitement par lots:
Au lieu d’envoyer de nombreux petits messages entre les processus, regroupez les données par lots afin de minimiser le nombre de communications.Éviter les transferts de données inutiles:
Ne transmettre que les informations essentielles entre les processus. Utiliser la mémoire partagée pour les objets de données volumineux si possible.Structures de données efficaces:
Utilisez des structures de données légères qui sont plus rapides à sérialiser et à transmettre.
Exemple : Traitement par lots avec Pool.map
import multiprocessing
import time
def process_data(data_batch):
# Simuler le traitement d'un lot de données
1)
time.sleep(return sum(data_batch)
if __name__ == "__main__":
= list(range(1, 101))
data # Regrouper les données en groupes de 10
= [data[i:i+10] for i in range(0, len(data), 10)]
batches
with multiprocessing.Pool(processes=4) as pool:
= pool.map(process_data, batches)
results
print("Processed Results:", results)
Gérer efficacement les pools de processus
L’utilisation correcte des pools de processus peut vous aider à atteindre un bon équilibre entre le parallélisme et l’utilisation des ressources.
Ajuster le nombre de processus:
Faites des essais avec le nombre de processus de travail pour trouver l’équilibre optimal pour votre charge de travail spécifique.Utiliser des gestionnaires de contexte:
Utilisez le modèlewith multiprocessing.Pool() as pool:
pour vous assurer que les processus sont correctement fermés après leur exécution.Mappage asynchrone:
Pour les charges de travail plus dynamiques, envisagez d’utiliserapply_async
ouimap
pour gérer les tâches de manière asynchrone.
Exemple : Utilisation de apply_async avec un callback
import multiprocessing
def compute_square(n):
return n * n
def collect_result(result):
results.append(result)
if __name__ == "__main__":
= [1, 2, 3, 4, 5]
numbers = []
results
with multiprocessing.Pool(processes=3) as pool:
for number in numbers:
=(number,), callback=collect_result)
pool.apply_async(compute_square, args
pool.close()
pool.join()
print("Squares:", results)
Utilisation de la mémoire partagée
Dans les scénarios où plusieurs processus doivent accéder aux mêmes données sans les copier, les objets à mémoire partagée peuvent réduire considérablement les frais généraux.
Tableaux et valeurs partagés:
Utilisezmultiprocessing.Array
etmultiprocessing.Value
pour partager des données entre processus sans les frais généraux de la sérialisation.Vues de la mémoire:
Utilisez les vues mémoire ou le modulemultiprocessing.shared_memory
(disponible dans Python 3.8+) pour travailler avec des blocs de mémoire partagée.
Exemple : Utilisation d’un tableau partagé
import multiprocessing
import numpy as np
def increment_array(shared_array, size):
# Convertir la mémoire partagée en tableau numpy
= np.frombuffer(shared_array.get_obj())
arr for i in range(size):
+= 1
arr[i]
if __name__ == "__main__":
= 10
size # Créer un tableau partagé d'entiers
= multiprocessing.Array('i', range(size))
shared_array
= []
processes for _ in range(4): # Créer 4 processus
= multiprocessing.Process(target=increment_array, args=(shared_array, size))
p
processes.append(p)
p.start()
for p in processes:
p.join()
# Convertir la mémoire partagée en un tableau numpy pour afficher le résultat
= np.frombuffer(shared_array.get_obj())
result_array print("Resulting Array:", result_array)
Conclusion
L’optimisation du code multiprocessus en Python implique une combinaison de stratégies visant à réduire les frais généraux et à maximiser l’efficacité de l’exécution simultanée. En minimisant les communications interprocessus, en gérant efficacement vos pools de processus et en utilisant la mémoire partagée lorsque c’est nécessaire, vous pouvez améliorer de manière significative les performances de vos applications. Expérimentez ces techniques pour déterminer ce qui fonctionne le mieux pour vos cas d’utilisation spécifiques.
Plus d’informations
- Multitraitement et multithreading en Python
- Traitement parallèle en Python : accélérez votre code
- Débogage et journalisation efficaces en Python : meilleures pratiques
Bon codage, et que vos applications Python s’exécutent plus rapidement et plus efficacement!
Explorer d’autres articles
Voici d’autres articles de la même catégorie pour vous aider à approfondir le sujet.
Réutilisation
Citation
@online{kassambara2024,
author = {Kassambara, Alboukadel},
title = {Optimisation du code multiprocesseur en Python},
date = {2024-02-05},
url = {https://www.datanovia.com/fr/learn/programming/python/advanced/parallel-processing/optimizing-multiprocessing-code.html},
langid = {fr}
}