Comment utiliser 100% de tous les cœurs de processeur dans Python (2024)

Vous pouvez utiliser tous les cœurs CPU de votre système à près de 100% d'utilisation en utilisant la concurrence basée sur les processus.

Ceci est adapté aux tâches liées au processeur, c'est-à-dire fonctionner aussi vite que vos cœurs CPU peuvent s'exécuter.

Dans ce tutoriel, vous découvrirezComment mettre à jour les programmes Python pour utiliser tous les cœurs CPU sur votre système.

Commençons.

Table des matières

Python n'utilisera pas tous les processeurs par défaut

L'exécution d'un programme Python ordinaire n'utilisera pas tous les cœurs CPU par défaut.

Au lieu de cela, il fonctionnera sur un noyau de processeur jusqu'à la fin.

C'est un problème car les systèmes modernes ont un processeur avec 2, 4, 8 ou plus.

Cela signifie que vos programmes Python n'utilisent qu'une fraction des capacités de votre système.

Comment pouvez-vous mettre à jour vos programmes Python pour utiliser tous les cœurs CPU?

Exécutez vos boucles en utilisant tous les processeurs,Téléchargez mon livre gratuitpour apprendre comment.

Utilisez tous les processeurs via le multiprocessem*nt

Nous pouvons utiliser tous les cœurs de processeur de notre système en utilisant la concurrence basée sur les processus.

Ceci est fourni dans la bibliothèque Python Standard (vous n'avez rien à installer) via le module multiprocesseur.

La concurrence basée sur le processus créera une instance de l'interprète Python par processus pour exécuter notre code.

Nous pouvons configurer notre programme pour créer un processus Python par noyau CPU dans notre système, puis attribuer une tâche ou un appel de fonction à chaque processus.

Cela utilisera tous les cœurs CPU et utilisera pleinement notre système.

Il y a trois façons de le faire, ils sont:

  • Utilisez lemultiprocessem*nt.classe.
  • Utilisez lemultiprocessem*nt.poolclasse.
  • Utilisez leconcurrent.futures.processpoolExecutorclasse.

Examinons de plus près chacun à son tour.

Utilisez tous les processeurs avec la classe de processus

Nous pouvons exécuter une fonction cible dans un nouveau processus en utilisant lemultiprocessem*nt.classe.

Ceci peut être réalisé en créant une instance dumultiprocessem*nt.classe et spécifiant le nom de la fonction à exécuter via le «cible" argument.

Par exemple:

1

2

3

...

# Créer et configurer un nouveau processus

processus = multiprocessem*nt.Processus(cible=tâche)

Nous pouvons alors appeler lecommencer()méthode afin de démarrer le processus et d’exécuter la tâche.

1

2

3

...

# Démarrez le nouveau processus

processus.commencer()

Nous pouvons attendre que le nouveau processus se termine en appelant lerejoindre()méthode.

Par exemple:

1

2

3

...

# Attendez que le processus se termine

processus.rejoindre()

Nous pouvons créer un processus par tâche que nous voulons accomplir, comme un pour chaque noyau CPU de notre système.

Vous pouvez en savoir plus sur l'exécution des fonctions dans les processus enfants dans le tutoriel:

  • Multiprocessem*nt: le guide complet

Utiliser tous les processeurs avec la classe Pool

Nous pouvons démarrer un pool de processus de travail et émettre des tâches à la piscine à exécuter.

Cela peut être réalisé en utilisant lemultiprocessem*nt.poolclasse.

L'utilisation d'un pool de travailleurs peut être préférée à la création de processus manuellement comme dans l'exemple précédent car chaque processus de travailleur peut être réutilisé pour plusieurs tâches.Nous pouvons effectuer autant de tâches que nous le devons à la piscine et ils seront achevés aussi vite que les travailleurs.

Nous pouvons configurer le pool avec un processus de travailleur par noyau CPU dans notre système.

Par exemple:

1

2

3

...

# Créer un pool de processus

piscine = multiprocessem*nt.Piscine(8)

Nous pouvons émettre des tâches uniques à la piscine via leappliquer_async ()Méthode qui prend le nom de la fonction cible et de tout argument.Cette méthode renvoie un asyncresult qui fournit une poignée sur la tâche asynchrone.

Par exemple:

1

2

3

...

# Exécutez une tâche unique dans le pool

async_result = piscine.appliquer_async(tâche)

Nous pouvons appliquer une fonction cible à chaque élément dans un itérable en tant que tâche distincte dans le pool de processus en utilisant lecarte()Méthode sur lePiscineclasse.

Par exemple:

1

2

3

...

# publier une tâche par élément dans l'itérable

piscine.carte(tâche, articles)

Vous pouvez en savoir plus sur l'utilisation dumultiprocessem*nt.poolclasse dans le guide:

  • Pool multiprocesseur: le guide complet

Utilisez tous les CPU avec la classe ProcessPoolExecutor

Nous pouvons utiliser un pool de processus moderne qui utilise le cadre de l'exécuteur.

Le cadre de l'exécuteur est un modèle des autres langages de programmation, tels que Java, et fournit un moyen cohérent d'utiliser un pool de travailleurs à travers les fils et les processus.

Nous pouvons utiliser un pool de processus basé sur un exécuteur via leconcurrent.futures.processpoolExecutorclasse

LeProcessPoolExecutorLa classe est plus simple que lePiscineclasse et peut-être plus facile à utiliser.

Une instance duProcessPoolExecutorLa classe peut être créée et configurée avec un travailleur par noyau CPU dans le système.

Par exemple:

1

2

3

...

# créer le pool de travailleurs

exe = ProcessPoolExecutor(8)

Nous pouvons ensuite émettre des tâches uniques via lesoumettre()Méthode qui renvoie un objet futur, fournissant une poignée sur la tâche asynchrone.

Par exemple:

1

2

3

...

# émettre une tâche ponctuelle

avenir = exe.soumettre(tâche)

Nous pouvons également appeler notre fonction cible pour chaque élément dans un itérable, émis comme tâches dans la piscine via lecarte()méthode.

Par exemple:

1

2

3

...

# publier une tâche par élément dans l'itérable

exe.carte(tâche, articles)

Vous pouvez en savoir plus sur la façon d'utiliser leProcessPoolExecutorDans le guide:

  • ProcessPoolExecutor: le guide complet

Maintenant que nous savons comment utiliser pleinement les CPU dans notre système, examinons certains exemples travaillés.

Confusé par l'API du module multiprocesseur?
Téléchargez mon gratuitAide-mémoire PDF

Exemple de tâche lente en utilisant un noyau de processeur

Avant de chercher à utiliser pleinement les processeurs dans notre système, développons un exemple qui n'utilisera qu'un seul noyau de processeur.

L'exemple ci-dessous définit une fonction tâche () qui effectue une tâche à forte intensité de processeur.

Cette tâche est ensuite appelée de notre programme 50 000 fois.

Un seul noyau CPU est utilisé et le programme est lent.

L'exemple complet est répertorié ci-dessous.

1

2

3

4

5

6

7

8

9

dix

11

12

13

14

15

16

# Superfastpython.com

# Exemple d'un programme qui n'utilise pas tous les cœurs CPU

importermathématiques

# définir une tâche à forte intensité de processeur

deftâche(arg):

retour somme([mathématiques.sqrt(je) pour je dans gamme(1, arg)]])

