Comment puis-je m'assurer que mon programme fonctionne du début à la fin sans interruption?

StackOverflow https://stackoverflow.com/questions/1215713

  •  06-07-2019
  •  | 
  •  

Question

J'essaie de programmer le code temporel à l'aide de RDTSC (aucun autre logiciel de profilage que j'ai essayé ne permet de chronométrer la résolution dont j'ai besoin) sous Ubuntu 8.10. Cependant, je continue à avoir des valeurs aberrantes dues à des commutateurs de tâches et des interruptions de déclenchement, qui rendent mes statistiques non valides.

Étant donné que mon programme s'exécute en quelques millisecondes, est-il possible de désactiver toutes les interruptions (ce qui aurait pour effet de désactiver les commutateurs de tâches) dans mon environnement? Ou dois-je utiliser un système d'exploitation qui me donne plus de puissance? Aurais-je intérêt à utiliser mon propre noyau de système d'exploitation pour exécuter ce code de synchronisation? J'essaie de prouver les performances optimales / optimales d'un algorithme, il doit donc être totalement solide avec le timing.

Le code que j'utilise actuellement est le suivant:

inline uint64_t rdtsc()
{
    uint64_t ret;
    asm volatile("rdtsc" : "=A" (ret));
    return ret;
}

void test(int readable_out, uint32_t start, uint32_t end, uint32_t (*fn)(uint32_t, uint32_t))
{
    int i;
    for(i = 0; i <= 100; i++)
    {
        uint64_t clock1 = rdtsc();
        uint32_t ans = fn(start, end);
        uint64_t clock2 = rdtsc();

        uint64_t diff = clock2 - clock1;

        if(readable_out)
            printf("[%3d]\t\t%u [%llu]\n", i, ans, diff);
        else
            printf("%llu\n", diff);
    }
}

Des points supplémentaires pour ceux qui remarquent que je ne gère pas correctement les débordements dans ce code. A ce stade, j'essaie simplement d'obtenir une sortie cohérente sans sauts brusques en raison de la perte de mon programme.

La valeur intéressante de mon programme est de -20.

Donc, pour récapituler, est-il possible pour moi d'exécuter ce code sans interruption du système d'exploitation? Ou vais-je avoir besoin de l'exécuter sur du matériel nu sous ring0 pour pouvoir désactiver les IRQ et la planification? Merci d'avance!

Était-ce utile?

La solution

Si vous appelez nanosleep () pour dormir pendant une seconde ou plus immédiatement avant chaque itération du test, vous devriez obtenir un & "frais &"; tranche de temps pour chaque test. Si vous compilez votre noyau avec des interruptions de minuterie de 100 Hz et que votre fonction chronométrée se termine en moins de 10 ms, vous devriez pouvoir éviter que des interruptions de minuterie ne vous frappent de cette façon.

Pour minimiser les autres interruptions, déconfigurez tous les périphériques réseau, configurez votre système sans permutation et assurez-vous qu'il est sinon inactif.

Autres conseils

Tricky. Je ne pense pas que vous puissiez éteindre le système d'exploitation et garantir un planning strict.

Je voudrais renverser la situation: compte tenu du fait qu’elle fonctionne très vite, exécutez-la plusieurs fois pour collecter une distribution des résultats. Étant donné qu’Ubuntu Linux standard n’est pas un système d’exploitation temps réel au sens étroit, tous les algorithmes alternatifs s’exécuteraient dans la même configuration - et vous pourrez ensuite comparer vos distributions (en utilisant n’importe quoi, des statistiques résumées aux quantiles à qqplots). Vous pouvez faire cette comparaison avec Python, ou R, ou Octave, ... selon votre préférence.

Vous pourrez peut-être utiliser FreeDOS , car il s'agit d'un système d'exploitation à processus unique .

Voici le texte pertinent du deuxième lien:

  

L'implémentation DOS de Microsoft, qui est le   norme facto pour les systèmes DOS dans le   monde x86, est un utilisateur unique,   système d'exploitation mono-tâche. Il   fournit un accès brut au matériel, et   seule une couche minimale pour les API de système d'exploitation pour   des choses comme le fichier I / O. C'est un   bonne chose quand il s'agit d'intégrer   systèmes, parce que vous avez souvent juste besoin   faire quelque chose sans un   système d'exploitation à votre façon.

     

DOS n’a (nativement) aucun concept de   fils et pas de concept de multiple,   processus en cours. Application   logiciel fait des appels système via le   utilisation d'une interface d'interruption, appelant   diverses interruptions matérielles à gérer   des choses comme la vidéo et l'audio, et   appeler des interruptions logicielles pour gérer   diverses choses comme lire un   répertoire, l'exécution d'un fichier, etc.   à venir.

Bien sûr, vous obtiendrez probablement les meilleures performances en démarrant FreeDOS sur du matériel réel, pas sur un émulateur.

Je n'ai pas réellement utilisé FreeDOS, mais je suppose que puisque votre programme semble être en C standard, vous pourrez utiliser le compilateur standard utilisé pour FreeDOS.

Si votre programme s'exécute en millisecondes et sous Linux, Assurez-vous que la fréquence de votre minuterie (sous Linux) est réglée sur 100Hz (et non sur 1000Hz). (cd / usr / src / linux; make menuconfig, et regardez & "Type de processeur et ses fonctionnalités &"; - > & "; fréquence du minuteur &";) De cette façon, votre processeur sera interrompu toutes les 10 ms.

De plus, considérez que la tranche de temps du processeur par défaut sous Linux est de 100 ms. Ainsi, avec un niveau agréable de -20, vous ne serez pas désorganisé si vous ne travaillez pas pendant quelques millisecondes.

De plus, vous faites une boucle 101 fois sur fn (). S'il vous plaît, envisagez de donner fn () pour ne pas avoir à calibrer votre système correctement.

Créez des statistiques (moyenne + stddev) au lieu d’imprimer trop de fois (cela consommerait votre tranche de temps planifiée, et le terminal finira par obtenir une planification, etc ... évitez cela).

exemple de code de référence RDTSC

Vous pouvez utiliser chrt -f 99 ./test pour exécuter ./test avec la priorité maximale en temps réel. Au moins, il ne sera pas interrompu par d'autres processus de l'espace utilisateur.

En outre, l'installation du package linux-rt installe un noyau en temps réel, ce qui vous permet de mieux contrôler la priorité du gestionnaire d'interruptions via les interruptions threadées.

Si vous vous exécutez en tant que root, vous pouvez appeler sched_setscheduler () et vous attribuer une priorité en temps réel. Consultez la documentation.

Peut-être existe-t-il un moyen de désactiver la planification préemptive sur Linux, mais cela n’est peut-être pas nécessaire. Vous pouvez potentiellement utiliser les informations de /proc/<pid>/schedstat ou de tout autre objet de /proc pour détecter le moment où vous avez été préempté, et ignorer ces échantillons de minutage.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top