2016-11-09 5 views
0

J'écris un programme qui doit boucler régulièrement 100 microsecondes pour une boucle. J'ai trouvé la boucle à régulièrement dans un temps fixe. Mais je trouve un problème quand le temps de bouclage est trop petit.C++ effectuer avec précision une action dans "tous" 100 microsecondes sans pause

Le code de démonstration ci-dessous (code non complet) est à:

  1. Incrémenter la microseconde count tous les 100. Afficher le count toutes les secondes.

Le résultat attendu est d'environ 10000 toutes les secondes. Mais le résultat montre environ quatre mille par seconde.

void f2(int input) 
{ 
    auto start = std::chrono::system_clock::now(); 
    auto displayStart = std::chrono::system_clock::now(); 
    while(true){ //keep looping quickly 
     auto now = std::chrono::system_clock::now(); 
     auto interval = std::chrono::duration_cast<std::chrono::microseconds>(now - start); 
     if (interval.count() > input){ //if 100 microsecond do 
      count++; 
      start = std::chrono::system_clock::now(); 
     } 

     auto displayNow = std::chrono::system_clock::now(); 
     auto displayInterval = std::chrono::duration_cast<std::chrono::microseconds>(displayNow - displayStart); 
     if (displayInterval.count() > 1000000){ //if 1 second do 
     std::cout<< "1 second count: "<<count<<std::endl; 
     count=0; 
     displayStart = std::chrono::system_clock::now(); 

     } 

    } 

} 

Après que je pense que la planification du processeur peut être le problème pour cette. J'ai vérifié que le programme fonctionne normalement dans chaque boucle. Chaque itération prend environ 100 microsecondes ce qui est précis. Mais un problème peut survenir lorsque le programme/thread est en pause et attendre le replanification du CPU. Par exemple, et permet d'agrandir la valeur pour une illustration plus claire. Par exemple, et

Le fil a fait une pause pendant 1 seconde. Normalement, il va augmenter de 10000 fois. Mais maintenant, pour la prochaine itération, elle vérifie pendant> 100 microsecondes, donc compte ++ et le compteur est réinitialisé quand 1 seconde est passée. Pour ce cas, le compte n'a été incrémenté que pour 1.

Avec le code suivant que j'ai modifié, je peux terminer 10000 count++ en une seconde. Mais le problème est que ces 10000 comptes ne sont pas répartis uniformément en une seconde. Parce que ce n'est que le programme de démonstration pour les tests. L'action que je veux réellement est de faire une action précise toutes les 100 microsecondes. Mais en raison de la pause du fil, je ne trouve toujours pas la solution pour résoudre ce problème.

void f2(int input) 
{ 
    auto start = std::chrono::system_clock::now(); 
    auto displayStart = std::chrono::system_clock::now(); 
    while(true){ //keep looping quickly 
     auto now = std::chrono::system_clock::now(); 
     auto interval = std::chrono::duration_cast<std::chrono::microseconds>(now - start); 
     if (interval.count() > input){ //if 100 microsecond do 
      for(int i=0;i<interval.count()/input;i++){ //modified part 
       count++; 
      } 
      start = std::chrono::system_clock::now(); 

     } 


     auto displayNow = std::chrono::system_clock::now(); 
     auto displayInterval = std::chrono::duration_cast<std::chrono::microseconds>(displayNow - displayStart); 
     if (displayInterval.count() > 1000000){ //if 1 second do 
     std::cout<< "1 second count: "<<count<<std::endl; 
     count=0; 
     displayStart = std::chrono::system_clock::now(); 


     } 


    } 


} 

Y a-t-il un moyen quelconque: par ex. rendre le processus sans pause. Gardez-le dans le CPU (pas si possible) pour que l'action de comptage dans le programme de démonstration fonctionne toutes les 100 microsecondes?

Merci beaucoup

+12

Pour ce type de précision, vous avez besoin d'un [système d'exploitation en temps réel] (https://en.wikipedia.org/wiki/Real-time_operating_system). L'OS à usage général ne vous permettra pas de réaliser ceci - votre programme peut être interrompu à tout moment par un conducteur, disons. Quoi qu'il en soit, quel genre de problème tentez-vous de résoudre, à votre avis, nécessite des performances de l'ordre de 10 000 FPS? –

+0

Merci d'avoir répondu. Je dois utiliser Linux pour le programme. J'écris un commutateur logiciel qui a besoin de * 0.08 pour chaque 100 microsecondes pour le compteur pour le calcul de certaines données à d'autres fins. (calcul des données de congestion pour chaque port) –

+0

Vous devrez trouver un autre moyen de calculer ces données, j'en ai peur. Si vous expliquez le problème que vous tentez de résoudre, plutôt que la solution que vous avez essayée (que vous ne parvenez pas à utiliser), vous pourriez obtenir de l'aide. Voir aussi: [Problème XY] (http://xyproblem.info/) –

Répondre

0

seaux Have N, où N est assez grand que le retard de programmation ne sera pas un problème.

Notez la dernière fois que votre code de désintégration a été exécuté. Lorsqu'un nouveau paquet "s'éteint", placez-le dans un compartiment en fonction de la dernière fois que votre code de désintégration est passé (si moins de 100 ms, seau 0, si 200 ms, seau 1, etc.).

Lorsque votre code de désintégration s'exécute, calculez la valeur actuelle après la décomposition correcte et mettez à jour l'horodatage.

Notez que la contention (la mise à jour du thread et la dégradation du thread) reste un problème. Vous pouvez corriger cela dans une certaine mesure avec un double ou triple buffering des compteurs, des drapeaux atomiques et des pointeurs, et des boucles occupées dans le code non sensible aux performances (disons, le code de désintégration).

Alternativement, au lieu d'enregistrer des comptes, enregistrez les horodatages. Consommez le tampon des horodatages, en faisant de la désintégration à ce moment-là. Problèmes similaires impliquant la taille du tampon et plusieurs threads restent, avec des solutions similaires.

Vous pouvez également effectuer la décomposition mathématique dans le code qui effectue le comptage.