précision rdtsc sur les cœurs CPU
j'envoie des paquets réseau à partir d'un thread et je reçois des réponses sur un 2ème thread qui tourne sur un noyau CPU différent. Mon processus mesure le temps entre l'envoi et la réception de chaque paquet (similaire au ping). J'utilise le rdtsc pour obtenir une haute résolution, un timing faible, ce qui est nécessaire pour ma mise en œuvre.
toutes les mesures semblent fiables. Pourtant, je m'inquiète de la précision rdtsc à travers les cœurs, puisque j'ai lu certains textes qui impliquent que tsc n'est pas synchronisé entre les cœurs.
j'ai trouvé les informations suivantes à propos de TSC dans wikipedia
Constante TSC comportement garantit qu' la durée de chaque tic d'horloge est uniforme et soutient l'utilisation de TSC comme horloge murale même si le le noyau du processeur change de fréquence. Ce architecturale comportement de déplacement en avant pour tous les processeurs Intel.
pourtant je m'inquiète de l'accruracy sur les cœurs, et c'est ma question
Plus D'Info
- j'exécute mon processus sur une machine Intel nehalem.
- le système D'exploitation est Linux.
- Le " constant_tsc" le drapeau cpu est défini pour tous les noyaux.
6 réponses
X86_FEATURE_CONSTANT_TSC
+ X86_FEATURE_NONSTOP_TSC
bits dans cpuid (edx=x80000007, bit #8; case unsynchronized_tsc
function du noyau linux pour plus de vérifications)
Intel Designer vol3b, section 16.11.1 Invariant TSC il est dit ce qui suit
" 16.11.1 Invariant TSC
le compteur d'horodatage dans les nouveaux processeurs peut supporter une amélioration, appelée TSC invariante. Le support du processeur pour TSC invariant est indiqué par CPUID.80000007H: EDX[8].
le TSC invariant s'exécute à une vitesse constante dans tous les ACPI P -, C -. et T-unis. C'est l'architecture comportement aller de l'avant. Sur les processeurs avec un support TSC invariant, L'OS peut utiliser le TSC pour les services de minuterie murale (au lieu des minuteries ACPI ou HPET). Les lectures TSC sont beaucoup plus efficaces et n'entraînent pas les frais généraux associés à une transition d'anneau ou l'accès à une ressource de plate-forme."
donc, si TSC peut être utilisé pour wallclock, ils sont garantis d'être dans synchronisation.
sous linux, vous pouvez utiliser clock_gettime (3) avec CLOCK_MONOTONIC_RAW, ce qui vous donne un résultat de nanosecondes et n'est pas soumis aux mises à jour de ntp (s'il y en a eu).
en fait, il semble que cores ne partage pas TSC, vérifier ce fil: http://software.intel.com/en-us/forums/topic/388964
En résumé, les différents noyaux ne partagent pas TSC, parfois TSC peut sortir de la synchronisation si un noyau change à un État d'énergie spécifique, mais cela dépend du type de CPU, donc vous devez vérifier la documentation Intel. Il semble que la plupart des systèmes d'exploitation synchronisent TSC au démarrage.
J'ai vérifié les différences entre TSC sur différents noyaux, en utilisant un algorithme de réaction passionnant, sur une machine Debian Linux avec un processeur core i5. Le processus exciter (dans un noyau) a déchiffré le TSC dans une variable partagée, lorsque le processus de réaction a détecté un changement dans cette variable, il compare sa valeur et le compare avec son propre TSC. Ceci est un exemple de sortie de mon programme de test:
TSC ping-pong test result:
TSC cores (exciter-reactor): 0-1
100 records, avrg: 159, range: 105-269
Dispersion: 13
TSC ping-pong test result:
TSC cores (exciter-reactor): 1-0
100 records, avrg: 167, range: 125-410
Dispersion: 13
le temps de réaction lorsque le CPU de l'excitateur est 0 (159 tics en moyenne) est presque le même que lorsque le CPU de l'excitateur est 1 (167 tics). Cela indique qu'ils sont assez bien synchronisée (peut-être avec quelques tics de différence). Sur les autres paires de carottes, les résultats étaient très semblables.
D'autre part, l'instruction d'assemblage rdtscp renvoie une valeur indiquant le CPU dans lequel le TSC a été lu. Ce n'est pas votre cas mais cela peut être utile quand vous voulez mesurer le temps dans un simple segment de code et vous voulez vous assurer que le processus n'a pas été déplacé de CPU au milieu du code.
sur les processeurs récents, vous pouvez le faire entre des noyaux séparés du même paquet (c.-à-d. un système avec un seul processeur core iX), vous ne pouvez tout simplement pas le faire dans des paquets séparés (processeurs), parce qu'ils ne partageront pas le rtc. Vous pouvez vous en tirer grâce à cpu affinity (verrouillage des threads pertinents à des cœurs spécifiques), mais là encore, cela dépendra de la façon dont votre application se comporte.
Sur linux, vous pouvez vérifier constant_tsc sur /proc/cpuinfo pour voir si le processeur dispose d'un seul tsc valable pour l'ensemble du paquet. Le registre brut est dans CPUID.80000007H: EDX[8]
ce que je lis autour, mais que je n'ai pas encore confirmé programatiquement, c'est que les processeurs AMD à partir de la révision 11h ont la même signification pour ce bit cpuid.
je vous recommande de ne pas utiliser rdtsc. Non seulement il n'est pas portable, il n'est pas fiable et ne fonctionne généralement pas - sur certains systèmes, le rdtsc n'est pas mis à jour uniformément (comme si vous utilisez speedstep etc). Si vous voulez des informations de synchronisation précises, vous devez définir L'option SO_TIMESTAMP sur la socket et utiliser recvmsg() pour obtenir le message avec une horodatage (résolution microseconde).
de plus, le timestamp que vous obtenez avec SO_TIMESTAMP est en fait l'heure à laquelle le noyau a reçu le paquet, pas quand votre tâche s'est avérée le remarquer.
Vous pouvez définir l'affinité du thread en utilisant sched_set_affinity()
API afin d'exécuter votre thread sur un noyau CPU.