9
votes

Comment dormir pour quelques microsecondes

Considérez le code suivant:

Elapsed: 5.308000 us
Elapsed: 69.142000 us


4 commentaires

Vous avez à la fois Linux et en temps réel en tant que tags. Pourquoi? Ils sont la craie et le fromage.


@David: Ce n'est pas comme s'il y a des gens fous travaillant sur Linux-RT ou quoi que ce soit comme ça ... oh attendre.


Je suis intrigué: qu'est-ce que c'est exactement le contexte? De quoi avez-vous besoin de ce genre de précision?


@Asdf: contrôle réel en temps réel des plasmas confinés magnétiquement.


7 Réponses :


8
votes

Le planificateur d'exploitation du système d'exploitation ne va pas faire quelque chose comme "Oh, prenez ce fil du processeur pour exactement 86 cycles d'horloge, puis le remettez-le".

Vous abandonnez le processeur, vous avez abandonné le processeur. Le système d'exploitation vous remettra de retour quand il se sent comme ça. Les chances sont que vous devrez attendre que tout ce qui est en cours d'exécution abandonne le processeur avant de pouvoir se faufiler.


13 commentaires

De plus, selon le chipset, la CPU et quelques autres choses, Clock_GetTime () pourrait être à la fois coûteuse et pas très déterministe. Il est un peu difficile de pointer du doigt sur quel le problème le plus important est ici même si la première méthode indique que le problème est que le thread est préempté et non la mise en œuvre de l'horloge.


Eh bien, vous obtiendrez immédiatement reporté avec planched_setschéduler (plancher_fifo) (ou planche_rr ou planche_deadline , quand disponible). Mais ce sont des cas très spéciaux.


Je ne veux pas prendre le fil du processeur, je ne veux juste rien faire pour un temps précis. N'y a-t-il aucun moyen d'accomplir cela?


@Nikratio: Si vous devez exécuter précisément à un moment donné, vous avez essentiellement besoin d'un système d'exploitation en temps réel. Sinon, vous n'avez aucune garantie que vous ne serez pas échangé du processeur à un moment donné. Pourquoi avez-vous besoin de courir précisément à ce moment-là?


"Vous devrez attendre que tout ce qui est en cours d'exécution abandonne le processeur" - Je suis à peu près sûr que Linus a eu le tour de la mise en œuvre de la préemption d'ici ...


@Steve: "Les chances sont ...". À moins que vous fassiez quelque chose d'autre de la CPU à la fois intensive, la plupart des autres processus bloqueront l'IO ou compléter leur travail et attendre avant d'expirer leurs quantums.


@Anon: Ok, je vois ce que tu veux dire. Je l'ai lu comme "tu devras attendre" pour une raison fondamentale qui l'empêche de se produire plus tôt. Vous voulez dire "vous devrez attendre", dans le sens où dans la pratique, vous n'aurez pas à attendre plus longtemps car la plupart des ordinateurs sont inactifs la plupart du temps de toute façon?


@Anon, si vous avez assez de cœurs, cela ne devrait pas être une raison


@Bestssss: Qu'est-ce qui vous fait penser que cela est en cours d'exécution sur une machine de 8 + -core?


@Anon, je ne l'ai pas impliqué, mais si vous avez besoin de timing parfait / en temps réel, vous feriez mieux de préparer suffisamment de cœurs, alors si occupé est nécessaire ...


@Bestsssss: Ou vous pouvez exécuter un système d'exploitation en temps réel. Vous savez, comme celui qu'ils allaient sur la lune. Je suis à peu près sûr que cela n'avait pas besoin d'une monstruosité de 8 cœurs.


@Anon, pas sûr qu'il était multi-processus non plus.


