Comment puis-je savoir si chaque cœur de ma machine utilise la même timer?

J’essaie d’écrire du code pour déterminer si clock_gettime utilisé avec CLOCK_MONOTONIC_RAW me donnera des résultats provenant du même matériel sur des cœurs différents.

D’après ce que j’ai compris, chaque kernel peut produire des résultats indépendants, mais pas toujours . J’ai été chargé d’obtenir des timings sur tous les cœurs avec une précision de 40 nanosecondes.

La raison pour laquelle je n’utilise pas CLOCK_REALTIME est que mon programme ne doit absolument pas être affecté par les ajustements NTP.

Modifier:

J’ai trouvé la fonction unsynchronized_tsc qui essaye de tester si le TSC est le même sur tous les cœurs. J’essaie maintenant de trouver si CLOCK_MONOTONIC_RAW est basé sur le TSC.

Édition finale :

Il s’avère que CLOCK_MONOTONIC_RAW est toujours utilisable sur les systèmes multi-core et ne repose pas sur le TSC même sur les machines Intel.

Faire des mesures avec précision; vous auriez besoin de:

  • code exécuté sur tous les processeurs, qui lit le compteur d’horodatage du processeur et le stocke dès qu’un “événement” se produit
  • une manière de créer “un événement” qui soit remarqué en même temps par tous les processeurs
  • un moyen d’empêcher les problèmes de synchronisation causés par les IRQ, les commutateurs de tâches, etc.

Les diverses possibilités pour l’événement incluent:

  • interroger un emplacement de mémoire dans une boucle, où une CPU écrit une nouvelle valeur et d’autres CPU cessent d’interroger lorsqu’ils voient la nouvelle valeur
  • utiliser l’APIC local pour diffuser un IPI (interruption inter-processeur) sur toutes les CPU

Pour ces deux méthodes, il existe des délais entre les CPU (en particulier pour les systèmes NUMA plus importants) – une écriture en mémoire (cache) peut être visible sur le CPU qui a immédiatement écrit, et visible par un CPU sur une autre puce physique ( dans un domaine NUMA différent) plus tard. Pour éviter cela, vous devrez peut-être trouver la moyenne de lancement de l’événement sur tous les processeurs. Par exemple (pour 2 processeurs), un processeur est initié et les deux mesurent, puis les autres processeurs initient et les deux mesurent, puis les résultats sont combinés pour annuler toute “latence de propagation d’événement”.

Pour résoudre d’autres problèmes de synchronisation (IRQ, commutateurs de tâches, etc.), je souhaiterais effectuer ces tests au démarrage, où rien ne peut perturber les choses. Sinon, vous devez soit éviter les problèmes (assurez-vous que tous les processeurs fonctionnent à la même vitesse, désactivez les IRQ, désactivez les commutateurs de threads, arrêtez tous les bus PCI, etc.) ou exécutez le même test plusieurs fois. vous obtenez des résultats similaires la plupart du temps).

Notez également que tout ce qui précède ne peut que garantir que les compteurs d’horodatage étaient synchronisés au moment du test, et ne garantissent pas qu’ils ne seront pas désynchronisés après le test. Pour vous assurer que les processeurs restnt synchronisés, vous devez vous fier aux garanties de “l’horloge monotone” du processeur (mais les anciens processeurs n’offrent pas cette garantie).

Finalement; Si vous essayez de le faire dans l’espace utilisateur (et non dans le code du kernel); alors, je vous conseille de concevoir du code d’une manière qui n’est pas si fragile au départ. Même si les TSC sur différents processeurs sont parfaitement synchronisés à tout moment, vous ne pouvez pas empêcher une IRQ d’interrompre immédiatement avant ou immédiatement après la lecture du TSC (et il n’y a aucun moyen de faire quelque chose de manière atomique et de lire le TSC en même temps) temps); Par conséquent, si votre code requirejs une synchronisation aussi précise, la conception de votre code est probablement erronée.