# Protégez le point d'entrée

si __nom__ == '__principal__':

# Signaler un message

imprimer('Tâche de départ ...')

# Effectuer des calculs

résultats = [tâche(je) pour je dans gamme(1,50000)]]

# Signaler un message

imprimer('Fait.')

L'exécution de l'exemple rapporte un message, puis effectue la tâche à forte intensité de calcul 50 000 fois.

Chaque tâche est effectuée par un et un seul cœur CPU.

En tant que tel, le programme est lent à exécuter.

Sur mon système, il faut environ 115,3 secondes, soit près de 2 minutes.

1

2

Tâche de départ ...

Fait.

Comment savons-nous qu'il a utilisé un seul noyau de processeur?

Tout d'abord, nous pouvons enregistrer lecommande supérieure(Disponible sur les systèmes POSIX)

Nous pouvons voir qu'un seul processus Python est en cours d'exécution et qu'il occupe 99% d'un noyau de processeur.

How to Use 100% of All CPU Cores in Python (1)

Nous pouvons également voir que l'utilisation globale du processeur sur mon système n'est que de 14%.

How to Use 100% of All CPU Cores in Python (2)

Nous pouvons également vérifier lemoniteur d'activitéSur mon système, disponible sur macOS.

Il montre à peu près la même chose, avec un seul processus Python occupant 99% d'un noyau de processeur

