J'ai expérimenté le multi threading et le traitement parallèle et j'avais besoin d'un compteur pour faire un comptage de base et une analyse statistique de la vitesse du traitement. Pour éviter les problèmes d'utilisation simultanée de ma classe, j'ai utilisé une instruction de verrouillage sur une variable privée de ma classe:
private object mutex = new object();
public void Count(int amount)
{
lock(mutex)
{
done += amount;
}
}
Mais je me demandais ... combien coûte le verrouillage d'une variable? Quels sont les effets négatifs sur les performances?
c#
.net
multithreading
locking
parallel-processing
Kees C. Bakker
la source
la source
Réponses:
Voici un article sur le coût. La réponse courte est 50ns.
la source
lock
plus que vous ne vous inquiétez pas au sujet du coût d'utilisation d' une variable.La réponse technique est que cela est impossible à quantifier, cela dépend fortement de l'état des tampons de réécriture de la mémoire du processeur et de la quantité de données que le pré-récupérateur a collectées doit être rejetée et relue. Les deux sont très non déterministes. J'utilise 150 cycles CPU comme approximation de fond de l'enveloppe qui évite les déceptions majeures.
La réponse pratique est que c'est waaaay moins cher que le temps que vous dépenserez pour déboguer votre code lorsque vous pensez pouvoir ignorer un verrou.
Pour obtenir un nombre précis, vous devrez mesurer. Visual Studio dispose d'un analyseur de concurrence astucieux disponible en tant qu'extension.
la source
Lectures complémentaires:
Je voudrais présenter quelques articles de ma part, qui s'intéressent aux primitives de synchronisation générales et qui explorent Monitor, le comportement des instructions de verrouillage C #, les propriétés et les coûts en fonction de scénarios distincts et du nombre de threads. Il s'intéresse particulièrement au gaspillage du processeur et aux périodes de débit pour comprendre la quantité de travail pouvant être effectuée dans plusieurs scénarios:
https://www.codeproject.com/Articles/1236238/Unified-Concurrency-I-Introduction https://www.codeproject.com/Articles/1237518/Unified-Concurrency-II-benchmarking-methodologies https: // www. codeproject.com/Articles/1242156/Unified-Concurrency-III-cross-benchmarking
Réponse originale:
Oh cher!
Il semble que la bonne réponse signalée ici comme LA RÉPONSE est intrinsèquement incorrecte! Je voudrais demander à l'auteur de la réponse, respectueusement, de lire l'article lié jusqu'à la fin. article
L'auteur de l'article de 2003 article a été mesure sur la machine Dual Core seulement et dans le premier cas de mesure, il mesure de verrouillage avec un seul fil seulement et le résultat était d' environ 50ns par un accès de verrouillage.
Cela ne dit rien sur un verrou dans l'environnement concurrent. Nous devons donc continuer à lire l'article et dans la seconde moitié, l'auteur mesurait le scénario de verrouillage avec deux et trois threads, ce qui se rapproche des niveaux de concurrence des processeurs actuels.
Ainsi, l'auteur dit qu'avec deux threads sur Dual Core, les verrous coûtent 120ns, et avec 3 threads, cela passe à 180ns. Cela semble donc clairement dépendre du nombre de threads accédant au verrou simultanément.
Donc c'est simple, ce n'est pas 50 ns à moins qu'il ne s'agisse d'un seul thread, où le verrou devient inutile.
Un autre problème à considérer est qu'il est mesuré en temps moyen !
Si le temps des itérations était mesuré, il y aurait même des temps entre 1 ms et 20 ms, simplement parce que la majorité était rapide, mais peu de threads attendront le temps des processeurs et subiront même de longs délais de quelques millisecondes.
C'est une mauvaise nouvelle pour tout type d'application nécessitant un débit élevé et une faible latence.
Et le dernier point à considérer est qu'il pourrait y avoir des opérations plus lentes à l'intérieur de la serrure et c'est très souvent le cas. Plus le bloc de code est exécuté longtemps à l'intérieur de la serrure, plus le conflit est élevé et les retards montent très haut.
Veuillez noter que plus d'une décennie s'est écoulée depuis 2003, c'est-à-dire que quelques générations de processeurs sont spécifiquement conçues pour fonctionner de manière entièrement simultanée et que le verrouillage nuit considérablement à leurs performances.
la source
Cela ne répond pas à votre question sur les performances, mais je peux dire que le .NET Framework offre une
Interlocked.Add
méthode qui vous permettra d'ajouter votreamount
à votredone
membre sans verrouiller manuellement sur un autre objet.la source
lock
(Monitor.Enter / Exit) est très bon marché, moins cher que des alternatives comme un Waithandle ou Mutex.Mais si c'était (un peu) lent, préféreriez-vous avoir un programme rapide avec des résultats incorrects?
la source
Le coût d'une serrure en boucle serrée, par rapport à une alternative sans serrure, est énorme. Vous pouvez vous permettre de boucler plusieurs fois tout en étant plus efficace qu'un verrou. C'est pourquoi les files d'attente sans verrouillage sont si efficaces.
Production:
la source
Il existe différentes manières de définir le «coût». Il y a la surcharge réelle d'obtention et de libération du verrou; comme l'écrit Jake, c'est négligeable à moins que cette opération ne soit effectuée des millions de fois.
L'effet que cela a sur le flux d'exécution est plus pertinent. Ce code ne peut être entré que par un thread à la fois. Si vous avez 5 threads effectuant cette opération régulièrement, 4 d'entre eux finiront par attendre que le verrou soit libéré, puis seront le premier thread programmé pour entrer ce morceau de code après que ce verrou soit libéré. Donc, votre algorithme va souffrir considérablement. Cela dépend de l'algorithme et de la fréquence à laquelle l'opération est appelée. Vous ne pouvez pas vraiment l'éviter sans introduire des conditions de concurrence, mais vous pouvez l'améliorer en minimisant le nombre d'appels au code verrouillé.
la source