Qu'est-ce que PTHREAD MUTEX ADAPTATIVE NP

Où puis-je trouver de la documentation sur les Mutex pthread "adaptatifs"? Le symbole PTHREAD_MUTEX_ADAPTIVE_NP est défini sur mon système, mais le seulement la documentation je peux trouver en ligne ne dit rien sur ce qu'une adaptation mutex est, ou lorsqu'il est approprié d'utiliser.

... quel est-il, et quand dois-je utiliser?

Pour référence, ma version de la libc est:

GNU C Library (Ubuntu EGLIBC 2.15-0ubuntu10.5) stable release version 2.15, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.6.3.
Compiled on a Linux 3.2.50 system on 2013-09-30.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
<!-Et "uname-a" donne

Linux desktop 3.2.0-55-generic #85-Ubuntu SMP Wed Oct 2 12:29:27 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
25
demandé sur laslowh 2013-11-08 20:17:47

3 réponses

Ici vous allez. Comme je l'ai lu, c'est un mutex brutalement simple qui ne se soucie pas de quoi que ce soit sauf de faire le cas no-contention courir vite.

2
répondu jthill 2013-11-11 23:23:07

PTHREAD_MUTEX_ADAPTIVE_NP est quelque chose que j'ai inventé tout en travaillant dans le rôle d'un contributeur glibc sur le fait de rendre les LinuxThreads plus fiables et plus performants. LinuxThreads était le prédécesseur de glibc NPTL library, développée à l'origine comme une bibliothèque autonome par Xavier Leroy, qui est aussi bien connu comme l'un des créateurs de OCaml.

le mutex adaptatif a survécu en NTPL sous une forme essentiellement non modifiée: le code est presque identique, incluant la magie constantes pour le lissage de l'estimateur et le spin maximum par rapport à l'estimateur.

sous SMP, lorsque vous allez acquérir un mutex et que vous voyez qu'il est verrouillé, il peut être sous-optimal d'abandonner et d'appeler dans le noyau pour bloquer. Si le propriétaire de la serrure ne tient la serrure que pour quelques instructions, il est moins coûteux d'attendre l'exécution de ces instructions, puis d'acquérir la serrure avec une opération atomique, au lieu de passer des centaines de cycles supplémentaires en faisant un système d'appel.

les développeurs du noyau le savent très bien, ce qui est l'une des raisons pour lesquelles nous avons des spinlocks dans le noyau Linux pour les sections critiques rapides. (Parmi les autres raisons est, bien sûr, ce code qui ne peut pas dormir, parce qu'il est dans un contexte d'interruption, peut acquérir des spinlocks.)

La question est, combien de temps devez-vous attendre? Si vous tournez à jamais jusqu'à ce que la serrure soit acquise, cela peut être sous-optimal. Les programmes d'espace utilisateur ne sont pas bien écrits comme le code du noyau (toux). Ils pourraient avoir de longues sections critiques. Ils ne peuvent pas désactiver préemption; parfois des sections critiques exploser en raison d'un changement de contexte. (Les threads POSIX fournissent maintenant des outils en temps réel pour gérer cela: vous pouvez mettre des threads dans une priorité en temps réel et un planning FIFO et ainsi de suite, en plus de configurer l'affinité du processeur.)

je pense que nous avons expérimenté avec fixe itération compte, mais ensuite j'ai eu cette idée: pourquoi devrions-nous deviner, quand nous pouvons mesurer. Pourquoi ne pas mettre en place un estimateur lissé de la durée de verrouillage, semblable à ce que nous faisons pour l'estimateur de temps d'arrêt de retransmission TCP (RTO). Chaque fois que nous tournons sur une serrure, nous devrions mesurer combien de tours il a réellement pris pour l'acquérir. En outre, nous ne devrions pas tourner indéfiniment: nous devrions peut-être tourner seulement au maximum deux fois la valeur actuelle de l'estimateur. Quand nous prenons une mesure, nous pouvons la lisser exponentiellement, en quelques instructions: prendre une fraction de la valeur précédente, et de la nouvelle valeur, et les additionner ensemble, ce qui est le même que ajouter une fraction de leur différence pour retourner à l'estimateur: disons,estimator += (new_val - estimator)/8 pour un 1/8 7/8 mélange entre l'ancienne et la nouvelle valeur.

vous pouvez voir ça comme un chien de garde. Supposons que l'estimateur vous indique que la serrure, en moyenne, prend 80 tours pour acquérir. Vous pouvez être tout à fait sûr, alors, que si vous avez exécuté 160 rotations, alors quelque chose ne va pas: le propriétaire de la serrure exécute un cas exceptionnellement long, ou peut-être a frappé une page fault ou était autrement préempté. À ce moment, le fil d'attente coupe ses pertes et appelle le noyau à bloquer.