How to Use 100% of All CPU Cores in Python (3)

Il montre également que l'utilisation globale du processeur sur le système est faible.

Vous pouvez effectuer des vérifications similaires en utilisant la surveillance d'utilisation du CPU spécifique à votre système.

How to Use 100% of All CPU Cores in Python (4)

Ensuite, examinons la mise à jour de l'exemple pour utiliser tous les processeurs via la classe ProcessPoolExecutor.

Cours de multiprocessem*nt Python gratuit

Téléchargez ma feuille de triche API multiprocesseur et en bonus, vous aurez un accès gratuit à mon cours de messagerie de 7 jours.

Découvrez comment utiliser le module de multiprocessem*nt Python, y compris comment créer et démarrer des processus enfants et comment utiliser des serrures et des sémaphores mutex.

Apprendre encore plus

Exemple d'utilisation de tous les processeurs avec le processPoolExecutor

Nous pouvons mettre à jour l'exemple lent précédent pour utiliser tous les cœurs de processeur dans le système via leProcessPoolExecutor.

Cela nécessite d'abord de créer une instance duProcessPoolExecutorclasse et la configurer avec un travailleur par noyau CPU.

J'ai 8 cœurs dans mon système, donc je vais le configurer pour avoir 8 travailleurs.Adaptez l'exemple de votre système en conséquence.

Nous pouvons alors appeler letâche()fonction pour chaque élément de la gamme via lecarte()Méthode sur leProcessPoolExecutor.

Afin d'assurer leProcessPoolExecutorest fermé une fois que nous en avons terminé, nous pouvons utiliser l'objet via l'interface de contexte.

Par exemple:

1

2

3

4

5

...

# Créez le pool de processus

avecProcessPoolExecutor(8) comme exe:

# Effectuer des calculs

résultats = exe.carte(tâche, gamme(1,50000))

En liant cela ensemble, l'exemple complet de l'exécution de la tâche à l'aide de tous les cœurs CPU est répertorié ci-dessous.

1

2

3

4

5

6

7

8

9

dix

11

12

13

14

15

16

17

18

19

# Superfastpython.com

# Exemple d'un programme qui utilise tous les cœurs CPU

importermathématiques

depuisconcurrent.avenirimporterProcessPoolExecutor

# définir une tâche à forte intensité de processeur

deftâche(arg):

retour somme([mathématiques.sqrt(je) pour je dans gamme(1, arg)]])

# Protégez le point d'entrée

si __nom__ == '__principal__':

# Signaler un message

imprimer('Tâche de départ ...')

# Créez le pool de processus

avecProcessPoolExecutor(8) comme exe:

# Effectuer des calculs

résultats = exe.carte(tâche, gamme(1,50000))

# Signaler un message

imprimer('Fait.')

L'exécution de l'exemple rapporte un message.

Il crée ensuite le processPoolExecutor avec 8 travailleurs, puis émet les 50 000 tâches.

Les 8 travailleurs terminent ensuite les tâches aussi vite qu'ils le peuvent.

Enfin, toutes les tâches sont effectuées et un message est signalé.

Dans ce cas, l'exemple se termine en 40,3 secondes environ sur mon système. C'est environ 75 secondes plus rapide, soit une accélération d'environ 2,86 fois.

1

2

Tâche de départ ...

Fait.

Comment savons-nous qu'il a utilisé tous les cœurs de processeur?

Tout d'abord, nous pouvons vérifier la commande supérieure (disponible sur les systèmes POSIX)

Nous pouvons voir que 8 processus Python fonctionnent et chacun occupe environ 90% d'un noyau de processeur donné.Nous pouvons voir un 9e processus Python, qui est le processus exécutant toutes les tâches, qui ne fait pas beaucoup de travail lui-même.

How to Use 100% of All CPU Cores in Python (5)

Nous pouvons également voir que l'utilisation globale du processeur sur mon système est de près de 100%.

How to Use 100% of All CPU Cores in Python (6)

Nous pouvons également vérifier le moniteur d'activité de mon système, disponible sur macOS.

Il montre à peu près la même chose, avec 8 processus Python de travailleur occupant 90% des 8 cœurs de CPU.

How to Use 100% of All CPU Cores in Python (7)

Il montre également que l'utilisation globale du processeur sur le système est proche de 96%.

How to Use 100% of All CPU Cores in Python (8)

Vous pouvez effectuer des vérifications similaires en utilisant la surveillance d'utilisation du CPU spécifique à votre système.

