Quelle est la différence entre un fil et une fibre?


187

Quelle est la différence entre un fil et une fibre? J'ai entendu parler des fibres de rubis et j'ai lu entendu dire qu'elles sont disponibles dans d'autres langues, quelqu'un pourrait-il m'expliquer en termes simples quelle est la différence entre un fil et une fibre.

Réponses:


163

Dans les termes les plus simples, les fils sont généralement considérés comme préemptifs (bien que cela ne soit pas toujours vrai, selon le système d'exploitation) tandis que les fibres sont considérées comme des fils coopératifs légers. Les deux sont des chemins d'exécution distincts pour votre application.

Avec les threads: le chemin d'exécution actuel peut être interrompu ou préempté à tout moment (note: cette instruction est une généralisation et peut ne pas toujours être vraie selon le système d'exploitation / le package de threads / etc.). Cela signifie que pour les threads, l'intégrité des données est un gros problème car un thread peut être arrêté au milieu de la mise à jour d'un morceau de données, laissant l'intégrité des données dans un état incorrect ou incomplet. Cela signifie également que le système d'exploitation peut tirer parti de plusieurs processeurs et cœurs de processeur en exécutant plus d'un thread en même temps et en laissant au développeur le soin de protéger l'accès aux données.

Avec les fibres: le chemin d'exécution courant n'est interrompu que lorsque la fibre cède l'exécution (même remarque que ci-dessus). Cela signifie que les fibres démarrent et s'arrêtent toujours à des endroits bien définis, de sorte que l'intégrité des données est beaucoup moins problématique. De plus, comme les fibres sont souvent gérées dans l'espace utilisateur, il n'est pas nécessaire d'effectuer des changements de contexte coûteux et des changements d'état du processeur, ce qui rend le passage d'une fibre à l'autre extrêmement efficace. D'un autre côté, étant donné qu'aucune fibre ne peut fonctionner exactement en même temps, la seule utilisation de fibres ne permet pas de tirer parti de plusieurs processeurs ou de plusieurs cœurs de processeur.


7
Existe-t-il un moyen d'utiliser plusieurs threads pour exécuter des fibres en parallèle?
Baradé

2
@Jason, lorsque vous indiquez ~ "avec des fibres, le chemin d'exécution actuel n'est interrompu que lorsque la fibre donne l'exécution" et "les fibres démarrent et s'arrêtent toujours à des endroits bien définis, donc l'intégrité des données est beaucoup moins problématique", voulez-vous dire que lors du partage de variables, nous n'avons pas besoin d'utiliser des «mécanismes de verrouillage» et des variables volatiles? Ou voulez-vous dire que nous devons encore faire ces choses?
Pacerier

@ Baradé C'est une question intéressante, as-tu trouvé une réponse?
Mayur

57

Les threads utilisent la planification préemptive , tandis que les fibres utilisent la planification coopérative .

Avec un thread, le flux de contrôle peut être interrompu à tout moment et un autre thread peut prendre le relais. Avec plusieurs processeurs, vous pouvez avoir plusieurs threads tous exécutés en même temps ( multithreading simultané ou SMT). En conséquence, vous devez faire très attention à l'accès simultané aux données et protéger vos données avec des mutex, des sémaphores, des variables de condition, etc. Il est souvent très difficile de bien faire.

Avec une fibre, le contrôle ne bascule que lorsque vous le lui demandez, généralement avec un appel de fonction nommé quelque chose comme yield(). Cela facilite l'accès simultané aux données, car vous n'avez pas à vous soucier de l'atomicité des structures de données ou des mutex. Tant que vous ne cédez pas, il n'y a aucun danger d'être préempté et d'avoir une autre fibre essayant de lire ou de modifier les données avec lesquelles vous travaillez. En conséquence, si votre fibre entre dans une boucle infinie, aucune autre fibre ne peut fonctionner, car vous ne cédez pas.

Vous pouvez également mélanger des fils et des fibres, ce qui pose les problèmes rencontrés par les deux. Non recommandé, mais cela peut parfois être la bonne chose à faire si cela est fait avec soin.


