Page 1 sur 3

A la conquête du delay...

Publié : mer. 25/juin/2008 23:27
par Ollivier
Désolé de vous souler comme ça mais j'avais besoin de la poser cette question !

Personnellement, elle me semble importante et pourtant je la maîtrise mal.

C'est en manipulant successivement sur 4 bécanes différentes que j'ai compris ma douleur... En effet, je peux programmer sur un gros PC des codes qui peuvent m'éteindre un portable plus faiblard (4 bips généraux + 1 coupure nette à la clé sur le mien, plus faiblard)

Dobro parlait de chaleur à cause des processeurs. Avec la souflette stressante (pppwwwwuuui...) de mon portable, je maîtrisais correctement l'intensité flux avec mes delay. C'est comme avec une voiture particulière : on se fait à l'embrayage !

Or, en programmant sur d'autres bécanes, dès que je réimporte ma clef USB sur le vieux faiblard (mais utile) de PC, je suis obligé de modifier le Delay ! Sinon catastrophe au bout 5 minutes.

Comment peut-on réellement savoir, si on est en train faire chauffer son PC : y'a-t-il un lien vers une fonction standard pour éviter ce massacre ?

Merci

Ollivier

Publié : jeu. 26/juin/2008 0:07
par Ar-S
Je plussois avec Ollivier à cette question profonde. 8)

Publié : jeu. 26/juin/2008 0:22
par Octavius
J'ai trouvé ceci sur le forum anglais : >> Sujet intéressant ! <<

Il est apparemment possible de faire une procédure qui récupère des informations sur le système grâce à l'API Windows.

Peut-être devrais-tu essayer de moduler ton Delay() en fonction de la puissance du processeur ? De cette façon, tu n'aurais pas besoin de le régler manuellement pour chaque PC.

Publié : jeu. 26/juin/2008 8:27
par djes
On a rarement besoin d'avoir un programme qui tourne à 100%. Si tu utilises des fenêtres, avec le waitwindowevent(), tu rends la main au système régulièrement ; et si tu utilises directx, avec flipbuffers() ton programme une fois sa tâche accomplie "attends" la synchro suivante. Un delay() n'est donc jamais utile et ne devrait pas être utilisé dans ces cas-là.

Publié : jeu. 26/juin/2008 13:30
par Jacobus
Perso je m'en sers dans les threads incluant des boucles For ... next et qui actualisent un affichage graphique. Ca permet de soulager le(s) processeur(s) qui ainsi ne sera pas monopolisé à 100%
Sur un double coeur un delay(1) peut suffire mais sinon un delay(10) devrait passer partout. Jusqu'à maintenant c'est la meilleure solution que j'ai trouvé pour les tâches répétitives sans avoir de plantage.

Publié : jeu. 26/juin/2008 13:37
par djes
Jacobus a écrit :Perso je m'en sers dans les threads incluant des boucles For ... next et qui actualisent un affichage graphique. Ca permet de soulager le(s) processeur(s) qui ainsi ne sera pas monopolisé à 100%
Sur un double coeur un delay(1) peut suffire mais sinon un delay(10) devrait passer partout. Jusqu'à maintenant c'est la meilleure solution que j'ai trouvé pour les tâches répétitives sans avoir de plantage.
Tu peux nous donner un exemple?

Publié : jeu. 26/juin/2008 15:00
par Jacobus
Voici un extrait d'une procedure servant à ajouter des données dans des fichers à des moments donnés, en fonction de différents paramètres, etc... (extrait non fonctionnel ainsi, à ne pas tester donc) et ceci devant traiter plusieurs milliers ou dizaines de milliers de fichiers.

Code : Tout sélectionner

