2
votes

Taille optimale pour un tampon en anneau avec un seul producteur et un seul consommateur

J'ai un seul producteur, un seul problème de consommateur qui (je crois) peut être résolu en utilisant un tampon circulaire / en anneau.

J'ai un microcontrôleur exécutant un RTOS, avec un ISR (Interrupt Service Routine) qui gère les interruptions UART (Serial port). Lorsque l'UART déclenche une interruption, l'ISR publie les caractères reçus dans la mémoire tampon circulaire. Dans une autre tâche RTOS (appelée packet_handler), je lis à partir de ce tampon circulaire et j'exécute une machine à états pour décoder le paquet. Un paquet valide a 64 octets comprenant tous les octets de trame.

L'UART fonctionne à 115 200 et un paquet arrive toutes les 10 ms. Le packet_handler s'exécute toutes les 10 ms. Cependant, ce gestionnaire peut parfois être retardé par le planificateur en raison d'une autre tâche de priorité plus élevée en cours d'exécution.

Si j'utilise une mémoire tampon circulaire arbitrairement grande, il n'y a pas de suppression de paquets. Mais comment déterminer la taille optimale du tampon circulaire dans ce cas? Au moins théoriquement. Comment cette décision de taille de tampon est-elle prise en pratique?

Actuellement, je détecte un dépassement de la mémoire tampon grâce à certaines fonctions d'instrumentation, puis j'augmente la taille de la mémoire tampon pour réduire la perte de paquets.


3 commentaires

Votre gestionnaire de paquets doit avoir un temps de cycle <10 ms. Rappelez-vous que les 10 ms sur le processeur récepteur ne sont pas 10 ms sur le processeur émetteur et qu'ils s'éloignent donc asymptotiquement les uns des autres (en supposant qu'il n'y ait pas d'autre mécanisme de synchronisation). Si votre packet_handler ne traite qu'un seul paquet et que votre émetteur fonctionne légèrement plus vite que le récepteur, vous serez toujours à court de mémoire, quelle que soit la taille du tampon. C'est juste Shannon déguisé :)


D'accord. Je peux changer la périodicité de packet_handler après avoir pris en compte la dérive d'horloge maximale de l'expéditeur par rapport au récepteur. En outre, je réduirai un peu plus la période de packet_handler afin que le récepteur fonctionne toujours à un rythme légèrement plus rapide que celui de l'émetteur. Le problème est-il maintenant résoluble en utilisant un tampon fini?


Le tampon en question est-il un tampon de paquets ou un tampon de caractères?


4 Réponses :


0
votes

Je calculerais de cette manière:

64 octets reçus juste savoir
64 octets toujours dans le tampon en anneau
+ 100% pour être économisé
===================
Tampon de 256 octets

Mais ce n'est qu'une supposition. Vous avez dû faire le pire des cas avec votre tampon, puis dépenser + 100% pour être sauvé.


2 commentaires

Deux emplacements (de 64 octets chacun) dans le tampon suffiraient si le packet_handler est très ponctuel et apparaît exactement à des intervalles de 10 ms (car il y a un paquet toutes les 10 ms). Mais le problème ici est que le packet_handler est préempté en raison d'autres tâches hautement prioritaires.


Je suppose que je perds des paquets en raison de la gigue au moment où packet_handler est planifié.



1
votes

Vous ne serez jamais en sécurité, car vous avez affaire à un processus stochastique (selon votre explication). Répondre à votre question: Vous aurez besoin d'un tampon infini juste au cas où la tâche consommateur serait prête pendant des secondes infinies. Vous devrez donc changer quelque chose dans votre approche initiale:

  • Augmentez la priorité du consommateur, afin d'assurer l'exécution de 10 ms (la plus petite approche de tampon, mais cela peut ne pas être possible).
  • Essayez d'obtenir une meilleure caractérisation de votre modèle, afin de prédire l'intervalle de temps maximal pendant lequel la tâche consommateur ne sera pas exécutée (faites en sorte que votre système soit aussi prévisible que possible).
  • Perdez des paquets avec une taille de tampon aléatoire (cela peut ne pas être sûr)

9 commentaires

D'accord. Donc, si vous connaissez le pire moment d'exécution de toutes les tâches du système et leurs priorités, ces informations sont-elles suffisantes pour calculer la taille de tampon requise? Il n'y a pas de travaux sporadiques (imprévisibles) dans le système.


Oui, mais la taille du tampon peut être infinie. Le consommateur doit également pouvoir lire plus d'un colis par appel.


En supposant que toutes les autres tâches ont une priorité plus élevée que packet_handler et que leur temps d'exécution dans le pire des cas est connu, je peux calculer l'intervalle de temps maximal pour lequel packet_handler sera bloqué. De plus, je peux modifier mon packet_handler pour traiter autant de paquets qu'il y en a dans le tampon en une seule invocation. Compte tenu de ces deux conditions (temps de blocage maximum, et packet_handler pouvant traiter plusieurs paquets en un seul appel), peut-il y avoir une solution avec une taille de tampon finie?


En supposant que vous avez calculé le pire des cas et que ce soit quelque chose comme: PPCPPCPPCPP (étant C le consommateur et P le producteur), vous avez toujours besoin d'un tampon infini: [P (64B) C (0B) P (64B) P (128B) C (64B) P (128B) P (192B) C (128B) P (192B) P (256B) C (192B) P (256B) P (320B)] (le producteur est + 64B et le consommateur est -64B) , le consommateur doit donc lire autant d'emballages que la relation entre le consommateur et le producteur.


Je veux dire, si le producteur est deux fois plus rapide, le consommateur devra lire presque deux fois le nombre de paquets: [P (64B) C (0B) P (64B) P (128B) C (0B) P (64B) P (128B) C (0B) P (64B) P (128B) C (0B) P (64B) P (128B)] (le producteur est + 64B Bande le consommateur est -128B). Ici, un tampon de 128B suffit.


Pour mettre les choses en pratique - J'ai deux tâches périodiques T1 et T2 autres que la tâche packet_handler (T3). T1 est programmé pour se produire périodiquement toutes les 50 ms et a une période d'exécution dans le pire des cas de 10 ms. T2 est programmé pour se produire périodiquement toutes les 100 ms et a une période d'exécution dans le pire des cas de 10 ms.


Maintenant, les tâches T1, T2 et T3 (toutes les tâches du système) ont une hyperpériode (l'intervalle de temps après lequel le modèle d'ordonnancement se répète) de 100 ms (multiplicateur le moins commun de période de T1, T2 et T3). Ainsi, les tâches T1 et T2 seront planifiées ensemble à des intervalles de temps tels que 0 ms, 100 ms, 200 ms, etc. .


Ainsi, au moment où T3 est planifié, il y a déjà deux paquets complets reçus et il devrait y avoir un espace tampon pour un autre paquet. Donc, un espace tampon pour 4 paquets est assez sûr je suppose. Est-ce que je vais mal quelque part ici?


Si votre tâche avec un délai de 10 ms peut être retardée de plus de 10 ms, vos priorités de tâche doivent peut-être être reconsidérées. La priorité n'est pas une question d'importance, mais de durée d'exécution et de délais. Mais c'est peut-être une question différente.



0
votes

Bien que toutes les réponses ci-dessus soient correctes et éclairent le problème, cette page résume tous les facteurs à prendre en compte lors du choix de la taille d'un tampon en anneau.

Certains modèles de mise en file d'attente peuvent être utilisés pour analyser théoriquement le problème actuel et trouver la taille appropriée du tampon en anneau.

Une approche plus pragmatique consiste à commencer avec un tampon volumineux, puis à déterminer la taille maximale du tampon utilisé dans un cas de test réel (ce processus s'appelle le filigrane) et à utiliser ce chiffre dans le code final.


0 commentaires

0
votes

Il s'agit simplement de déterminer le délai maximum possible - la somme des temps d'exécution de toutes les tâches de priorité plus élevée pouvant être exécutées - et de le diviser par l'intervalle d'arrivée des paquets.

Cela peut ne pas être simple, mais peut être simplifié en accordant une priorité plus élevée aux tâches les plus déterministes et en déplaçant les tâches moins déterministes et plus longues vers des priorités inférieures selon des principes monotones de taux Tâches qui s'exécutent fréquemment pendant une courte période, mais de manière sporadique courir plus longtemps sont des candidats pour être divisés en deux tâches (et en files d'attente supplémentaires) pour décharger l'exécution plus longue vers une priorité inférieure.


0 commentaires