CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

Le fetch-and-add ...

Lagrangien
Lagrangien
Niveau 8
26 janvier 2014 à 22:14:27

Salut, en étudiant les primitives de synchronisation, il apparaît que presque toutes les primitives protégeant des sections critiques sont, en fait, elles-mêmes, des sections critiques, qui forcent alors au niveau du hardware les différents threads à patienter les uns après les autres. Jusque là, j'ai bien compris?

Cependant, mon prof dit qu'il existe une primitive qui est "réellement parallèle" : le fetch-and-add.
Or, celle-ci contient, comme les autres primitives, une ou des opérations atomiques, du coup je comprend pas où est la différence fondamentale avec d'autres primitives telles que par exemple le test-and-set.

Merci de m'éclairer : )

Lagrangien
Lagrangien
Niveau 8
26 janvier 2014 à 22:26:56

"forcent alors au niveau du hardware les différents threads à patienter les uns après les autres" ==> je veux dire par là que l'atomicité requise dans la primitive est réalisée au niveau du harware en sérialisant les appels des différents processeurs.

godrik
godrik
Niveau 30
27 janvier 2014 à 01:27:01

(Interessant, je parles de ca a mes etudiants en classe en ce moment)

Il y a plusieurs facon de synchoniser deux threads (logique). Les methodes de synchronisation du systeme d'exploitation (typiquement les mutex, semaphores et compagnie) sont des methodes de synchronization qui repose sur une semantique propre au systeme. Tu prends un mutex, pour faire ca, tu fais un appel de fonction qui te fait tomber en espace noyau. De la le noyau assure que la semantique du mutex est respecte. C'est a dire que si un autre thread a ce mutex, alors le premier thread doit attendre, c'est a dire qu'il est deschedule par le systeme jusqu'a ce que le mutex soit libre. La synchronisation se fait au niveau du systeme et typiquement coute cher: probablement au moins un contexte switch (* voir futex plus bas). En plus en fonction du comportement et du scheduling des autres threads, il peut se retrouver a attendre plus longtemps.

La primitive fetch_and_add dont tu parles fait partie des operations atomique du processeur comme les test_and_set et compare_and_swap et les autres trucs du genre (ca depend des processeurs). Basiquement c'est operations ne sont pas des operations faites par le systeme, mais par ton processeur. Elles fonctions en lockant physiquement une ligne de cache de la memoire principale. Ainsi, le cout typique de cette operation est tres court, beaucoup plus court qu'un appel systeme. Aussi cette primitive n'est pas bloquante.

Ces primitives atomiques peuvent avoir de nombreuses utilite, la plus courante etant l'implementation de spinlock qui essentiellement sont une primitive de synchronisation comme un mutex, sauf qu'elle est deploye en espace utilisateur entierement. Ca permet d'avoir une synchronisation potentiellement beaucoup plus rapide, mais ca conserve un thread (logique) active ce qui consomme les ressources d'un thread (physique) a temps plein. Les systeme implementes maintenant des mutex hybride, appelle futex sous linux (et j'en sais rien dans les autres systemes) qui sont un genre d'hybride des spinlock et des mutex, basiquement, tu fais du spinlock pendant 50ms et apres tu switch sur un mutex.

Mais l'interet principal de ces operations atomiques n'est pas dans la reimplementation d'un verrou parcequ'il est toujours succeptible a des problemes d'attente sur un verrou. Imagine que tu ais un code comme celui ci: "mutexlock(); i++; mutexunlock();" tu pourrais avoir envie de dire que comme ce que le code protege par le mutex est tres court et que donc, on s'en fout en terme de performance. Le probleme est que si ton thread (logique) est deschedule par le systeme alors qu'il tient le mutex, alors potentiellement TOUS les autres threads (logique) de ton systeme peuvent se retrouver a attendre jusqu'a ce que le thread (logique) qui tient le mutex soit schedule a nouveau.

Ici, tu peux faire la meme operation en utilisant un unique fetch_and_add sur la variable i. Comme c'est une operation user space, le temps d'attente est naturellement tres faible (le cout reel d'u atomique est complique a calculer parcequ'il depend de la saturation du bus memoire et du bus reliant les different cache et servant a leur synchronisation.) Et ainsi cette operation ne provoquera jamais une attente considerable des autres threads (logique).

Ces operations peuvent etre utilise pour implementer de nombreuse structures de donne parallel ou structure de synchronisation qui arrive a garantir que aucun verrou n'est jamais pris. Si tu veux en savoir plus. Regardes les concepts de lock-free et wait-free data structures. Si tu cherches des articles en particulier, il y en a de nombreux publie dans la conference IPDPS.

Si tu as d'autres questions ou veut plus d'explication n'hesites pas a demander.

Lagrangien
Lagrangien
Niveau 8
27 janvier 2014 à 11:05:45

Merci beaucoup pour ta réponse !

Mais est-ce que le fait de considérer un fetch-and-add comme non-bloquant est une approximation venant de la rapidité avec laquelle l'operation atomique est exécutée ? Parce que (et c'est peut-être là que j'ai un problème) je conçois pas comment une opération atomique peut ne pas être bloquante, puisqu'un seul processeur à la fois peut l'exécuter. Du coup je conçois pas comment on peut dire qu'un fetch-and-add n'est pas bloquant.

godrik
godrik
Niveau 30
27 janvier 2014 à 21:18:14

Toutes les operations memoires sont blocantes au niveau du processeur :) Quand tu ecris en memoire, c'est une operation potentiellement blocante. Si le buffer d'ecriture est plein alors tu ne peux pas executer ton store, il faut attendre.

Ce n'est pas blocant dans le sens ou le thread n'a pas besoin d'etre descheduler par le systeme et n'execute pas une boucle d'attente active.

Lagrangien
Lagrangien
Niveau 8
28 janvier 2014 à 09:34:52

Ok merci, j'ai compris cette fois : )

Sous forums
  • Aide à l'achat Mac
  • Steam Deck
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Macintosh
  • Hardware
La vidéo du moment