@Bestsssss: C'était très certainement un système multi-tâches. Peut-être devriez-vous lire un compte de l'atterrissage Apollo 11, où une composante logicielle (le radar d'atterrissage) n'a pas pu suivre et respecter ses délais, mais le système a pu conserver tous les autres composants avec des exigences en temps réel fonctionnant en douceur.



2
votes

Eh bien, vous devrez apprendre à vivre avec elle puisque la page de l'homme, en partie: Le temps réel dormi peut être plus long, en raison des latences de système et des limitations possibles de la résolution de la minuterie du matériel < / code>: -)

Maintenant quant à la réponse à votre question, ma meilleure estimation est que c'est parce que votre première boucle est en cours d'exécution. En d'autres termes, il n'y a pas de commutateurs contextuels impliqués car vous exécutez la CPU Flat Out et vous ferez tout ce qui fonctionne dans vos 100 ms quant à vous par le planificateur.

Cependant, il y a de bonnes chances que nanosleep vous désactivent depuis que vous demandez explicitement à être mis au sommeil. Il ne sera pas si inefficace de simplement mettre votre processus dans un serré pendant la boucle jusqu'à ce que la durée soit terminée: -)

Cela signifie que vous êtes soumis à tous les aléas du planificateur y compris le fait qu'un autre processus peut totalement utiliser son quanta, d'où votre processus peut donc être hors de neuf. Sur un système chargé fortement suffisant, il pourrait être sorti pendant un certain temps.


0 commentaires

0
votes

Efficacité - Un système d'exploitation qui a permis de commuter et de sortir des tâches avec une précision de quelques cycles d'horloge feraient très peu d'autre.

Il existe des systèmes d'exploitation spécialisés qui font cela - mais sur du matériel régulier, vous payez beaucoup de frais généraux pour l'hyperviseur


0 commentaires

0
votes

Ceci est une réponse de maintien - je ne connais pas les internes de Linux pertinents, espérons qu'un expert peut venir et le dégager.

Une possibilité est que 69us est simplement la surcharge crue de déschuilant puis de reprogrammer le fil. Même si le sommeil est court, le noyau pourrait faire beaucoup de travail pour effectuer un commutateur de contexte (ou un demi-commutateur de contexte, s'il n'y a rien à planifier), puis l'annulera presque immédiatement. Je ne sais pas combien de temps "devrait" prendre Linux sur un PC typique.

Si cela ne l'explique pas, un planificateur a généralement un concept d'une "ligne de temps", ce qui est de la longueur d'un thread planifié à exécuter avant que le planificateur ne pense de le changer, à moins que cela ne soit désinstallé. quelque chose avec une priorité plus élevée devient programmé. Le noyau aura des chronométrages de faible teneur en train de tirer des interruptions à la fin d'une tranche de temps (en plus d'interrompre l'incendie de certains autres événements tels que des E / S pouvant débloquer un fil). Lorsqu'il prend fin, le planificateur peut décider de continuer avec le même thread ou de passer à un autre.

Il semble donc que lorsque vous dormez, soit (A) Le planificateur ne définit pas réellement une minuterie qui rendra votre fil planifiable à l'heure requise, il s'agit simplement d'attendre une franchise de temps. La CPU va donc au ralenti plus longtemps que nécessaire; ou sinon (b) il rend votre fil planifiable à l'heure demandée, mais lorsque vous avez abandonné l'exécution en dormant, un autre thread de la même priorité est arrivé, et le planificateur n'a pas de motif de vous les préférer avant que ce soit "votre tour "Encore une fois selon les règles, le planificateur utilise généralement pour décider du fil à planifier.

69us est assez court pour être un artefact de Timeslicing, cependant.

Vous semblez avoir une solution rudimentaire - vous pouvez retarder les très courtes périodes en vous asseoir dans une vérification de la boucle, comme un spinlock. Comme tout le monde dit, cependant, dans un système non en temps réel, plus ou moins par définition, vous ne pouvez pas exiger que le planificateur exécute votre thread à un moment donné. Même dans un système en temps réel, si vous êtes en concurrence avec des fils de priorité égale, vous risquez de perdre, et si vous êtes en concurrence avec des threads à une priorité plus élevée, vous perdrez.


0 commentaires

10
votes

Si vous souhaitez que votre application soit capable de "veille" aussi précisément que possible, mettez d'abord votre application dans des conditions en temps réel

  • Utilisez une classe de planificateur en temps réel pour votre programme / thread: plancher_fiFo ou planche_rr
  • Élevez votre programme / priorité de fil
  • et si vous allez "dormir" pendant moins que le montant minimum que le noyau va manipuler, tâche manuellement d'attendre

    regarder http://www.drdobbs.com/184402031

    Et cette autre question: Utilisation de Nanosleep High CPU?


2 commentaires

Avec la priorité en temps réel, Nanosleep fonctionne comme je le veux. Merci!


planche_deadline arrive! lwn.net/articles/356576 LWN.net/Articles/396634 espérons-le, d'améliorer la convivialité RT sur Linux. (Si vous n'êtes pas prudent avec plancher_fiFo / planche_rr , vous pouvez facilement verrouiller toute la machine.)



1
votes

Vous pouvez utiliser USLEP méthode pour obtenir la veille des unités microsecondes.


1 commentaires

C'est à peu près la même chose que l'horloge_nanosleep, qui, comme expliqué dans les questions et autres réponses, ne fait pas tout à fait le travail.



2
votes
// busy wait for 10 microseconds
struct timespec ttime,curtime;

// get the time
clock_gettime(CLOCK_REALTIME,&ttime);

// clear the nanoseconds and keep the seconds in order not to overflow the nanoseconds
ttime.tv_nsec = 0;

// set it back
clock_settime(CLOCK_REALTIME,&ttime);

// get the time again 
clock_gettime(CLOCK_REALTIME,&ttime);

// increase the nano seconds by 10*1000
ttime.tv_nsec += 10000;

// loop
while(true){
  clock_gettime(CLOCK_REALTIME,&curtime);
  if (curtime.tv_nsec > ttime.tv_nsec)
    break;
}
// it is much better than the usleep.

0 commentaires