> La mise en attente demande un context switch entre autre.
Ce qui ne coûte rien (ou n'impacte pas les performances) puisque le cpu n'a rien d'autre à foutre (cas où il y a plus de cpu que de thread actif).
> (d'autant que ton code est pas thread safe, vu que deux personne peuvent rentrer avec ton ++i==1.
Il est thread-safe. J'utilise "volatile". Il est thread-safe à un petit soucis près, ça dépend du compilo et du hardware. Mais sur un PC "classique", ça marche.
> Il faut que le test_and_set soit atomique pour que ce soit viable, ce que fait l'instruction asm)
Relis bien le code. Ça marche. Ce qui compte, c'est que ++i soit atomique et réalisé par un thread à la fois (ce que nous garantit "volatile").
volatile int i = 0 ;
lock() {
while (true) {
while (i) ;
if (++i == 1) { [1]
break ;
}
else {
// lock déjà pris par un autre
--i ;
}
}
}
Thread 1 fait "++i" et obtient la valeur 1.
Thread 2 fait "++i" et obtient la valeur 2.
Thead 1 compare la valeur de retour de "++i" avec "1" beaucoup plus tard. C'est true, donc il a le lock.
Thead 2 compare la valeur de retour de "++i" avec "1". C'est false, donc il n'a pas le lock. Plus loins il fait un "--i" pour "remettre de l'ordre".
Que l'incrémentation ET la comparaison ne soit pas atomique n'est pas un problème ici. Le "volatile" garantit qu'il n'y a qu'un thread qui accède à i à la fois.
Mais il faut l'utiliser avec beaucoup de précaution.
Pour "++i" ça doit marcher.
Pour :
i = (DoLock == true ? i+1 : i ) ;
ça doit très probablement ne pas marcher. Le résultat de "i+1" peut être mis dans une "variable temporaire" puis copié dans i.
Mon lock ne marcherait pas s'il fait :
if (i==0) { ++i ; }
Mais ce n'est pas ce qu'il fait.
Il y a effectivement des instructions asm pour faire une incrémentation et un test de façon atomique (il y en a plusieurs).
> D'ailleur c'est pas pour rien que les mutex pthread sont en partie écrit en asm : pour avoir le moins d'overhead possible
Les mutex phtread, ne font pas que ce que je fais (avec la fonction lock()). Il y a spinlock pour un nombre de cycle limité, il y a vérification si c'est un système smp ou non (si c'est mono-cpu, inutile de faire le spinlock et il faut passer directement en sommeil), il enregistre l'id du thread qui fait le lock pour donner un warning si le thread qui fait l'unlock n'est pas le même, les mutex phtread sont inter-processus, mon lock() ne l'ai pas, etc...
> C'est tres simple d'avoir plus d'un million de lock par seconde.
Dans ce cas j'ai envis de dire que c'est compliqué pour ne pas faire ce million de lock par seconde.
Avec volatile (et du matos correcte), il y a plein de cas où on peut éviter les locks. Et ça marche, je le fais courrament sur des trucs qui tourne 24h/24. Par contre, je le fait avec beaucoup de précaution et uniquement pour int, long et pointeur. Il y a même des systèmes (nombreux) qui n'ont pas besoin de "volatile" :-) Les cpus/cache vérifient tout.
[^] # Re: Multicoeur ?
Posté par IsNotGood . En réponse à la dépêche Intel libère TBB. Évalué à 1.
Ce qui ne coûte rien (ou n'impacte pas les performances) puisque le cpu n'a rien d'autre à foutre (cas où il y a plus de cpu que de thread actif).
> (d'autant que ton code est pas thread safe, vu que deux personne peuvent rentrer avec ton ++i==1.
Il est thread-safe. J'utilise "volatile". Il est thread-safe à un petit soucis près, ça dépend du compilo et du hardware. Mais sur un PC "classique", ça marche.
> Il faut que le test_and_set soit atomique pour que ce soit viable, ce que fait l'instruction asm)
Relis bien le code. Ça marche. Ce qui compte, c'est que ++i soit atomique et réalisé par un thread à la fois (ce que nous garantit "volatile").
volatile int i = 0 ;
lock() {
while (true) {
while (i) ;
if (++i == 1) { [1]
break ;
}
else {
// lock déjà pris par un autre
--i ;
}
}
}
Thread 1 fait "++i" et obtient la valeur 1.
Thread 2 fait "++i" et obtient la valeur 2.
Thead 1 compare la valeur de retour de "++i" avec "1" beaucoup plus tard. C'est true, donc il a le lock.
Thead 2 compare la valeur de retour de "++i" avec "1". C'est false, donc il n'a pas le lock. Plus loins il fait un "--i" pour "remettre de l'ordre".
Que l'incrémentation ET la comparaison ne soit pas atomique n'est pas un problème ici. Le "volatile" garantit qu'il n'y a qu'un thread qui accède à i à la fois.
Mais il faut l'utiliser avec beaucoup de précaution.
Pour "++i" ça doit marcher.
Pour :
i = (DoLock == true ? i+1 : i ) ;
ça doit très probablement ne pas marcher. Le résultat de "i+1" peut être mis dans une "variable temporaire" puis copié dans i.
Mon lock ne marcherait pas s'il fait :
if (i==0) { ++i ; }
Mais ce n'est pas ce qu'il fait.
Il y a effectivement des instructions asm pour faire une incrémentation et un test de façon atomique (il y en a plusieurs).
> D'ailleur c'est pas pour rien que les mutex pthread sont en partie écrit en asm : pour avoir le moins d'overhead possible
Les mutex phtread, ne font pas que ce que je fais (avec la fonction lock()). Il y a spinlock pour un nombre de cycle limité, il y a vérification si c'est un système smp ou non (si c'est mono-cpu, inutile de faire le spinlock et il faut passer directement en sommeil), il enregistre l'id du thread qui fait le lock pour donner un warning si le thread qui fait l'unlock n'est pas le même, les mutex phtread sont inter-processus, mon lock() ne l'ai pas, etc...
> C'est tres simple d'avoir plus d'un million de lock par seconde.
Dans ce cas j'ai envis de dire que c'est compliqué pour ne pas faire ce million de lock par seconde.
Avec volatile (et du matos correcte), il y a plein de cas où on peut éviter les locks. Et ça marche, je le fais courrament sur des trucs qui tourne 24h/24. Par contre, je le fait avec beaucoup de précaution et uniquement pour int, long et pointeur. Il y a même des systèmes (nombreux) qui n'ont pas besoin de "volatile" :-) Les cpus/cache vérifient tout.