sans mesure, vous ne pouvez pas le faire avec précision: il n'y a pas de valeur" Taille unique". Par exemple, une limite fixe de 200 rotations serait sous-optimale dans un programme dont les sections critiques sont si courtes qu'un verrou peut presque toujours être récupéré après avoir attendu seulement 10 rotations. La fonction de verrouillage mutex brûlerait à travers 200 itérations chaque fois qu'il y a un temps d'attente anormal, au lieu de bien donner jusqu'à, disons, 20 et enregistrement de cycles.

cette approche adaptative est spécialisée, dans le sens qu'elle ne fonctionnera pas pour toutes les serrures dans tous les programmes, donc elle est empaquetée comme un type mutex spécial. Par exemple, cela ne fonctionnera pas très bien pour les programmes qui bloquent les Mutex pendant de longues périodes: des périodes si longues que plus de temps CPU est gaspillé à tourner sur les grandes valeurs d'estimateur qu'il ne l'aurait été en entrant dans le noyau. L'approche n'est pas non plus adapté pour uniprocessors: tous les fils en dehors de la un qui essaie d'obtenir le lock est suspendu dans le noyau. L'approche n'est pas non plus appropriée dans les situations où l'équité est importante: il s'agit d'un verrouillage opportuniste. Peu importe combien d'autres fils ont attendu, peu importe combien de temps, ou Quelle est leur priorité, un nouveau fil peut venir et arracher la serrure.

si vous avez un code très bien comporté avec de courtes sections critiques qui sont fortement contestées, et vous êtes à la recherche d'une meilleure performance sur SMP, l'adaptative mutex peut valoir la peine d'essayer.

52
répondu Kaz 2018-04-01 08:52:51

Le symbole est mentionné:

http://elias.rhi.hi.is/libc/Mutexes.html

"LinuxThreads supporte un seul attribut mutex: le type mutex, qui est soit PTHREAD_MUTEX_ADAPTIVE_NP pour les Mutex "rapides", PTHREAD_MUTEX_RECURSIVE_NP pour les Mutex" récursifs", PTHREAD_MUTEX_TIMED_NP pour les Mutex" chronométrés", ou PTHREAD_MUTEX_ERRORCHECK_NP pour les Mutex" de vérification d'erreur". Comme l'indique le suffixe NP, il s'agit d'une extension non portable de POSIX. standard et ne doit pas être utilisé dans les programmes portables.

le type mutex détermine ce qui se passe si un thread essaie de verrouiller un mutex qu'il possède déjà avec pthread_mutex_lock. Si le mutex est du type" fast", pthread_mutex_lock suspend simplement le thread appelant pour toujours. Si le mutex est du type "vérification d'erreur", pthread_mutex_lock retourne immédiatement avec le code d'erreur EDEADLK. Si le mutex est du type" recursive" , l'appel à pthread_mutex_lock retourne immédiatement avec un code de retour de succès. Le nombre de fois où le fil propriétaire du mutex s'est verrouillé est enregistré dans le mutex. Le thread propriétaire doit appeler pthread_mutex_unlock le même nombre de fois avant de le mutex retourne à l'état déverrouillé.

le type mutex par défaut est "timed", C'est-à-dire PTHREAD_MUTEX_TIMED_NP."

EDIT: mis à jour avec les infos trouvées par jthill (merci!)

un peu plus d'informations sur les drapeaux mutex et le PTHREAD_MUTEX_ADAPTIVE_NP peuvent être trouvées ici:

" le pthred_mutex_adaptive_np est un nouveau mutex qui est destiné à haute débit au détriment de l'équité et même des cycles CPU. Ce mutex ne transfère pas la propriété sur un fil d'attente, mais plutôt permet la concurrence. Aussi, sur un noyau SMP, l'opération de verrouillage utilise la rotation pour rejouer la serrure pour éviter le coût de descheduling."

ce qui suggère essentiellement ce qui suit: mutex peut être implémenté en exigeant des considérations supplémentaires de la logique du thread en raison de sa nature même. Vous aurez à concevoir un algorithme qui peut utiliser ces propriétés résultant en haut débit. Quelque chose qui se charge de l'intérieur (par opposition à "du noyau") où l'ordre d'exécution est sans importance.

il y avait un très bon livre pour la programmation multithreading linux/unix dont le nom m'échappe. Si je le trouve, je le mettrai à jour.

6
répondu Sebastien 2013-11-15 21:30:54