3
Je pense qu'une boucle infinie est juste un bogue qui doit être corrigé, et les threads n'ont qu'un avantage assez obscur lorsqu'il y a une boucle infinie. Le concept de non-buggy associé est lorsqu'il y a un processus de longue durée que l'utilisateur peut souhaiter annuler. Dans ce cas, que vous utilisiez des threads ou des fibres, le processus de longue durée doit être coopératif - le simple fait de tuer son thread peut laisser certaines de vos structures de données en désordre, donc un meilleur moyen est par exemple le thread de processus de longue durée vérifierait périodiquement s'il avait été interrompu. Ce n'est pas tellement différent d'une fibre cédant périodiquement.
Evgeni Sergeev

43

Dans Win32, une fibre est une sorte de thread géré par l'utilisateur. Une fibre a sa propre pile et son propre pointeur d'instruction etc., mais les fibres ne sont pas planifiées par le système d'exploitation: vous devez appeler SwitchToFiber explicitement. Les threads, en revanche, sont planifiés de manière préventive par le système d'exploitation. Donc, en gros, une fibre est un thread qui est géré au niveau de l'application / du runtime plutôt que d'être un véritable thread du système d'exploitation.

Les conséquences sont que les fibres sont moins chères et que l'application a plus de contrôle sur la planification. Cela peut être important si l'application crée de nombreuses tâches simultanées et / ou souhaite optimiser étroitement leur exécution. Par exemple, un serveur de base de données peut choisir d'utiliser des fibres plutôt que des threads.

(Il peut y avoir d'autres utilisations pour le même terme; comme indiqué, il s'agit de la définition Win32.)


37

Tout d'abord, je recommanderais de lire cette explication de la différence entre les processus et les threads comme documentation de base.

Une fois que vous avez lu que c'est assez simple. Les threads peuvent être implémentés soit dans le noyau, dans l'espace utilisateur, ou les deux peuvent être mélangés. Les fibres sont essentiellement des threads implémentés dans l'espace utilisateur.

  • Ce qu'on appelle généralement un thread est un thread d'exécution implémenté dans le noyau: ce qu'on appelle un thread du noyau. La planification d'un thread du noyau est gérée exclusivement par le noyau, bien qu'un thread du noyau puisse volontairement libérer le CPU en dormant s'il le souhaite. Un thread du noyau a l'avantage de pouvoir utiliser des E / S bloquantes et de laisser le noyau se soucier de la planification. Son principal inconvénient est que le changement de thread est relativement lent car il nécessite un piégeage dans le noyau.
  • Les fibres sont des threads de l'espace utilisateur dont la planification est gérée dans l'espace utilisateur par un ou plusieurs threads du noyau sous un seul processus. Cela rend la commutation de fibre très rapide. Si vous regroupez toutes les fibres accédant à un ensemble particulier de données partagées dans le contexte d'un seul thread de noyau et que leur planification est gérée par un seul thread de noyau, vous pouvez éliminer les problèmes de synchronisation car les fibres fonctionneront effectivement en série et vous avez terminé contrôle de leur programmation. Le regroupement des fibres apparentées sous un seul thread de noyau est important, car le thread de noyau dans lequel elles s'exécutent peut être préempté par le noyau. Ce point n'apparaît pas clairement dans la plupart des autres réponses. De plus, si vous utilisez des E / S bloquantes dans une fibre, le thread du noyau entier fait partie de blocs comprenant toutes les fibres qui font partie de ce thread du noyau.

Dans la section 11.4 «Processus et threads sous Windows Vista» dans les systèmes d'exploitation modernes, Tanenbaum commente:

Bien que les fibres soient planifiées de manière coopérative, s'il y a plusieurs fils planifiant les fibres, une synchronisation minutieuse est nécessaire pour s'assurer que les fibres n'interfèrent pas les unes avec les autres. Pour simplifier l'interaction entre les threads et les fibres, il est souvent utile de créer uniquement autant de threads qu'il y a de processeurs pour les exécuter, et d'affiniter les threads à chaque exécution uniquement sur un ensemble distinct de processeurs disponibles, voire sur un seul processeur. Chaque fil peut ensuite exécuter un sous-ensemble particulier de fibres, établissant une relation un à plusieurs entre les fils et les fibres, ce qui simplifie la synchronisation. Même ainsi, il existe encore de nombreuses difficultés avec les fibres. La plupart des bibliothèques Win32 ignorent complètement les fibres, et les applications qui tentent d'utiliser des fibres comme s'il s'agissait de threads rencontreront divers échecs. Le noyau n'a aucune connaissance des fibres, et lorsqu'une fibre entre dans le noyau, le thread sur lequel elle s'exécute peut se bloquer et le noyau planifiera un thread arbitraire sur le processeur, le rendant indisponible pour exécuter d'autres fibres. Pour ces raisons, les fibres sont rarement utilisées, sauf lors du portage de code provenant d'autres systèmes qui ont explicitement besoin de la fonctionnalité fournie par les fibres.


