gettimeofday () est garanti de la résolution de microseconde?

voix
82

Je PORTAGE un jeu, qui a été initialement écrit pour l'API Win32, Linux (bien, le portage du port OS X du port Win32 à Linux).

Je l' ai mis en œuvre QueryPerformanceCounteren donnant les uSeconds depuis le processus de démarrage:

BOOL QueryPerformanceCounter(LARGE_INTEGER* performanceCount)
{
    gettimeofday(&currentTimeVal, NULL);
    performanceCount->QuadPart = (currentTimeVal.tv_sec - startTimeVal.tv_sec);
    performanceCount->QuadPart *= (1000 * 1000);
    performanceCount->QuadPart += (currentTimeVal.tv_usec - startTimeVal.tv_usec);

    return true;
}

Ceci, couplé à QueryPerformanceFrequency()donner une 1000000 constante que la fréquence, fonctionne bien sur ma machine , me donner une variable de 64 bits qui contient uSecondsdepuis le début de la place du programme.

Alors est - ce portable? Je ne veux pas découvrir cela fonctionne différemment si le noyau a été compilé une certaine façon ou quelque chose comme ça. Je suis bien avec elle étant non-portable à autre chose que Linux, cependant.

Créé 01/08/2008 à 15:36
source utilisateur
Dans d'autres langues...                            


10 réponses

voix
54

Peut être. Mais vous avez des problèmes plus graves. gettimeofday()peut entraîner des horaires incorrects s'il y a des processus sur votre système qui changent la minuterie (c. -à- ntpd). Sur un linux « normal », bien que, je crois que la résolution gettimeofday()est 10US. Il peut sauter vers l' avant et vers l' arrière et le temps, par conséquent, sur la base des processus en cours d' exécution sur votre système. Cela rend effectivement la réponse à votre question non.

Vous devriez regarder dans clock_gettime(CLOCK_MONOTONIC)les intervalles de synchronisation. Il souffre de plusieurs moins de problèmes en raison de choses comme les systèmes multi-core et les réglages d'horloge externe.

Aussi, regardez dans la clock_getres()fonction.

Créé 01/08/2008 à 15:53
source utilisateur

voix
39

Haute résolution, Timing faible surcharge pour les processeurs Intel

Si vous êtes sur le matériel Intel, voici comment lire le compteur d'instructions en temps réel CPU. Il vous dira le nombre de cycles CPU exécutés depuis le processeur a été démarré. Ceci est probablement le compteur grain le plus fin que vous pouvez obtenir pour la mesure du rendement.

Notez que ceci est le nombre de cycles CPU. Sur Linux, vous pouvez obtenir la vitesse du CPU / proc / cpuinfo et diviser pour obtenir le nombre de secondes. La conversion de ce à un double est tout à fait à portée de main.

Quand je lance cela sur ma boîte, je reçois

11867927879484732
11867927879692217
it took this long to call printf: 207485

Voici le guide du développeur Intel qui donne des tonnes de détails.

#include <stdio.h>
#include <stdint.h>

inline uint64_t rdtsc() {
    uint32_t lo, hi;
    __asm__ __volatile__ (
      "xorl %%eax, %%eax\n"
      "cpuid\n"
      "rdtsc\n"
      : "=a" (lo), "=d" (hi)
      :
      : "%ebx", "%ecx");
    return (uint64_t)hi << 32 | lo;
}

main()
{
    unsigned long long x;
    unsigned long long y;
    x = rdtsc();
    printf("%lld\n",x);
    y = rdtsc();
    printf("%lld\n",y);
    printf("it took this long to call printf: %lld\n",y-x);
}
Créé 02/08/2008 à 09:08
source utilisateur

voix
18

@Bernard:

Je dois admettre que, la plupart de votre exemple est allé directement sur ma tête. Il ne compile et semble fonctionner, cependant. Est-ce sans danger pour les systèmes SMP ou SpeedStep?

Voilà une bonne question ... Je pense que oks le code. D'un point de vue pratique, nous l'utilisons dans mon entreprise tous les jours, et nous courons sur un éventail assez large de boîtes, tout de 2-8 noyaux. Bien sûr, YMMV, etc, mais il semble être un système fiable et peu de frais généraux (car il ne fait pas de changement de contexte dans le système espace) méthode de synchronisation.