n = GetGadgetState(#LISTICON)
 Count = CountGadgetItems(#LISTICON)-1
 ValMax = Count 
    For n = 0 To Count
    Filename$ = GetGadgetItemText(#LISTICON, n, 0)
         For np = 1 To nbdata       
           If OpenFile(#File,Filename$)
            Statusfile$ = "Succes"
            filesize = Lof(#File) 
            AddFileData(filesize)    
              e = Eof(#File)
              If e = 0
                 AddGadgetItem(#EDITORLOG, -1,FormatDate("%hh:%ii:%ss - ", Date())+" - Erreur / fichier : "+GetFilePart(Filename$))
                 AddGadgetItem(#EDITORLOG, -1,"---Emplacement = "+Filename$)
                 SendMessage_(GadgetID(#EDITORLOG),#EM_SCROLL,#SB_LINEDOWN,#Null)
                 Statusfile$ = "Echec"
                 Break 
              EndIf   
              CloseFile(#File)
           Else 
            AddGadgetItem(#EDITORLOG, -1,"- Echec à l'ouverture -> "+Filename$)
            SendMessage_(GadgetID(#EDITORLOG),#EM_SCROLL,#SB_LINEDOWN,#Null)
            Statusfile$ = "Echec"
            Break 
           EndIf
          Delay(1) ; <<< ici
         Next np   
        pourcentage.f = n/Count*100 
        SetGadgetState(#Progression,pourcentage)         
        If Statusfile$ = "Succes"  
          FullPathName$ = GetPathPart(Filename$)
          Renommer = RenameFile(Filename$, FullPathName$+Input$) 
           If Renommer = 0 
             AddGadgetItem(#EDITORLOG, -1,"-ERREUR - Impossible de renommer : "+GetFilePart(Filename$))
             SendMessage_(GadgetID(#EDITORLOG),#EM_SCROLL,#SB_LINEDOWN,#Null)
           EndIf
        EndIf         
      EndIf   
   Delay(10) ;<<< et là
  Next  
j'appelle cette fonction dans un thread qui va pouvoir travailler en arrière plan sans surcharger le cpu. Sur 1000 ou 2000 fichiers par traitement, l'absence de delay() ne se fera pas sentir car la tâche est rapide, au delà par contre c'est le plantage assuré. le proc se gonfle à 99% voire 100% et Blam! Depuis j'utilise cette méthode dans mes applications devant gérer des threads de ce type pour un fonctionnement quasi insensible pour le cpu (dans les 50% de charge en plein travail)

J'avoue que si tu as une autre méthode je suis intéressé...

Publié : jeu. 26/juin/2008 15:26
par djes
Là ce n'est pas tant attendre le CPU que d'attendre le système d'exploitation. Apparemment ton code crée et gère des gadgets et réalise des entrées/sorties fichier; tout ça c'est le boulot de l'OS qui prend tout en charge et rend la main tout de suite, au lieu de terminer les tâches les unes après les autres. Du coup la file d'attente grandit jusqu'à saturation...

Le delay fait l'affaire "en général", mais sur un système (ou un lecteur) plus lent il ne fonctionnerait pas, et sur un système plus rapide il ralentirait les opérations :(

Je ne suis malheureusement pas un spécialiste des opérations système, je ne sais pas s'il existe un truc pour attendre qu'un gadget soit créé ou pour vérifier qu'une opération sur un fichier soit finie, de façon sûre; peut-être dans ce cas un événement à intercepter pourrait-il remplacer ce delay(). Ce qui est sûr, c'est qu'il faut éviter de tout faire en parallèle car windows ne se débrouille pas très bien dans ces cas-là. Y'a ptet un truc à faire avec ça : http://technet.microsoft.com/en-us/sysi ... 63891.aspx

Publié : jeu. 26/juin/2008 19:05
par comtois
Fred a écrit :Put the delay() only if it doesn't have any events left in the queue.
Il faut mettre un delay() quand il n'y a plus d'évènement en attente

Ce qui pourrait donner

Code : Tout sélectionner

Event = WindowEvent()

Select Event

  Case 0
    Delay(10)
  
  ...  

Publié : jeu. 26/juin/2008 22:18
par Ollivier
@Jacobus : Si j'ai une autre méthode ??? Vue la qualité de ce code qui me fumerait mon CPU, je n'en ai pas qu'une :

1) La ListIcon c'est juste pour la visu, sûrement pas pour un calcul en arrière-plan. Donc transfert ListIcon >> Tableau de chaînes

2) Prohibe les chaînes dans une tâche en arrière-plan : anticipe l'ouverture des fichiers pour limiter l'accès aux chaînes.

3) Status$ = "succes" ne vaut pas Status | 1 (V 4.10 et antérieures) ou encore Status = #True (V 4.20 et supérieures)
(http://www.purebasic.fr/english/viewtopic.php?t=32427)

4) Pour le pourcentage de progression, la division c'est out dans une avancée constante (l'incrémentation de n est toujours 1) La division est faite au point de départ pour calculer la valeur différentielle. Dans ton thread ne doit apparaîttre alors qu'une simple addition.

Woilà, p... ça se voit que tu as une bonne bécane sous les mains. C'est le jour et la nuit. Je t'assure sincèrement que ton code ne fonctionnerait pas chez moi. Par contre, est-ce que toi tu ressents le besoin d'optimiser ton code ? Pas sûr si ton matériel encaisse bien. Mon but est d'éviter de perdre du temps à modifier des arguments de Delay() quand je passe d'une bécane puissance vers un ordi faiblard. ça n'est pas un 8088 à 4 MHz, je peux quand même charger une boucle mais les limites sont là (1GHz + ATI).

Aussi je ne reste pas dans dans le domaine du gadget, j'utilise indirectement les ressources du GPU (sprite et autres).

Merci pour les liens. Notamment l'API qu'Octavius a mis.
Ainsi que pour les conseils. J'ai fini par me résigner pour obtenir la température du CPU, faute de standard.

Pour me consoler, j'ai trouvé ce code de NetMaestro, pour déterminer l'utilisation du CPU. Je ne l'ai pas encore étudié.

http://www.purebasic.fr/english/viewtop ... pu+monitor

Ollivier

Publié : jeu. 26/juin/2008 23:11
par Jacobus
:lol: :lol: Tu tournes avec quoi? un poste à galènes.... appuies sur les pédales la dynamo est un peu faible.

Nan mais ce type de code ne m'a jamais rien grillé même si actuellement je travaille avec Intel Pentium Dual-core et Intel Pentium D, d'autres comme Intel Pentium III (Win Me), AMD Sempron 3000+ avec 512 Mo de Ram ou encore AMD Athlon 3500 supportent très bien la torture... J'ai quand même une préférence pour Intel, ça chauffe moins.

L'optimisation est toujours bonne à réaliser, il faut juste que cela colle avec le reste. J'utilise beaucoup les ListIcon car j'aime bien voir ce qu'il se passe quand j'en ai envie (caché/affiché).
Status = #True est le genre de détails qu'il faut que je modifie dans mes kilomètres de pages de code. Le problème est bien là, remettre à jour les anciennes versions en appliquant les nouveautés :roll:

Pour en revenir au sujet je crois que je vais refaire des tests sur de longues listes de fichiers pour voir le comportement des threads sans l'utilisation de Delay() en observant les agissements cpu. Comme le signale djes ce doit être le boulot de Windows. Il y a manifestement une mauvaise utilisation du Delay() qui a été faite et sûrement par plusieurs d'entre nous. Je suggère à Comtois de rajouter quelques détails la dessus dans la doc.

Publié : ven. 27/juin/2008 4:50
par Ollivier
( :D Un poste à galène !!!)

Ben, en fait je n'ai pas trop compris pourquoi Comtois a posté ça. Et je ne pense pas qu'il manque grand chose à ce sujet dans la doc.

Un marché va continuer à s'ouvrir dans les mois à venir avec des configurations CPU et GPU plus faiblardes que les bons processeurs actuels (Autour du gigahertz), c'est celui des petits PC de poche (avec une baisse nette de coùt). ça ne vas pas durer ad vitam. Peut-être un an.

Je ne dis pas que des gens vont se mettre à programmer en serrant les doigts. Mais par contre, des programmes très utiles peuvent être créés. Voire des jeux tout bêtement ! Or, d'une part, l'utilisation de DirectX peut s'avérer consommatrice de ressources, et d'autre part, si tel est le cas, avoir des repères sur la limite de charge de code dans une boucle principale peut éviter des désagréments lors d'un passage vers un autre PC moins performant.

ça ne dépend pas de la doc en fait. ça dépend de quelque tests à faire au démarrage d'un programme.

Ce qui m'a poussé à faire ce post est simple au fond.

>> La durée d'un Delay() sur le PC de bureau va être faible (5 ms par exemple).
>> Je migre sur mon poste à galène avec mon programme. La soufflette se met en route à fond tellement ça ne lui fait pas du bien.
>> J'augmente donc la durée du Delay() jusqu'à ce que la soufflette cesse son hystérie : 20 ms.
>> ça marche !
>> Je reviens sur le gros PC. Avec ce Delay, il saccade. Je dois donc redescendre la durée...

Woilà, c'est un petit programme qui gère ce problème là que j'aimerais faire.

Publié : ven. 27/juin/2008 19:58
par beauregard
décidément, cette commande nous torturera à jamais ! ;)
Ollivier a écrit :je n'ai pas trop compris pourquoi Comtois a posté ça. Et je ne pense pas qu'il manque grand chose à ce sujet dans la doc.
pour aider car il s'y connait un peu quand même, un peu beaucoup même.
Ollivier a écrit :Je ne dis pas que des gens vont se mettre à programmer en serrant les doigts. Mais par contre, des programmes très utiles peuvent être créés. Voire des jeux tout bêtement !
pour un jeu en 2D, cette commande est inutile( voir forum jeu( vers l'infini et peur basique :) )). Et pour un jeu en 3D, faut demander à comtois.

Publié : ven. 27/juin/2008 21:54
par Ollivier
Salut Beauregard,

En te relisant, plusieurs choses me viennent à l'esprit :

- La première : ça fait 7 ans que j'ai découvert Comtois. On ne se connait pas particulièrement, alors j'espère au moins savoir estimer les connaissances d'autrui, et en l'occurence les siennes ! Du moins, comme tout un chacun, celles qu'il est en mesure de partager ! D'où mon étonnement, quand je constate une réponse qui me semble inutile et venue de sa part (c'est bien la première fois).

- La seconde : Mille excuses :
Je n'ai pas pris soin, (depuis le temps : tout est à mon tort) de tester tes 2 jeux : peur basique et vers l'infini. Je n'ai fait que corriger une petite erreur sur l'un sans pouvoir l'exécuter (pour des raisons proprement personnelles).
Aussi, je viens de faire le transfert de ces deux oeuvres et les tester : Le travail est original et me montre que, toi aussi tu en sais des choses !

Seulement, c'est avec véritable dérangement que je t'apprends que leur exécution me bouffe de la batterie sur 2 machines distinctes. Autrement dit : compatibilité négative avec une machine à puissance limitée.

Par contre, mon gros fourbi pas fini lui, il tourne !!!! Les soufflettes ne réveillent pas Mémé en pleine nuit, puisqu'elles ne s'allument pas pour refroidir un CPU non passé à tabac... Et il est tout aussi complexe en affichage ce code, je crois.

J'espère que tu me comprends parce que ce serait bête de perdre des joueurs supplémentaires pour une simple instruction mal utilisée dans des circonstances diverses !

Ollivier

PS : Je tâcherai de te poster les 2 codes corrects dès que possible. Là, je dois rendre la main.

Publié : ven. 27/juin/2008 23:26
par djes
Ce que dit comtois, c'est ce que répète Fred. Quand on utilise un prog qui tourne beaucoup, donc qu'on utilise windowevent() au lieu de waitwindowevent(), il FAUT traiter tous les messages reçus et cela AVANT de faire un delay(). Le delay redonne alors un peu de CPU au reste du système qui peut s'occuper des autres tâches.