basé sur ce Question J'ai supposé que la création Nouveau processus Strong> devrait être tests: p> donc, les processus sont presque upd 1. strong> pour le rendre plus clair. Je comprends que ce morceau de code n'introduit pas de concurrence. L'objectif ici est de tester le temps nécessaire pour créer un processus et un fil. Pour utiliser la concurrence réelle avec Python, on peut utiliser quelque chose comme ceci: p> qui fonctionne vraiment beaucoup plus vite que la version filetée. p>
OS.FORK () code>: p>
$ time python test_fork.py
real 0m3.919s
user 0m0.040s
sys 0m0.208s
$ time python test_multiprocessing.py
real 0m1.088s
user 0m0.128s
sys 0m0.292s
$ time python test_threadings.py
real 0m0.134s
user 0m0.112s
sys 0m0.048s
3 Réponses :
Oui, c'est vrai. Démarrer un nouveau processus (appelé processus lourd) est coûteux. p>
Un aperçu ... P>
Le système d'exploitation doit (dans l'affaire Linux) Fourche le premier processus, configurez la comptabilisation du nouveau processus, configurez la nouvelle pile, effectuez le commutateur de contexte, copiez une mémoire qui est modifiée et déchire tout cela. lorsque le nouveau processus revient. P>
Le fil alloue simplement une nouvelle structure de pile et de thread, le contexte change-t-il et retourne lorsque le travail est terminé. P>
... c'est pourquoi nous utilisons des threads. P>
Vous l'avez en arrière. Un processus n'est qu'un processus. Un thread est un processus léger :) Je suppose que vous pouvez appeler un processus un fil lourd, mais je ne pense pas que personne ne le fait. Qu'est-ce qu'un processus de poids lourd?
@ Shatang soupir. Si vous ne savez pas si vous ne savez pas, alors au moins, vous pourriez le faire Google. Essayez Googling "Processus de poids lourd" et voir si Quelqu'un fait cela i>.
Dans mon expérience, il existe une différence significative entre la création d'un thread (avec Par exemple, j'ai créé un test C similaire à votre test de python avec le code de thread ceci: p> et processus de force de traitement comme ceci: p> sur mon système, le code de recherche a pris environ 8 fois plus Longue à exécuter. P> Cependant, il convient de noter que la mise en œuvre de Python est encore plus lente - pour moi, c'était environ 16 fois plus lent. Je soupçonne que c'est parce que, en plus des frais généraux réguliers de la création d'un nouveau processus, il existe également plus de surcharge de python associée au nouveau processus. P> p> pthread_create code>) et le destination d'un processus.
La question que vous avez liée à la comparaison du coût de l'appelant Si, comme vous dites ... P> Le but ici est de tester le temps nécessaire pour créer un processus et un fil. P>
BlockQuote> ... alors vous ne devriez pas attendre qu'ils se terminent. Vous devriez utiliser des programmes de test plus comme ceux-ci ... p> thread.py strong> p> ... qui donnent les résultats suivants ... p> ... donc il y a donc Pas beaucoup de différence dans le temps de création des fils et des processus. P> p> Fork (2) code> vs. code> pthread_create (3) code>, alors que votre code fait un peu plus, par exemple Utilisation de
Joindre () Code> Pour attendre que les processus / threads se terminent.
Mais votre Fork.py code> ne peut-il pas créer de nouveaux threads et sortie, sans attendre les processus d'enfants à compléter?
En outre, vous lancez le prochain thread / processus sans attendre la fin de la fin de la fin, ils fonctionnent donc simultanément, alors qu'il semble être plus correct de les démarrer séquentiellement pour éviter toute gil et toutes ces choses.
@ffriend Eh bien, votre question a dit (l'accent est mis sur le mien) "J'ai supposé que Création de nouveau processus doit être presque aussi rapide que de créer un nouveau thread de Linux", et c'est. L'ensemble du point d'utilisation des threads est pour la concurrence, alors quel serait le point de faire fonctionner séquentiellement? Qu'est-ce que vous essayez exactement d'atteindre ici?
J'essaie de comparer les frais généraux pour avoir exécuté un nouveau fil et un nouveau processus. J'ai souligné la création pour séparer le thread / processus à partir d'autres détails tels que Gil, appels de fonction, etc. Mais bien sûr, le joindre en arrière compte également. Exécution de nombreux threads / processus séquentiellement est juste une autre façon de trouver du temps moyen. Voir ma première mise à jour pour plus de détails.
@ffriend bien, si vous incluez l'heure de la déchirure, les processus prennent un peu plus long que les fils, mais les frais généraux sont toujours dans la gamme de millisecondes, de toute façon. Cependant, dans la pratique, si la quantité de temps nécessaire à la configuration et à démolir un processus / thread est supérieure à la quantité de temps que le processus / thread fonctionne pour, il n'y a pas beaucoup de point dans les utiliser. Sinon, les frais généraux ne sont pas pertinents et le choix entre les deux devraient être basés sur ceux qui sont plus appropriés pour l'objectif réel que vous essayez d'accomplir.
@ffriend également, étant donné que la question liée ne fait que mesurer l'heure de configuration et ignorer le temps de démolition, alors cela expliquerait la différence entre vos résultats et les résultats des exemples de cette réponse. Je pensais que votre question était d'expliquer cette divergence, ce que je pensais avoir eu. Donc, si ce n'est votre question, alors quoi?
Tout comme exemple, envisagez l'application ou le cadre qui crée de nombreux threads / processus tout le temps, quelque chose de similaire à ce que fait Erlang. Si les processus étaient vraiment légers, vous pouvez les utiliser au lieu de threads. Mais si vous obtenez (relativement) de grandes frais générales, il serait préférable de mettre plus d'efforts sur les threads à la place. Bien sûr, il existe des moyens de surmonter tous les problèmes, mais c'est pire de connaître ces détails à l'avance. En outre, n'oubliez pas Gil qui est tout à propos des threads vs. Processus. Quoi qu'il en soit, les réponses et les commentaires clarifiés, alors j'accepte votre réponse comme le plus détaillé. Merci.
@ffriend je vois. Eh bien, la création de threads et de sous-processus a une surcharge assez importante, donc dans la pratique, j'essaierais probablement d'éviter de créer une "application ou un cadre qui crée beaucoup de threads / processus tout le temps" et d'utiliser une piscine modèle à la place. Le gil est un peu douloureux avec python, mais vous pouvez l'éviter à l'aide de sous-processus avec IPC ou à l'aide de threads qui appelle une bibliothèque C (par exemple avec CTYPES CODE>) pour faire la majeure partie du travail.
Eh bien, la question que vous avez liée à comparer le coût de l'appelant
Fork (2) code> vs. code> pthread_create (3) code>, alors que votre code fait un peu plus. Que diriez-vous de comparer
OS.FORK () code> avec
thread.start_new_thread () code>?
@Aya: Je n'ai pas pu trouver de type
rejoindre code> dans
thread code> Module pour créer un test similaire, mais même par rapport à une version de filetage code> de haut niveau code> avec
OS.FORK () code> est toujours beaucoup plus lent. En fait, c'est le plus lent (bien que des conditions supplémentaires puissent affecter les performances). Voir ma mise à jour.
Vous devez utiliser un mutex pour attendre le fil si vous utilisez le module de thread code> à bas niveau code>, qui correspond à la manière dont le niveau de threading
de niveau supérieur code> est implémente
rejoindre () code>. Mais, si vous essayez simplement de mesurer le temps nécessaire pour créer le nouveau processus / thread, vous ne devriez pas appeler
joindre () code>. Voir aussi ma réponse ci-dessous.