4
C'est la réponse la plus complète.
Bernard

12

Notez qu'en plus des threads et des fibres, Windows 7 introduit la planification en mode utilisateur :

La planification en mode utilisateur (UMS) est un mécanisme léger que les applications peuvent utiliser pour planifier leurs propres threads. Une application peut basculer entre les threads UMS en mode utilisateur sans impliquer le planificateur système et reprendre le contrôle du processeur si un thread UMS se bloque dans le noyau. Les threads UMS diffèrent des fibres en ce que chaque thread UMS a son propre contexte de thread au lieu de partager le contexte de thread d'un seul thread. La possibilité de basculer entre les threads en mode utilisateur rend UMS plus efficace que les pools de threads pour gérer un grand nombre d'éléments de travail de courte durée qui nécessitent peu d'appels système.

Plus d'informations sur les threads, les fibres et UMS sont disponibles en regardant Dave Probert: Inside Windows 7 - User Mode Scheduler (UMS) .


7

Les threads sont planifiés par le système d'exploitation (préemption). Un fil peut être arrêté ou repris à tout moment par l'OS, mais les fibres se gèrent plus ou moins d'elles-mêmes (coopératives) et se cèdent l'une à l'autre. Autrement dit, le programmeur contrôle quand les fibres effectuent leur traitement et quand ce traitement passe à une autre fibre.


7

Les threads dépendent généralement du noyau pour interrompre le thread afin qu'il ou un autre thread puisse fonctionner (ce qui est mieux connu sous le nom de multitâche préventif) tandis que les fibres utilisent le multitâche coopératif où c'est la fibre elle-même qui abandonne son temps de fonctionnement afin que d'autres fibres peuvent couler.

Quelques liens utiles expliquant mieux que je ne l'ai probablement fait sont:


7

Les threads ont été créés à l'origine comme des processus légers. De la même manière, les fibres sont un fil léger, reposant (de manière simpliste) sur les fibres elles-mêmes pour se programmer les unes les autres, en cédant le contrôle.

Je suppose que la prochaine étape sera des brins où vous devrez leur envoyer un signal chaque fois que vous voulez qu'ils exécutent une instruction (pas contrairement à mon fils de 5 ans :-). Dans l'ancien temps (et même maintenant sur certaines plates-formes embarquées), tous les threads étaient des fibres, il n'y avait pas de préemption et vous deviez écrire vos threads pour bien vous comporter.


3

La définition de la fibre Win32 est en fait la définition «Green Thread» établie chez Sun Microsystems. Il n'est pas nécessaire de gaspiller le terme fibre sur le thread d'un certain type, c'est-à-dire un thread s'exécutant dans l'espace utilisateur sous le contrôle du code utilisateur / de la bibliothèque de threads.

Pour clarifier l'argument, regardez les commentaires suivants:

  • Avec l'hyper-threading, le processeur multicœur peut accepter plusieurs threads et les distribuer un sur chaque cœur.
  • Le processeur en pipeline superscalaire accepte un thread pour l'exécution et utilise le parallélisme de niveau d'instruction (ILP) pour exécuter le thread plus rapidement. Nous pouvons supposer qu'un fil est cassé en fibres parallèles fonctionnant dans des pipelines parallèles.
  • Le processeur SMT peut accepter plusieurs threads et les fractionner en fibres d'instructions pour une exécution parallèle sur plusieurs pipelines, en utilisant des pipelines plus efficacement.

Nous devons supposer que les processus sont faits de fils et que les fils doivent être faits de fibres. Avec cette logique à l'esprit, l'utilisation de fibres pour d'autres types de fils est une erreur.


C'est intéressant.
JSON
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.