En général, comment cela fonctionne est la suivante:

  • déclarer le bloc de code pour être assembleur (et volatile, de sorte que l'optimiseur laisser seul).
  • exécuter l'instruction CPUID. En plus d'obtenir des informations CPU (que nous ne faisons rien avec), il synchronise le tampon d'exécution de la CPU afin que les horaires ne sont pas affectés par hors-exécution d'ordres.
  • exécuter l'exécution rdtsc (horodatage lu). Ce va chercher le nombre de cycles de machine exécutés depuis le processeur a été remis à zéro. Ceci est une valeur 64 bits, donc avec des vitesses de CPU actuelles, il se terminera autour de tous les 194 ans environ. Fait intéressant, dans la référence Pentium original, ils notent qu'il enroule autour de tous les 5800 ans environ.
  • les deux dernières lignes de stocker les valeurs des entrées dans les variables HI et LO, et mettez dans la valeur de retour de 64 bits.

Notes spécifiques:

  • out-of-order exécution peut provoquer des résultats incorrects, donc nous exécuter l'instruction « CPUID » qui, en plus de vous donner quelques informations sur le cpu synchronise tout hors exécution d'ordres d'instruction.

  • La plupart des systèmes d'exploitation synchronisent les compteurs sur les CPU quand ils commencent, donc la réponse est bonne à l'intérieur d'un couple de nano-secondes.

  • Le commentaire hibernant est probablement vrai, mais dans la pratique, vous ne se soucient pas probablement sur les horaires à travers les frontières d'hibernation.

  • en ce qui concerne SpeedStep: plus récents processeurs Intel pour compenser les changements de vitesse et renvoie un nombre ajusté. Je l'ai fait une analyse rapide sur quelques-unes des boîtes sur notre réseau et trouvé une seule case qui ne l'ont: un Pentium 3 exécutant un serveur de base de données ancienne. (Ce sont des boîtes Linux, donc j'ai vérifié avec: grep CONSTANT_TSC / proc / cpuinfo)

  • Je ne suis pas sûr de CPU AMD, nous sommes principalement un magasin Intel, même si je sais que certains de nos systèmes de bas niveau gourous ont fait une évaluation AMD.

Espérons que cela satisfait votre curiosité, c'est un intéressant et (à mon humble avis) sous-étudié domaine de la programmation. Vous savez quand Jeff et Joel parlaient si oui ou non un programmeur C doit savoir? Je criais à eux, « hey oublier ce genre de choses C-haut niveau ... assembleur est ce que vous devez savoir si vous voulez savoir ce que l'ordinateur est en train de faire! »

Créé 04/08/2008 à 01:51
source utilisateur

voix
14

Vous pouvez être intéressé par Linux FAQ pourclock_gettime(CLOCK_REALTIME)

Créé 18/08/2008 à 16:51
source utilisateur

voix
11

Le vin est en fait en utilisant gettimeofday () pour mettre en œuvre QueryPerformanceCounter () et il est connu pour faire beaucoup de jeux Windows fonctionnent sur Linux et Mac.

lance http://source.winehq.org/source/dlls/kernel32/cpu.c#L312

conduit à http://source.winehq.org/source/dlls/ntdll/time.c#L448

Créé 04/08/2008 à 15:44
source utilisateur

voix
9

Ainsi, il est dit explicitement microsecondes, mais dit la résolution de l'horloge système est non spécifiée. Je suppose que la résolution dans ce contexte signifie comment la plus petite quantité, il ne sera jamais incrémenté?

La structure de données est définie comme ayant microsecondes comme une unité de mesure, mais cela ne veut pas dire que l'horloge ou le système d'exploitation est en fait capable de mesurer finement que.

Comme d' autres personnes ont suggéré, gettimeofday()est mauvais parce que le réglage du temps peut provoquer un décalage d'horloge et de jeter votre calcul. clock_gettime(CLOCK_MONOTONIC)est ce que vous voulez, et clock_getres()vous dire la précision de votre horloge.

Créé 02/08/2008 à 18:57
source utilisateur

voix
8

La résolution réelle de gettimeofday () dépend de l'architecture matérielle. processeurs Intel, ainsi que les machines SPARC offrent timers haute résolution qui mesurent microsecondes. D'autres architectures matérielles se replient à la minuterie du système, qui est généralement fixé à 100 Hz. Dans de tels cas, la résolution temporelle sera moins précise.

J'ai obtenu cette réponse de haute résolution Mesure du temps et minuteries, Partie I

Créé 01/08/2008 à 15:55
source utilisateur

voix
5

Cette réponse mentionne des problèmes avec l'horloge étant ajustée. Vos deux problèmes qui garantissent des unités de tiques et les problèmes avec le moment ajustés sont résolus en 11 C ++ avec la <chrono>bibliothèque.

L'horloge std::chrono::steady_clockest garantie de ne pas être réglé, et en outre , il avancera à un taux constant par rapport au temps réel, des technologies telles que SpeedStep ne doit pas affecter.

Vous pouvez obtenir des unités de Typesafe en se convertissant à l' une des std::chrono::durationspécialisations, comme std::chrono::microseconds. Avec ce type il n'y a pas d' ambiguïté sur les unités utilisées par la valeur de la tique. Cependant, gardez à l' esprit que l'horloge ne doit pas nécessairement cette résolution. Vous pouvez convertir une durée à l' attoseconde sans réellement avoir une horloge précise.

Créé 26/06/2012 à 16:57
source utilisateur

voix
4

D'après mon expérience, et de ce que j'ai lu sur Internet, la réponse est « Non », il est pas garanti. Cela dépend de la vitesse du processeur, système d'exploitation, saveur de Linux, etc.

Créé 01/08/2008 à 15:46
source utilisateur

voix
3

La lecture du RDTSC n'est pas fiable dans les systèmes SMP, puisque chaque CPU maintient son propre compteur et chaque compteur n'est pas garanti par synchronisée par rapport à un autre CPU.

Je pourrais suggère d' essayer clock_gettime(CLOCK_REALTIME). Le manuel posix indique que cela devrait être mis en œuvre sur tous les systèmes conformes. Il peut fournir un nombre de nanosecondes, mais vous voudrez probablement vérifier clock_getres(CLOCK_REALTIME)sur votre système pour voir ce que la résolution réelle est.

Créé 18/08/2008 à 16:40
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more