IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Thread et occupation CPU


Sujet :

C++Builder

  1. #1
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut Thread et occupation CPU
    Bonjour,

    Je dois poller pour des lectures un port de communication dans un thread séparé. Dans la fonction Execute() du thread, si je me contente de lire byte par byte le flux entrant, ça marche correctement.
    En revanche, si je fais un test préliminaire pour savoir si des données sont disponibles sur le port - comme le bon sens m'y invite - ça marche aussi mais le CPU est à 100%.

    Voici un extrait du code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    void __fastcall USB_RX_THREAD::Execute()
    {
    DWORD BytesReturned, BytesSent, EventWord;
    while (!Terminated) {
            FT_GetStatus(ftHandle, &BytesReceived, &BytesSent, &EventWord);
            //if (BytesReceived) {
                    FT_Read(ftHandle, &RxData, 1, &BytesReturned);
                    Synchronize(ProcessRxData);
            //}
     
    }
    Dans le code ci-dessus, le test préliminaire est mis en commentaires.
    Il y a sans doute qqch qui cloche dans mon code... Une idée? Merci!

  2. #2
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    ton code doit pas compiler il manque }
    sinon tu viens de créer un deamon il va tout le temps faire le test de ta connexion.

  3. #3
    Membre actif Avatar de cfdev
    Homme Profil pro
    Passionné
    Inscrit en
    Octobre 2004
    Messages
    220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Passionné

    Informations forums :
    Inscription : Octobre 2004
    Messages : 220
    Points : 210
    Points
    210
    Par défaut
    lut,
    Ton code me dis quelque chose
    j'avais le même pour dialoguer avec le FDTI232BM
    seul pb, c'est que j'ai fait exactement la meme chose que toi et pareil 100% pross meme dans un thread!
    Obliger de faire ca avec un Timer.
    Si jamais tu trouves la soluce ce serai sympa de la patager.



    Bon courage.
    ++
    mcercle facturation - Logiciel de facturation Win/Mac/Linux

  4. #4
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut
    Salut VirtuA,

    Bien vu, ce sont des fonctions de l'API FTDI
    J'ai provisoirement réglè le problème en insérant un Sleep() dans la boucle. Il y a eu un post ici-même à ce sujet:
    http://www.developpez.net/forums/vie...1b34625eca5fa7
    Le code est à présent
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    while (!Terminated) {
            FT_GetStatus(ftHandle, &BytesReceived, &BytesSent, &EventWord);
            if (BytesReceived) {
                    FT_Read(ftHandle, &RxData, 1, &BytesReturned);
                    Synchronize(ProcessRxData);
            }
            else
                    Sleep(5);
    }
    Evidemment cette méthode suppose que tu as une idée du débit sur la ligne. Pour ma part je sais que je reçois 200 bytes de statuts par seconde que je dois traiter au plus vite, d'où les 5 ms pour le sleep. Je ne suis pas amoureux de cette solution mais bon ça marche - et sous Windows je m'habitue à ne pas trop en demander.
    D'ailleurs je manque d'infos sur le traitement multi-tâches de Windows. J'ai une doc qui annonce que Windows accorde 20ms d'exécution à chaque process. Si le process est multi-threads, ces 20ms sont partagées entre les threads. Dans quelle mesure? Enfin pour ma part j'ai testé les événements signalés par la souris, et je mesure précisément 1 événement souris par 10ms. Quelqu'un a-t-il des infos plus précises sur le cadencement sous Windows?

  5. #5
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2002
    Messages : 84
    Points : 109
    Points
    109
    Par défaut
    Bonjour,

    La libération de la charge CPU vient de la fonction Synchronize.

    Quand tu enléves les commentaires, tu passes tout le temps dans le Synchronize.
    Dans le cas contraire, tu boucles jusqu'a valider la condition, donc tu prends 100% de CPU.

    Soit tu ajoutes une pause (effectivement ici le Sleep(1)), soit essaye d'appeler Synchronize ou Application->ProcessMessages().

    Attention toutefois au temps de pooling.
    Dans les 2 cas c'est assez incertain.

    Le Sleep est fonction du quantum de windows ( 1ms = 10ms )
    Application->ProcessMessages/Synchronize dépend du traitement effectué ...
    A ta disposition
    Christophe MERLIER

  6. #6
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut
    Merci! Je commence à comprendre l'esprit je crois. Tant qu'il n'a pas exécuté un Synchronise(), le thread reste actif.
    Je devrais pouvoir écrire (?) à la place du sleep():

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    while (!Terminated) { 
            FT_GetStatus(ftHandle, &BytesReceived, &BytesSent, &EventWord); 
            if (BytesReceived) { 
                    FT_Read(ftHandle, &RxData, 1, &BytesReturned); 
                    Synchronize(ProcessRxData); 
            } 
            else 
                    Synchronize(ReturnToMain);
    }
    où la fonction ReturnToMain() ne serait que l'instruction return() ou une fonction vide.

  7. #7
    Membre régulier
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    84
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations forums :
    Inscription : Mai 2002
    Messages : 84
    Points : 109
    Points
    109
    Par défaut
    Dans l'absolue oui.
    Je vois que tu fais une pause de 5ms.
    Le quantum au Ring3 (niveau utilisateur est égal à 10ms.
    Donc entre 1 et 10ms, la pause effective est de 10ms, entre 11 et 20ms, la pause effective est de 20ms, etc ...

    Le probléme du Synchronize est que le temps laissé au CPU n'est pas en soit mesurable.
    Si tu bouges la souris comme un fous, tu vas capter le processeur et donc augmenter le temps de traitement (ceci est un exemple bien évidement).

    Normalement la captation au niveau binaire (ou caractére) doit se faire dans un driver. Seul le "completion code" est laissé à un thread de plus haut niveau. (ceci est valable pour le pooling).

    Une autre solution est de voir s'il est possible de se mettre en attente d'un événement (event) ou signal. Ainsi le Thread se met en attente d'information, lorsque celle ci est disponible l'evenement est déclenché (ou le signal signalé ) et le thread se débloque pour traiter les datas.

    Exemple de code sur demande. Il faut bien sur que le systéme puisse supporter ces modes de fonctionnement.
    A ta disposition
    Christophe MERLIER

  8. #8
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut
    Mischt! J'ai essayé le coup du ReturnToMain() vide, et la charge CPU est à 100%. Je ne comprends décidément pas la logique du thread: quand (à quelle condition) passe-t-il la main?
    Merci pour la suggestion du thread déclenché par l'événement, mais je ne vois pas comment faire à priori. Aurais-tu un exemple simple montrant comment cette technique est mise en oeuvre?

  9. #9
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    bonjour,
    pour eviter ce problème de polling il faut utiliser les notification les API de
    FTDI les proposent

    un exemple de code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    // demande de notification a placer dans le constructeur du Thread par exemple
     
    FT_HANDLE ftHandle; // handle of an open deviceFT_STATUS ftStatus;
    HANDLE hEvent;
    DWORD EventMask;
    hEvent = CreateEvent( NULL, false, // auto-reset event false, // non-signalled state “” );
    EventMask = FT_EVENT_RXCHAR | FT_EVENT_MODEM_STATUS;
    ftStatus = FT_SetEventNotification(ftHandle,EventMask,hEvent);
     
    /////////////////////////////////////////////////////////////////////////////
    // code Execute de ta classe TThread
    while (!Terminated) { 
     
    WaitForSingleObject(hEvent,INFINITE);
    DWORD EventDWord;
    DWORD RxBytes;
    DWORD TxBytes;
    FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord);
    if (RxBytes > 0) 
     { // call FT_Read() to get received data from device }
    FT_Read(ftHandle, &RxData, 1, &BytesReturned); 
     Synchronize(ProcessRxData); 
     }
    }
    de cette manière ton thread ne consomme uniquement du temps processeur lors du traitement de l'information
    cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  10. #10
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut
    Ca c'est fort!
    Merci DjmSoftware!

    J'ai testé - avec un certain retard - la méthode qui bloque le thread dans l'attente d'un événement. Ca fonctionne, mais le PC n'arrive pas à suivre la cadence imposée par le flux en réception - la méthode ne semble pas adaptée au 'temps réel' (je lis et traite chaque byte à mesure qu'il est dispo).
    A noter que la méthode précédente par polling des status et attente (sleep) ne rencontre aucun problème de cadence.

  11. #11
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    bonjour,
    c'est un fonctionnement parfaitement normal
    en effet lors que l'Event est signalé dans le code on ne contrôle pas le nombre de caractères qui se trouve dans le Buffer (paramètre RxBytes)

    si par exemple 15 caractères sont déposés dans le Buffer, et que l'on lise uniquement 1 caractères à la fois, la prochaine notification aura lieu lorsque le 16 em caractère sera déposé dans le buffer
    --> perte de 14 éléments

    en faisant un polling on force la lecture du buffer chaque fois que le thread est activé par l'OS

    le solution conciste en la lecture de (RxBytes* éléments) en lieu et place d'un élément à la fois

    d'autre part dans le code on peut supprimer FT_EVENT_MODEM_STATUS de l'EventMask

    Cordialement
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  12. #12
    Membre à l'essai
    Inscrit en
    Avril 2005
    Messages
    22
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 22
    Points : 22
    Points
    22
    Par défaut
    Merci pour ces précisions et encore merci pour ton intervention.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. occupation cpu par coeur
    Par htristra dans le forum C++
    Réponses: 0
    Dernier message: 21/01/2008, 23h59
  2. problème bizarre d'occupation CPU
    Par bmw13fr dans le forum Autres éditeurs
    Réponses: 0
    Dernier message: 23/11/2007, 17h07
  3. Occupation CPU très élevée
    Par sebhm dans le forum Administration système
    Réponses: 10
    Dernier message: 07/06/2006, 16h12
  4. Réponses: 1
    Dernier message: 12/04/2005, 20h36
  5. Connaître le taux d'occupation CPU
    Par Thom@s dans le forum API, COM et SDKs
    Réponses: 5
    Dernier message: 12/11/2003, 23h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo