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

x86 32-bits / 64-bits Assembleur Discussion :

Ramdom leger ET homogène


Sujet :

x86 32-bits / 64-bits Assembleur

  1. #1
    Membre actif

    Inscrit en
    Février 2009
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 200
    Points : 235
    Points
    235
    Par défaut Ramdom leger ET homogène
    Une particularité des suites numériques permet de concevoir des algos vraiment simples génèrant des suites très homogènes en quelques instructions.
    Ici, DU.Ambitus, représente évidement un DWORD Unsigned stipulant la largeur de l'itération souhaitée -> 0 à DU.Ambitus compris.

    Vous pouvez, bien évidement, ajouter une base ou symétriser la valeur.

    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
    26
    27
    28
    [DU.Rnd: D$ ?]
     
    Randomize:
     
        pushad
     
            Call 'KERNEL32.GetTickCount'
     
            mov D$DU.Rnd eax
     
        popad
     
    ret
     
    Proc Random:
     
        Argument @DU.Ambitus
     
        Uses eax,
             edx
     
        mov eax 00_0001_0010_0100_1000_0011_0110_1100_1111 | mul D$DU.Rnd
     
        mov D$DU.Rnd eax
     
        mul D@DU.Ambitus | mov eax edx
     
    EndP

  2. #2
    Membre actif

    Inscrit en
    Février 2009
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 200
    Points : 235
    Points
    235
    Par défaut Plus homogène pour le remplissage
    Visuellement certaines récurences dans cette modification (il f'audrait l'écouter pour reperer plus facilement les boucles) mais très efficace pour le remplissage méthodique:

    En hexa cette fois -> mov eax 0_1357BDFF

  3. #3
    Membre actif

    Inscrit en
    Février 2009
    Messages
    200
    Détails du profil
    Informations forums :
    Inscription : Février 2009
    Messages : 200
    Points : 235
    Points
    235
    Par défaut Optimisation
    Soit le code suivant, appelé à chaque itération d'un traitement, que nous désirons optimiser stratégiquement dans un premier temps puis de manière millimétrée:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Proc Random:
     
        Argument @DU.Ambitus
     
        Uses eax,
             edx
     
        mov eax 0_1357BDFF | mul D$DU.Rnd
     
        mov D$DU.Rnd eax
     
        mul D@DU.Ambitus | mov eax edx
     
    EndP
    La première chose qui vient à l'esprit est de supprimer ce qui prend le plus de temps
    Dans la catégorie chronovre, la Macro utilisée pour le cadre de pile est très bien placée:
    Sauvegarde du contexte, utilisation d'Equates de déplacement pour accéder aux divers éléments sur la pile (le code est plus lent) restauration du contexte plus, évidement, deux modifications de l'adresse de traitement d'instruction (ce qui prend le plus de temps en fait hormis les inénarrables push et pop qui résistent à la parallélisation).

    Ce qui donne en clair:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    push ebp
    mov ebp esp
    [RANDOM@DU.AMBITUS ebp+08] ; Déclaration d'Equate globale localisée
    push eax
    push edx
     
    ... code "utile" 
     
    pop edx
    pop eax
    mov esp ebp
    pop ebp
    ret 04
    Au passage, les Macros, sont très utiles pour la lisibilité mais si vous n'avez pas la main dessus cela devient un véritable handicap lié à l'obfuscation du code réel...
    Sous l'apparence d'une réduction de code se cache un monstre qui devient de plus en plus dur à débusquer au fur et à mesure que vous habituez à l'utiliser:
    Un petit rappel -> Le code d'apparence le plus court est rarement le plus rapide !

    Donc, les principes de la sauce étant posés, lançons la cuisson du spaghetti:
    Nous intégrons la génération calibrée dans le code, ce qui permet éviter les sauts, les changements de contextes et une gestion de pile chronovore, non parallélisé correctement dans un système multi-coeurs.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    code...
     
    mov eax 0_1357BDFF 
    mul D$DU.Rnd
    mov D$DU.Rnd eax
    mul D@DU.Ambitus
    mov eax edx
     
    code...
    Ce qui est nettement plus sobre (quitte à la mettre dans une Macro pour éviter les bugs liés aux erreurs de typo dans les multiples répétitions).

    Il est possible, évidement, de tirer encore les coûts et d'augmenter la mise en parallèle par l'utilisation des mécanismes multi-coeur.
    Une utilisation rationnelle de registres supplémentaires, ebx comme base et ecx comme compteur (ici ambitus) permet le montage suivant:
    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
     
    push ebx
    mov ebx D$DU.Rnd 
    mov ecx D@DU.Ambitus
     
    code ....
     
    mov eax 0_1357BDFF 
    mul ebx
    mov ebx eax
    mul ecx
    mov eax edx
     
    code...
     
    pop ebx
    Déjà un peu plus propre et stratégiquement plus souple:
    L'intérêt étant de pouvoir optimiser l'algorithme vers un model itératif par la modification dynamique d'ecx en fonction de l'évolution du traitement.

    Il est possible maintenant de millimétrer la stratégie plus simplement en remplaçant:

    - Eax par edx (il y a de forte chance pour que le résultat ne soit pas conservé longtemps après son utilisation puisque nous parlons de vitesse dans une boucle de traitement): Edx sera donc le registre qui contiendra le résultat à utiliser.

    - Ebx par eax: Eax sera donc la base (ce qui est moins lisible mais il n'apparaîtra plus dans le code)

    - Eax (dans sa fonction de constante) par ebx: L'emploi d'ebx reste lisible puisqu'il est bien utilisé en tant que base constante (à moins que, là aussi, vous désiriez faire évoluer dynamiquement le modèle…)

    Nous obtenons, après une unique initialisation "nettement" plus lourde (principe de base de la plupart des optimisations):

    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
     
    push ebx
    mov eax D$DU.Rnd 
    mov ebx 0_1357BDFF
    mov ecx D@DU.Ambitus
     
    code...
     
    mul ebx
    mul ecx
     
    ; Edx contient le résultat qui sera utilisé
    ; Eax étant devenu la variable de randomisation
     
    code...
     
    pop ebx
    Nous n'avons pas perdu l'avantage stratégique précédent d'optimisation d'ambitus: Ecx reste toujours dynamiquement modifiable.

    Côtés négatifs:

    - Ebx n'est plus utilisable (pourquoi ne pas le remplacer par un des registres (le bon !) servant à gérer habituellement les cadres de pile…)

    - Eax n'est plus utilisable en entrée mais maintient des informations précieuses et utilisables !

    - Edx n'est pas persistant mais eax ne l'était pas vraiment non plus...

    - Ecx n'est plus utilisable en tant que compteur indépendant mais…

    Côtés positifs:

    - Esi/edi sont libres pour la gestion de blocs

    - Eax maintient la variable de randomisation disponible
    - Ecx est un compteur toujours fixé sur l'ambitus courant (y compris s'il est réajusté à chaque itération) cela permet une gestion directe des blocs à traiter

    - Edx est disponible pour les déplacements et la gestion des blocs étant initialisé correctement à chaque itération

    - Ebp/(esp) sont libres comme rappelé plus haut

    Enfin, n'oubliez pas que pour la gestion des blocs qu'edx est mis à jour automatiquement par les mul et que vous pouvez donc protéger ecx par edx (ce qui n'est pas forcément votre priorité, dans cas là vous travaillerez plutôt sur edx dans ecx (ce qui est plus important à mon avis) et ecx sera sauvegardé dans ebx ou son registre de remplacement -> selon le choix fait précédemment).

    Je me permets aussi de vous rappeler que l'accès à des donnés non-alignées est sanctionné par votre processeur: Si mov al B$LP.xxx ne pose aucun problème, mov ax W$LP.xxx ou mov eax D$LP.xxx sont considérablement ralentis en cas d'alignements impairs pour les WORDs ou non multiples de 4 pour les DWORDs !

    La routine ci-dessous copie plus rapidement des adresses alignées (sachant que SSEx ne donnera pas de meilleurs résultats ici pour des raisons de synchronisations des transferts.
    Si donc l'adresse de départ vos données n'est pas (forcément) alignée vous devez modifier le code pour copier via mosb jusqu'à l'alignement DWORD, copier via movsd tous vos DWORS et, enfin, finir avec movsb de copier les derniers BYTEs si besoin.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    code...
     
    mov esi LP.Source,  ; Aligné sur DWORD
        edi LP.Cible,   ; aligné sur DWORD
        edx ecx        ; Sauvegarde d'ecx
     
    shr ecx 2 | rep movsd ; Copie par DWORDs
     
    mov cl dl | and cl 3 | rep movsb ; Copie des BYTEs restants (0 ~3)
     
    mov ecx edx ; Restauration d'ecx
     
    code...

Discussions similaires

  1. Réponses: 13
    Dernier message: 09/09/2005, 14h34
  2. Les Distributions légères (486)
    Par nuke_y dans le forum Distributions
    Réponses: 17
    Dernier message: 19/08/2005, 13h19
  3. [c#][VS.NET 2K3]leger comparatif access et mysql
    Par megatof dans le forum Windows Forms
    Réponses: 15
    Dernier message: 22/07/2005, 21h32
  4. Un gestionnaire de fichiers léger et thémable
    Par Thrystan dans le forum Applications et environnements graphiques
    Réponses: 3
    Dernier message: 29/06/2005, 22h45
  5. Convertir un *.pdf en un format plus leger
    Par Nasky dans le forum Autres Logiciels
    Réponses: 8
    Dernier message: 23/06/2003, 08h44

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