• [^] # Re: Multicoeur ?

    Posté par . En réponse à la dépêche Intel libère TBB. Évalué à 4.

    • le volatile garantie que les données seront mise a nouveau en mémoire une fois qu'elles sont calculées.
    • Elle évite donc qu'elles reste dans des registres pour des optimisations.
    • Par exemple j'ai trois variables et 5 registres. Je peux stocker toutes les variables dans les registres et faire toutes mes instructions dessus.
    • Si il y a un thread qui en a besoin au milieu (je libère un lock et je le reprend après) je n'ai aucune assurance que les variables qui sont des les registres sont bien pushé en mémoire. Le volatile sert a ca.
    • D'ailleur le volatile nous protège tellement peu de ca qu'il y a un spinlock au début des lock ou unlock d'un mutex. Car le spinlock est fait lui sur une véritable instruction atomique (test and set).
    • exemple de code .
    toto (){
    int a;
    lock();
    ++a;
    a*=2;
    unlock();
    do_something();
    lock();
    a/=2;
    unlock();
    }
    
    Sans le volatile, au premier unlock, on ne sait pas si a sera en mémoire (donc visible par les autres threads) ou alors encore dans les registres. Si il est encore dans les registres, alors lors du second lock, on n'aura pas une bonne valeur de a car il a pu etre modifié pendant qu'on était dans do_something et qu'on aurait donc une valeur obsolète. le volatile n'est permet pas de faire une fonction atomique. Comme je sens déja l'attaque (pas forcément de lasher ou d'isnotgood, mais mieux vaut prevenir que guerir) du 'tu ne sais pas de quoi tu parle' regardons donc ce que fait volatile :
    int test1()
    {
     volatile int a;
     ++a;
     a+=2;
     return a;
    }
    int test2()
    {
     int a;
     ++a;
     a+=2;
     return a;
    }
    int main()
    {
    }
    
    Un code relativement simple n'est il pas ? Maintenant regardons l'asm qu'il nous génère pour ca : gcc -S test.c
    test1:
     pushl %ebp
     movl %esp, %ebp
     subl 16,ドル %esp
     movl -4(%ebp), %eax ; on recupere a
     addl 1,ドル %eax ; ++a
     movl %eax, -4(%ebp) ; on le remet 
     movl -4(%ebp), %eax ; on le recupere a nouveau
     addl 2,ドル %eax ; a+=2
     movl %eax, -4(%ebp) ; on le remet
     movl -4(%ebp), %eax ; return a
     leave ; bye bye
     ret
     .size test1, .-test1
    .globl test2
     .type test2, @function
    test2:
     pushl %ebp
     movl %esp, %ebp
     subl 16,ドル %esp
     addl 1,ドル -4(%ebp) ;++a
     addl 2,ドル -4(%ebp) ;a+=2
     movl -4(%ebp), %eax ;return a
     leave
     ret
     .size test2, .-test2
    
    je vois mal en quoi faire 3 instructions a la place d'une seule rend ces instructions 'atomiques'. Ps désolé pour la liste en début de commentaire, je sais pas comment incoporer du code , mais pouvoir avoir des retour chariots 'normaux' dans le reste du commentaire.