Cela met en évidence la façon dont nous pouvons mettre à jour nos programmes Python pour utiliser tous les cœurs CPU et réaliser près de 100% d'utilisation de chaque noyau.

Submergé par les API de concurrence Python?
Trouver un soulagement, téléchargez mon gratuitCartes mentales de concurrence python

Exemple d'utilisation de tous les processeurs avec la piscine

Nous pouvons également mettre à jour l'exemple lent pour utiliser le multiprocesseurPiscineclasse.

Cela semble presque identique à l'utilisation duProcessPoolExecutor.

Nous pouvons utiliser l'interface de contexte et émettre toutes les tâches du pool de travailleurs en utilisant lecarte()méthode.

L'exemple complet est répertorié ci-dessous.

1

2

3

4

5

6

7

8

9

dix

11

12

13

14

15

16

17

18

19

# Superfastpython.com

# Exemple d'un programme qui utilise tous les cœurs CPU

importermathématiques

depuismultiprocessem*ntimporterPiscine

# définir une tâche à forte intensité de processeur

deftâche(arg):

retour somme([mathématiques.sqrt(je) pour je dans gamme(1, arg)]])

# Protégez le point d'entrée

si __nom__ == '__principal__':

# Signaler un message

imprimer('Tâche de départ ...')

# créer le pool de processus

avecPiscine(8) comme piscine:

# Effectuer des calculs

résultats = piscine.carte(tâche, gamme(1,50000))

# Signaler un message

imprimer('Fait.')

L'exécution de l'exemple rapporte un message.

Il crée ensuite la piscine avec 8 travailleurs, puis publie les 50 000 tâches.

Les 8 travailleurs terminent ensuite les tâches aussi vite qu'ils le peuvent.

Enfin, toutes les tâches sont effectuées et un message est signalé.

Dans ce cas, l'exemple se termine en environ 36,4 secondes sur mon système.Cela représente environ 78,9 secondes plus rapide ou environ une accélération de 3,17 fois.

LePiscinepeut être plus rapide que leProcessPoolExecutorDans certains cas, car il peut créer moins d'objets en interne lorsque vous appelez lecarte()Méthode et à son tour, transmettez moins de données entre les processus de travail et le processus principal.

1

2

Tâche de départ ...

Fait.

LePiscineLa classe peut également être plus efficace.

Dans certaines expériences, il semblait mieux utiliser les noyaux du processeur, atteignant une utilisation de près de 98%.

How to Use 100% of All CPU Cores in Python (9)

Pourquoi ne pouvons-nous pas obtenir une utilisation complète à 100% du processeur?

Nous pouvons voir que nous pouvons obtenir près de 100% d'utilisation du processeur sur tous les noyaux à l'aide du module multiprocesseur.

Les années 90 sont cependant à 100% d'utilisation.

Pourquoi ne pouvons-nous pas obtenir une utilisation complète à 100% lors de l'utilisation de pools de processus?

Je soupçonne que cela est dû aux frais généraux nécessaires pour exécuter et gérer le programme.

Peut-être l'interprète lui-même, peut-être la transmission des données entre les processus, peut-être la création d'objets dans les pools de processus.

Néanmoins, en utilisant tous les noyaux, nous obtenons une augmentation de vitesse spectaculaire sur la tâche liée au CPU (par exemple 3x ou plus).

Plats à emporter

Vous savez maintenant comment mettre à jour les programmes Python pour utiliser tous les cœurs CPU sur votre système.

Avez-vous des questions?
Posez vos questions dans les commentaires ci-dessous et je ferai de mon mieux pour répondre.

photo parFans de Tesla SuissesurDésactiver

Tutoriels connexes:

Comment utiliser 100% de tous les cœurs de processeur dans Python (2024)
Top Articles
Latest Posts
Article information

Author: Domingo Moore

Last Updated:

Views: 6276

Rating: 4.2 / 5 (53 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Domingo Moore

Birthday: 1997-05-20

Address: 6485 Kohler Route, Antonioton, VT 77375-0299

Phone: +3213869077934

Job: Sales Analyst

Hobby: Kayaking, Roller skating, Cabaret, Rugby, Homebrewing, Creative writing, amateur radio

Introduction: My name is Domingo Moore, I am a attractive, gorgeous, funny, jolly, spotless, nice, fantastic person who loves writing and wants to share my knowledge and understanding with you.