Je compte utiliser l'utilisation de centaines de centaines de threads pour mettre en œuvre des tâches qui gèrent les périphériques sur un réseau. p>
Ceci est une application C ++ en cours d'exécution sur un processeur PowerPC avec un noyau Linux. P>
Après une phase initiale lorsque chaque tâche est synchronisation pour copier des données de l'appareil dans la tâche, la tâche devient inactive et ne se réveille que lorsqu'elle reçoit une alarme ou doit modifier certaines données (configuration), qui est rare. après la phase de démarrage. Une fois que toutes les tâches atteignent la phase "inactive", je m'attends qu'à quelques-unes par seconde devraient se réveiller. P>
Donc, ma principale préoccupation est que si j'ai des centaines de threads auront un impact négatif sur le système une fois qu'ils deviennent inactifs? P>
merci. Amso p>
edit: strong> Mais alors, d'autres problèmes doivent être comptabilisés. Avoir des centaines de threads en attente augmentera probablement l'utilisation de la mémoire sur le noyau, en raison de la nécessité d'attendre des files d'attente ou d'autres ressources similaires. Il y a aussi une question de latence qui a l'air non déterministe. Pour vérifier la réactivité et l'utilisation de la mémoire de chaque solution, il faut le mesurer et comparer. P>
Enfin, toute l'idée de centaines de threads qui seront principalement au ralenti peut être modélisée comme une piscine de fil. Cela réduit un peu de linéarité de code, mais augmente considérablement l'évolutivité de la solution et avec des soins de proprier peut être facilement adaptable pour régler le compromis entre la performance et l'utilisation des ressources. P>
Je pense que c'est tout. Merci à tout le monde pour leur entrée. P>
-
Je mettez à jour la question basée sur les réponses que j'ai eues. Merci les gars.
Donc, il semble que d'avoir une tonne de threads au ralenti (io bloqué, attente, dormir, etc.), en soi em>, n'aura pas d'impact sur le système en termes de réactivité.
Bien sûr, ils dépenseront de l'argent supplémentaire pour chaque pile et données TLS du fil, mais ça va aussi longtemps que nous jetons plus de mémoire à la chose (ce qui en fait plus d'€€€) P>
Amso p>
6 Réponses :
Chaque fil a surcharge - plus important encore, chacun a sa propre pile et TLS. La performance n'est pas une grande difficulté car elles n'obtiendront aucune tranche de temps à moins de faire quoi que ce soit. Vous voudrez peut-être toujours envisager d'utiliser des piscines de fil. P>
Si des threads "inactifs" utiliseront des tranches de temps dépend de la manière dont leur code est écrit. Par exemple, j'ai vu beaucoup de code «inactif» qui, à tous plusieurs, MS vérifie si cela doit faire quoi que ce soit.
Ouch :) Oui, par "inactif", je voulais dire un fil dans un état d'attente, pas "ce que le programmeur pense inactif signifie".
Par "inactif", je veux dire que le fil bloquera sur un sémaphore ou une condition d'attente jusqu'à ce qu'il y ait une activité extérieure qui a besoin de son intervention. Par exemple: un paquet Times Out, a reçu un paquet, a changé certaines données et besoin de synchroniser ...
@amso - Exactement, c'est la bonne façon d'attendre, et cela ne volera pas de tranches de temps. Néanmoins, j'essaierais de ne pas créer trop de threads si c'est une option. Les piscines de fil pourraient être la voie à suivre.
Je ne suis pas un pirate linux, mais en supposant que la planification du fil de Linux est similaire à celle de Windows '... P>
Oui, bien sûr, le sera Cependant, dans un environnement en tranches de temps, les threads qui sont dans une attente / sommeil / l'état de jointure ne consomme pas de cycles de processeur jusqu'à ce qu'ils soient réveillés. P>
Je crois que dans les versions récentes, les threads Linux sont très légers. Voir EN.Wikipedia.org/wiki/native_posix_Thread_Library et esp. le papier de conception qui est référencé là-bas.
@Steve J'ai lu sur de nombreux sites Web (et je pense également à comprendre le noyau Linux, bien que je puisse me tromper sur celui-ci) que Pthreads sont mis en œuvre comme des processus sur UNIX, il est donc plutôt assez lourd. En fait, votre lien dit que aussi maintenant que je le regarde.
Je serais inquiet de proposer des mappages 1: 1 des connexions de fil, si rien d'autre parce que cela vous laisse plutôt exposé au déni des attaques de service. ( Ebomike a déjà répondu à la question directement - à condition que les threads sont bloqués et non occupés à attendre, ils ne consomment pas beaucoup dans la voie des ressources, bien qu'ils occupent la mémoire et l'échange pour tout l'état de thread. P > pthread_create () code> est une opération assez coûteuse par rapport à un appel à
accepter () code>) p>
Merci pour le conseil. DOS n'est pas un risque car les threads ne sont pas créés / détruits en fonction de connexions entrantes. Au lieu de cela, ils sont créés lors de la configuration de l'application (lors de son exécution) pour gérer un nouveau périphérique et détruits lorsqu'un périphérique est supprimé.
Pourriez-vous examiner ma réponse et laissez-moi savoir vos pensées? Je pense qu'il peut y avoir un impact, en fonction de l'acceptabilité de la latence dans le réveil d'un fil.
principalement, ils utiliseront l'espace d'adresses et la mémoire pour les piles; Une fois que vous avez obtenu, disons, 1000 threads, cela devient assez significatif que j'ai vu que 10 m par thread est typique des piles (sur x86_64). Il est changeable, mais seulement avec soin. P>
Si vous avez un processeur de 32 bits, l'espace d'adressage sera la principale limitation une fois que vous avez touché 1 000 de threads, vous pouvez facilement épuiser la mesure. P>
Ils utilisent de la mémoire du noyau, mais probablement pas autant que l'espace utilisateur. P>
EDIT: Bien sûr, les threads partagent l'espace d'adresses les uns avec les autres si elles sont dans le même processus; Je suppose qu'ils sont. P>
La bibliothèque Pthread a un minimum de 32 mégaoctets par fil recommandé
Citation s'il vous plaît; La plupart des systèmes que j'ai vus semblent par défaut à environ 1 m à 8 m; Je ne vois pas où un minimum de 32 Mo par fil est recommandé.
J'apprends les bases du noyau maintenant. Je ne peux pas encore vous donner une réponse spécifique; Je suis toujours un noob ... mais voici quelques choses pour vous de mâcher. P>
Linux implémente chaque thread de POSIX en tant que processus unique. Cela créera des frais généraux comme d'autres ont mentionné. En plus de cela, votre modèle d'attente semble imparfait de toutes les manières que vous le faites. Si vous créez une variable conditionnelle pour chaque thread, je pense (basé sur mon interprétation du site Web ci-dessous) que vous accumulerez beaucoup de mémoire de noyau, car chaque thread serait placé dans sa propre file d'attente. Si vous avez la possibilité de casser vos discussions pour chaque groupe de threads X pour partager une variable conditionnelle, vous avez également des problèmes, car chaque fois que les signaux variables, vous devez réveiller _Every_darn_process_ dans la file d'attente de cette variable. P>
Je suppose également que vous devrez faire un objet partager une synchronisation. Dans ce cas, votre code peut devenir plus lent à cause de la nécessité de réveiller tous les processus en attente d'une ressource, comme je l'ai mentionné précédemment. P>
Je sais que ce n'était pas beaucoup d'aide, mais comme je l'ai dit, je suis un noyau noob. J'espère que cela a aidé un peu. P>
Ma compréhension de la mise en œuvre de la NPTL est que "chaque thread est un processus" n'est pas une moitié aussi mauvaise que cela sonne initialement, car le clone appelle que cette carte est plutôt optimisée. Les repères semblent être d'accord avec cela ( Kerneltrap.org/node/429 ). En ce qui concerne une variable conditionnelle par thread va si elle était vraiment nécessaire et s'est révélée être un problème, vous pouvez contourner cela par «hachage» (c'est-à-dire le partage) 1 Cond Var à 20 threads ou. J'avais supposé que ce serait io bloquant les threads et non les primitives de synchronisation que je pense est également moins chère.
Le blocage du fil doit être effectué à l'aide de la synchronisation. Un sémaphore serait-il une solution plus légère? Le réveil et le blocage des fils peuvent être facilement modélisés comme un modèle de producteur-consommateur.
Mesurez-le et voyez. Je pense que la plupart des primitives de synchronisation Pthread sur Linux sont implémentées avec Futex (2) ces jours-ci, donc il n'y a probablement pas beaucoup de différence entre eux. S'ils ne sont pas implémentés à l'aide de Futex, vous pouvez voir des gains de performance de l'utiliser vous-même bien que je suggère fortement de mesurer.
@asmo Si mon interprétation de l'article que j'ai publié est correcte, je ne pense pas qu'un sémaphore serait plus léger d'une solution. Comme le dit Awoodland, essayez-le :). Ce n'est peut-être pas un problème dans votre cas, malgré les lacunes inhérentes du modèle de thread / thread / processus de Linux.
@awoodland, il semble qu'un futex a sa propre attente quand même, je ne suis donc pas sûr que le problème soit évité. Si chaque processus doit passer à l'état exécuté afin de voir s'il est prêt à exécuter, vous réveillez une tonne de fils chaque fois que vous déverrouillez le FUTEX / SEMAPHORE dans le cas d'une table de hachage.
@awoodland, mais encore une fois, sauf si vous êtes dans une application en temps réel., je ne pense pas que vous vous réveillez 100 (jusqu'à 100 threads par fuite, et 10 Fuex) Les threads seraient aussi importants.
Je ne suis pas sûr de ce que "périphérique" dont vous parlez, mais s'il s'agit d'un descripteur de fichier, je vous suggère de regarder commencer à migrer à l'aide de sondage ou d'Epoll (ID suggère ce dernier compte de la description de la description de Dans quelle mesure vous attendez-vous à chaque descripteur de fichier). De cette façon, vous pouvez utiliser un processus qui serait responsable de tous les FDS. P>
Merci. Je pense que vous avez mal compris la question. Je ne sondre pas d'événements d'un descripteur de fichier ni de rien de quelque sorte. La question concerne la mise en œuvre de plusieurs tâches pour le contrôle de potentiellement des centaines de périphériques ou d'entités, ou tout ce qui nécessite un algorithme d'état.
Si vous avez besoin de centaines de threads, vous regardez le problème dans le mauvais sens.
ROGER: Je suis en désaccord, les 100 fils peuvent être corrects, en fonction du problème. L'utilisation de threads signifie que le code peut être une belle linéaire, ce qui rend certaines tâches beaucoup plus facilement.
Je ne suis pas d'accord avec le désaccord. Si vous avez déjà examiné la sortie
ps Amx code> sur Linux, vous remarquerez des programmes (comme ...
console-kit-daemon code>) qui empêche environ 63 fils de démon (dont lequel 57 sont généralement inutiles et ne font rien).