• [^] # Re: Ai-je bien compris ?

    Posté par . En réponse au journal Performances des processeurs Intel et optimisation. Évalué à 10.

    Je suis d'accord en ce que la méthodologie me semble peu rigoureuse. Mais en même temps, on peut sans doute faire en sorte de l'améliorer ! :-)

    Ta suggestion de faire tout tourner sur un seul cœur les deux versions est à mon avis excellente : même s'il y a une race condition, les effets de bords ne seront pas réellement « visibles » dans le cas non thread-safe.

    Les instructions atomiques sont certes plus lentes que des instructions normales, mais elles ont aussi quelques avantages/propriétés. Je vais en citer quelques uns:

    1. Une instruction atomique sur x86 actuel (donc Core i5) effectue les opérations suivantes : load-modify-write. Pendant que ceci s'opère, le processeur verrouille la ligne contenant le mot à modifier, et souvent aussi le bus mémoire du cœur qui effectue la modification: le mot est chargé dans un registre, modifié/comparé en utilisant une des UAL du cœur qui a effectué l'op atomique, puis stocké à nouveau en mémoire.
    2. Au sein d'un même processeur multi-cœur, lorsqu'on utilise une instruction atomique, seule la ligne de cache qui contient la donnée accédée est verrouillée. Ce qui est important avec ce constat, c'est que le cache lui-même n'est pas complètement verrouillé, et aussi qu'il n'y a pas « d'écriture retour » (write-back) vers la DRAM automatiquement après exécution d'une instruction atomique. Bref, il y a bien sérialisation des écritures/lectures sur une ligne de cache donnée, mais pas sur le bloc/niveau de cache complet (ce qui se faisait à une époque, le bus étant complètement verrouillé pour ce niveau de cache tant que l'op atomique avait lieu).
    3. Si jamais tu n'utilises pas d'instruction atomique pour accéder à un mot partagé par plusieurs threads, et que ce mot n'est pas « isolé » tout seul sur sa ligne de cache, tu risques de provoquer un phénomène de faux partage (false sharing), c'est-à-dire que le mot est modifié et du coup indique que la ligne entière est modifiée. Si par hasard d'autres données étaient utilisées en lecture ou écriture par un autre thread sur un autre cœur (en L2 par ex), la ligne devient marquée invalide alors qu'en fait c'était pas le cas. Je ne sais pas si c'est ce qui se passe, mais il arrive qu'en induisant des délais supplémentaire, une opération « lisse » les effets de contention sur un certain composant mémoire (je ne sais pas si je suis clair).

    Dans tous les cas, comme on te le faisait remarquer plus haut, si tu ne fournis pas ton code, on ne peut que spéculer.