Excuse moi mais qu'est ce que j'ai à voir là dedans ?Ollivier a écrit :@PAPIPP
1) Tu me rabaches un truc que je sais déjà sur RDTSC, de ta part, comme de celle de Progi1984, donc inutile
Boucle For et calcul dans la plage
- Progi1984
- Messages : 2659
- Inscription : mar. 14/déc./2004 13:56
- Localisation : France > Rennes
- Contact :
Librairies & Applications : https://www.purebasic.fr/french/viewtop ... f=8&t=6220
Site Web : https://rootslabs.net
Site Web : https://rootslabs.net
Rien de mal, au contraire. Tu m'as appris à me servir de RDTSC quand un ProcedureReturn dans une procédure retourne un quad en chargeant EAX en poids faible et EDX en poids fort.
La tournure de la phrase peut porter à confusion, mais ce qui est inutile, c'est bien le rabachage de PAPIPP qui donne une énorme envie de continuer à donner de son temps pour partager du code et des idées.
La tournure de la phrase peut porter à confusion, mais ce qui est inutile, c'est bien le rabachage de PAPIPP qui donne une énorme envie de continuer à donner de son temps pour partager du code et des idées.
Pour éviter de trop rabâcher et bien que la répétition soit une excellente forme pédagogique je t’invite à regarder
ici Mercredi 17 Juin 2009 23h11
http://www.purebasic.fr/french/viewtopi ... p&start=15
La boucle est bouclée
ici Mercredi 17 Juin 2009 23h11
http://www.purebasic.fr/french/viewtopi ... p&start=15
La boucle est bouclée
Je tâcherai d'expliquer le code tout en haut quand j'aurai le temps. En attendant, j'ai l'intime conviction qu'il ne suffit pas de lire un fichier ASM pour être sorti de l'auberge quand à la chronométrie des instructions.
Code : Tout sélectionner
EnableExplicit
DisableDebugger
Procedure.Q BuildQuad(Low.I, High.I)
! mov Eax, [p.v_Low]
! mov Edx, [p.v_High]
ProcedureReturn
EndProcedure
Define A.I
Define B.I
Define C.I
Define D.I
Define E.I
Define F.I
Delay(100)
! MOV [v_A], Eax
Delay(1)
! MOV [v_A], Eax
! RDTSC
! MOV [v_E], Eax
! RDTSC
! MOV [v_F], Eax
! RDTSC
! MOV [v_A], Eax
! XOR Eax, Eax
! MOV [v_B], Edx
! RDTSC
! MOV [v_C], Eax
! MOV [v_D], Edx
MessageRequester("Supprimez la ligne 21", "!RDTSC" + Chr(9) + Chr(9) + Chr(9) + "} " + Str(F - E) + " cycle(s)" + Chr(10) + "!MOV [v_X], Eax" + Chr(10) + Chr(10) + "!RDTSC" + Chr(9) + Chr(9) + Chr(9) + "} " + Str(BuildQuad(C, D) - BuildQuad(A, B) ) + " cycle(s)" + Chr(10) + "!MOV [v_X], Eax" + Chr(10) + "!MOV [v_Y], Edx")
@PAPIPP
J'ai vu ton message (le dernier de la page précédente). Je le prends pour excuse tout à fait correcte. Et c'est à moi de m'excuser de t'avoir mis la pression.
J'ai vraiment pensé que tu te moquais, alors que tu as juste rassemblé plusieurs erreur de maladresse (cinq, c'est un record à mes yeux, mais si ce n'est que de la maladresse, c'est largement excusable). La programmation doit rester un échange. Si tu dis que tu es débutant en PB, je peux prendre soin de t'expliquer correctement ce qui cloche et quel code serait mieux adapté par le fond de tes remarques. Et, à mon avis ainsi tu aurais d'autres choses à m'apprendre sans aucune faille. Comme bon nombre de membres ici.
La chronométrie implique de prendre les valeurs (ici les cycles) de manières relatives. Une instruction va s'exécuter selon un contexte:
- l'instruction qui la précède;
- l'amorçage de la tâche;
- la durée d'appel de son argument (instructions de saut);
Les résultats individuels sont donc variés et ne peuvent donner lieu à un simple comme s'il s'agissait d'un domino-day où les instructions sont toutes idem et carrées dans leur exécution.
La remarque de LSI ("c'est strictement pareil") laissait penser, si elle avait été vraie, que son CPU avait la capacité matérielle d'optimiser les multiplications à produits identiques. Ce qui aurait pu être plausible. ça s'est révélé faux. Cependant, ça n'empêche en rien de déceler des choses intéressantes en créant les bons outils de mesure. L'exemple ci-dessus en est un. Mais il y en a une foule d'autres. Un autre exemple au pif, un JNE (If a <> b) plus lent qu'un JE (If a = b).
Aussi le meilleur outils c'est quand TOI tu répètes une instruction dans l'éditeur des centaines ou des milliers de fois en poussant souvent au max les limites du compilateur. Cette tâche te prendrait beaucoup de temps. Heureusement, Fred a créé un superbe compilateur (il a des défauts aussi bien sûr!). Sa compilation est rapide. Il est souple (Cf le sujet "Le compilateur en mode Standby"). Et le langage Basic est à la portée de bon nombres d'informaticiens. Sa syntaxe est plus légère que le C et l'assembleur y est insérable comme une lettre à la poste. Bien sûr, tout cela, tu le sais déjà, je pense. Ce qui est intéressant mais pas forcément séduisant, c'est de créer une application non-autonome. C'est-à-dire un exécutable qui, quand le commun des mortels sur le Net tombe dessus, quand il l'exécute se voit afficher "Compilateur introuvable! Aller à la page www.purebasic.com pour de plus amples renseignements." En revanche, la communauté PB, elle, n'a aucune difficulté à exécuter ce code. Un exemple non-autonome: Python.
Donc la chronométrie précise revient à chercher une méthode qui ouvre beaucoup plus de portes que d'écrire un simple programme. C'est exactement comme fouiller un champ, sous prétexte d'une légende qui indiquerait qu'un trésor s'y cache, alors qu'au final c'est l'action de ce travail de la terre qui a enrichi la récolte et donc produit un trésor.
Ce que je te conseille c'est de créer un petit programme qui t'affiche un message comme
et de l' "encapsuler" dans une chaîne pour obtenir ce programme dans la fenêtrede déboguage. La première difficulté c'est les guillemets, car on ne peut pas écrire
Les guillemets à l'intérieur doivent être remplacés par un Chr(34). Et comme une chaîne est entourée par une PAIRE de guillemets, il faut en théorie écrire DEUX fois CHR(34) sans compter les fermetures et les réouvertures de chaîne ainsi que les liens (les signes plus "+")
On peut heureusement simplifier par une procédure:
Avec la procédure G() comme suit:Et cette procédure est la première procédure que j'explique ici et qui se situe dans le code générateur plus haut, au début du sujet.
J'ai vu ton message (le dernier de la page précédente). Je le prends pour excuse tout à fait correcte. Et c'est à moi de m'excuser de t'avoir mis la pression.
J'ai vraiment pensé que tu te moquais, alors que tu as juste rassemblé plusieurs erreur de maladresse (cinq, c'est un record à mes yeux, mais si ce n'est que de la maladresse, c'est largement excusable). La programmation doit rester un échange. Si tu dis que tu es débutant en PB, je peux prendre soin de t'expliquer correctement ce qui cloche et quel code serait mieux adapté par le fond de tes remarques. Et, à mon avis ainsi tu aurais d'autres choses à m'apprendre sans aucune faille. Comme bon nombre de membres ici.
La chronométrie implique de prendre les valeurs (ici les cycles) de manières relatives. Une instruction va s'exécuter selon un contexte:
- l'instruction qui la précède;
- l'amorçage de la tâche;
- la durée d'appel de son argument (instructions de saut);
Les résultats individuels sont donc variés et ne peuvent donner lieu à un simple comme s'il s'agissait d'un domino-day où les instructions sont toutes idem et carrées dans leur exécution.
La remarque de LSI ("c'est strictement pareil") laissait penser, si elle avait été vraie, que son CPU avait la capacité matérielle d'optimiser les multiplications à produits identiques. Ce qui aurait pu être plausible. ça s'est révélé faux. Cependant, ça n'empêche en rien de déceler des choses intéressantes en créant les bons outils de mesure. L'exemple ci-dessus en est un. Mais il y en a une foule d'autres. Un autre exemple au pif, un JNE (If a <> b) plus lent qu'un JE (If a = b).
Aussi le meilleur outils c'est quand TOI tu répètes une instruction dans l'éditeur des centaines ou des milliers de fois en poussant souvent au max les limites du compilateur. Cette tâche te prendrait beaucoup de temps. Heureusement, Fred a créé un superbe compilateur (il a des défauts aussi bien sûr!). Sa compilation est rapide. Il est souple (Cf le sujet "Le compilateur en mode Standby"). Et le langage Basic est à la portée de bon nombres d'informaticiens. Sa syntaxe est plus légère que le C et l'assembleur y est insérable comme une lettre à la poste. Bien sûr, tout cela, tu le sais déjà, je pense. Ce qui est intéressant mais pas forcément séduisant, c'est de créer une application non-autonome. C'est-à-dire un exécutable qui, quand le commun des mortels sur le Net tombe dessus, quand il l'exécute se voit afficher "Compilateur introuvable! Aller à la page www.purebasic.com pour de plus amples renseignements." En revanche, la communauté PB, elle, n'a aucune difficulté à exécuter ce code. Un exemple non-autonome: Python.
Donc la chronométrie précise revient à chercher une méthode qui ouvre beaucoup plus de portes que d'écrire un simple programme. C'est exactement comme fouiller un champ, sous prétexte d'une légende qui indiquerait qu'un trésor s'y cache, alors qu'au final c'est l'action de ce travail de la terre qui a enrichi la récolte et donc produit un trésor.
Ce que je te conseille c'est de créer un petit programme qui t'affiche un message comme
Code : Tout sélectionner
Debug "Voici un message"
Code : Tout sélectionner
Debug "Debug "Voici un message""
Code : Tout sélectionner
Debug "Debug " + Chr(34) + "Voici un message" + Chr(34)
Code : Tout sélectionner
Debug "Debug" + G("Voici un message")
Code : Tout sélectionner
Procedure.S G(Chaine.S)
Protected Result.S
Result = Chr(34) + Chaine + Chr(34)
ProcedureReturn Result
EndProcedure
Ensuite, il y a cette procédure-ci:
Debug va afficher un message dans le débogueur. Si le message est une ligne de code qui doit être exécutée, au lieu d'utiliser Debug, dans le code générateur, on utilise Impr() (comme imprimer).
J'ai appelé cette procédure StoreTrust(), parce qu'elle stocke le code enfant. Et j'ai mis Trust parce qu'il faut vraiment avoir confiance en ce que l'on crée, vu qu'il est très facile de créer des codes impossibles à comprendre et trop gros pour être débogué à la main.
Dans cette procédure, pour repartir à zéro et réécrire un routine d'enregistrement de code, il suffit de faire le ménage:
Et de commencer à mettre son propre code:
Ainsi, tu peux exécuter à peu près tout et n'importe quoi. Ce programme devient une sorte de "Macro-Basic". C'est ainsi qu'il faut voir la procédure BouclageEcriture(). C'est en fait une macro dynamique du code enfant. Parce qu'en PureBasic, il est impossible de créer une macro qui va augmenter le nombre boucles imbriquées avec un simple nombre en argument.
La procédure BouclageEcriture(10, 1, "Max") créera le code suivant:(Comme tu peux le voir, c'est uniquement la seule ligne For qui est chronométrée.)
BouclageEcriture(11, 3, "Maximum") créera le code suivant:
Avec ces deux codes, on se rend bien compte que la procédure BouclageEcriture() joue le rôle d'une très puissante macro qui génère et mesure des boucles. Ainsi, c'est là, je pense que la boucle est bouclée...
Code : Tout sélectionner
Procedure StoreTrust(*C.OpString)
With *C
CreateFile(0, #Home + \TrustFileName + ".pb")
Impr("DisableDebugger")
BouclageEcriture(1, 100, "XYZTUVWXYZABCDEFGHIJKLM")
BouclageEcriture(2, 100, "X * Y * Z * T * U * V * W * X * Y * Z * A * B * C * D * E * F * G * H * I * J * K * L * M")
Impr("MessageRequester(" + G("Quantité approx de cycles utilisés") + ", " + G("Avec optimisation = ") + " + Str(Fin1 - Ini1) + " + G(" cycles") + " + Chr(10) + " + G("Sans optimisation = ") + " + Str(Fin2 - Ini2) + " + G(" cycles") + ")")
CloseFile(0)
EndWith
EndProcedure
J'ai appelé cette procédure StoreTrust(), parce qu'elle stocke le code enfant. Et j'ai mis Trust parce qu'il faut vraiment avoir confiance en ce que l'on crée, vu qu'il est très facile de créer des codes impossibles à comprendre et trop gros pour être débogué à la main.
Dans cette procédure, pour repartir à zéro et réécrire un routine d'enregistrement de code, il suffit de faire le ménage:
Code : Tout sélectionner
Procedure StoreTrust(*C.OpString)
With *C
CreateFile(0, #Home + \TrustFileName + ".pb")
CloseFile(0)
EndWith
EndProcedure
Code : Tout sélectionner
Procedure StoreTrust(*C.OpString)
With *C
CreateFile(0, #Home + \TrustFileName + ".pb")
Impr("Debug " + G("Voici mon propre code!") )
CloseFile(0)
EndWith
EndProcedure
La procédure BouclageEcriture(10, 1, "Max") créera le code suivant:
Code : Tout sélectionner
Define Ini10.I
Define Fin10.I
! RDTSC
! MOV [v_Ini10], Eax
For AA = 0 To Max
! RDTSC
! MOV [v_Fin10], Eax
Break 1
Next
BouclageEcriture(11, 3, "Maximum") créera le code suivant:
Code : Tout sélectionner
Define Ini11.I
Define Fin11.I
! RDTSC
! MOV [v_Ini11], Eax
For AA = 0 To Maximum
For AB = 0 To Maximum
For AC = 0 To Maximum
! RDTSC
! MOV [v_Fin11], Eax
Break 3
Next
Next
Next