Considérez le code suivant:
Elapsed: 5.308000 us Elapsed: 69.142000 us
7 Réponses :
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". P>
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. P>
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) code> (ou
planche_rr code> ou
planche_deadline code>, 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.
Eh bien, vous devrez apprendre à vivre avec elle puisque la page de l'homme, en partie: Maintenant quant à la réponse em> à 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. P>
Cependant, il y a de bonnes chances que Cela signifie que vous êtes soumis à tous les aléas du planificateur y compris em> 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. P> 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>: -) p>
nanosleep code> 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 code> jusqu'à ce que la durée soit terminée: -) p>
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. P>
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 p>
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. P>
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. P>
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. P>
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. p>
69us est assez court pour être un artefact de Timeslicing, cependant. P>
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 em> perdrez. P>
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 P>
regarder http://www.drdobbs.com/184402031 P>
Et cette autre question: Utilisation de Nanosleep High CPU? P>
Avec la priorité en temps réel, Nanosleep fonctionne comme je le veux. Merci!
planche_deadline code> 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 code> /
planche_rr code>, vous pouvez facilement verrouiller toute la machine.)
Vous pouvez utiliser USLEP code> méthode pour obtenir la veille des unités microsecondes. P>
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.
// 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.
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.