Questions sur la POO dans MQL5 - page 70

 
Maxim Kuznetsov:

C'est ce que l'on appelle le "déroulage de boucle" et il est effectué par le compilateur sans aucune OO ni modèle (du moins, il devrait l'être).

Si vous regardez dans le code intermédiaire (assembleur), il y a juste des opérations N consécutives au lieu d'une boucle.

Et pouvez-vous nous dire ce qui se passe lorsqu'une fonction est appelée de manière récursive ?

 
Dmitry Fedoseev:

Pouvez-vous me dire ce qui se passe lorsqu'une fonction est appelée de manière récursive ?

il n'y a pas d'appel récursif aux fonctions cibles :-)

Dans l'exemple ci-dessus N:=const, la récursion ne se produit que lorsque le code est généré à partir d'un template et que celui-ci est adapté. Au niveau du lien, une astuce consiste à transformer le cycle const en récursion de modèle et à l'appeler un mot intelligent.

si les macros avaient des boucles, cela s'écrirait comme ceci

#for x=0, x<N, x++

print("x=%d",x);

#endfor

et après le macro processeur, il se déploierait en une séquence de N princes. (ce qui s'est réellement produit, mais uniquement par le biais de classes de modèles)

C'est-à-dire que l'astuce ne fonctionne que si N est connu au moment de la compilation.

 
Maxim Kuznetsov:

et il n'y a pas d'appel récursif aux fonctions cibles :-)

Dans l'exemple donné au lien N:=const, la récursion n'intervient que lors de la génération de code à partir d'un template et celui-ci est adapté. Au niveau du lien, une astuce consiste à transformer le cycle const en récursion de modèle et à l'appeler un mot intelligent.

si les macros avaient des boucles, cela s'écrirait comme ceci

#for x=0, x<N, x++

print("x=%d",x);

#endfor

et après le macro processeur, il se déploierait en une séquence de N princes. (ce qui s'est réellement produit, mais uniquement par le biais de classes de modèles)

L'astuce ne fonctionne donc que si N est connu au moment de la compilation.

Vous ne le croirez pas, mais je sais comment fonctionnent les modèles, quel est le N et quel est le résultat. Et ma question sur l'appel de fonction récursive portait exactement sur l'appel de fonction récursive, et non pas sur comment y arriver ?

 
Dmitry Fedoseev:

Vous ne le croirez pas, mais je sais comment fonctionnent les modèles, quel est le N et quel est le résultat. Et ma question sur l'appel de fonction récursive portait exactement sur l'appel de fonction récursive, et non pas sur comment y arriver ?

Est-ce que c'est comme un examen "dare ?"? :-) Je pensais que cet exemple avait été discuté... j'avais tort :-)

Si le compilateur peut convertir la récursion en queue (ou c'est explicitement le cas, ou on lui a dit de le faire), alors physiquement il n'y aura pas de récursion - il fera une boucle (retour en arrière) et chaque itération "piétinera" le cadre de pile précédent.

 
Maxim Kuznetsov:

Est-ce que c'est une sorte d'examen "osé" ? :-) Je pensais que cet exemple avait été discuté... j'avais tort :-)

Si le compilateur peut convertir la récursion en une récursion de queue (ou s'il est explicitement tel ou si on lui a demandé de le faire), alors physiquement il n'y aura pas de récursion - il fera une boucle (retour en arrière) et chaque itération "piétinera" le cadre de pile précédent.

Qu'est-ce que cela a à voir avec la faiblesse ? Juste une question. Eh bien, non, donc non.

 
fxsaber:

Je ne veux même pas me donner la peine. J'ai fait des structures simples.



Je ne comprends pas pourquoi l'accès au premier champ d'une structure simple dépend de sa taille.

Huh. C'est trivial - le nombre de bits à multiplier est plus)))). Assurez-vous que le nombre de bits dans la représentation binaire de la taille de la structure était le même)))). Processeur stupide, ainsi qu'un homme, plus long à multiplier 1111*101 que 1111*10)
 
Vladimir Simakov:
Huh. C'est trivial - le nombre de bits pour la multiplication est plus)))). Assurez-vous que le nombre de bits dans la représentation binaire de la taille de la structure était le même))). Processeur stupide, ainsi qu'un homme, plus long à multiplier 1111*101 que 1111*10)

Je ne vais pas vérifier, il y a plein d'autres tâches. Mais je trouve ça difficile à croire.

 

Dans ME, je travaille avec mqh, appuyez sur ALT+N - l'arborescence dans la fenêtre du Navigateur montre l'emplacement du fichier.

Je veux maintenant l'inclure dans un fichier mq5 ouvert. Je fais glisser mqh de l'arbre vers mq5, mais aucune ligne d'inclusion appropriée n'est générée.

 
fxsaber:

Je ne vais pas vérifier, il y a plein d'autres tâches. Mais je trouve ça difficile à croire.

template <typename T>
size_t Func(T* arr,size_t arrSize)
{
000000013 FFC1DA0  mov         qword ptr [rsp+10 h],rdx  
000000013 FFC1DA5  mov         qword ptr [rsp+8],rcx  
000000013 FFC1DAA  push        rbp  
000000013 FFC1DAB  push        rdi  
000000013 FFC1DAC  sub         rsp,148 h  
000000013 FFC1DB3  lea         rbp,[rsp+20 h]  
000000013 FFC1DB8  mov         rdi,rsp  
000000013 FFC1DBB  mov         ecx,52 h  
000000013 FFC1DC0  mov         eax,0 CCCCCCCCh  
000000013 FFC1DC5  rep stos    dword ptr [rdi]  
000000013 FFC1DC7  mov         rcx,qword ptr [rsp+168 h]  
000000013 FFC1DCF  lea         rcx,[__116109BC_Test@cpp (013 FFD5029h)]  
000000013 FFC1DD6  call        __CheckForDebuggerJustMyCode (013 FFC10B9h)  
    // Write
    for (size_t i = 0; i <arrSize; ++i)
000000013 FFC1DDB  mov         qword ptr [rbp+8],0  
000000013 FFC1DE3  jmp         Func<STRUCT1>+50 h (013 FFC1DF0h)  
000000013 FFC1DE5  mov         rax,qword ptr [rbp+8]  
000000013 FFC1DE9  inc         rax  
000000013 FFC1DEC  mov         qword ptr [rbp+8],rax  
000000013 FFC1DF0  mov         rax,qword ptr [arrSize]  
000000013 FFC1DF7  cmp         qword ptr [rbp+8],rax  
000000013 FFC1DFB  jae         Func<STRUCT1>+71 h (013 FFC1E11h)  
        arr[i].i = i;
000000013 FFC1DFD  imul        rax,qword ptr [rbp+8],18 h  
000000013 FFC1E02  mov         rcx,qword ptr [arr]  
000000013 FFC1E09  mov         edx,dword ptr [rbp+8]  
000000013 FFC1E0C  mov         dword ptr [rcx+rax],edx  
000000013 FFC1E0F  jmp         Func<STRUCT1>+45 h (013 FFC1DE5h)  

    size_t Sum = 0;
000000013 FFC1E11  mov         qword ptr [Sum],0  

    // Read
    for (size_t i = 0; i < arrSize; ++i)
000000013 FFC1E19  mov         qword ptr [rbp+48 h],0  
000000013 FFC1E21  jmp         Func<STRUCT1>+8 Eh (013 FFC1E2Eh)  
000000013 FFC1E23  mov         rax,qword ptr [rbp+48 h]  
000000013 FFC1E27  inc         rax  
000000013 FFC1E2A  mov         qword ptr [rbp+48 h],rax  
000000013 FFC1E2E  mov         rax,qword ptr [arrSize]  
000000013 FFC1E35  cmp         qword ptr [rbp+48 h],rax  
000000013 FFC1E39  jae         Func<STRUCT1>+0 BBh (013 FFC1E5Bh)  
        Sum += arr[i].i;
000000013 FFC1E3B  imul        rax,qword ptr [rbp+48 h],18 h  
000000013 FFC1E40  mov         rcx,qword ptr [arr]  
000000013 FFC1E47  movsxd      rax,dword ptr [rcx+rax]  
000000013 FFC1E4B  mov         rcx,qword ptr [Sum]  
000000013 FFC1E4F  add         rcx,rax  
000000013 FFC1E52  mov         rax,rcx  
000000013 FFC1E55  mov         qword ptr [Sum],rax  
000000013 FFC1E59  jmp         Func<STRUCT1>+83 h (013 FFC1E23h)  

    return Sum + arrSize;
000000013 FFC1E5B  mov         rax,qword ptr [arrSize]  
000000013 FFC1E62  mov         rcx,qword ptr [Sum]  
000000013 FFC1E66  add         rcx,rax  
000000013 FFC1E69  mov         rax,rcx  
}
000000013 FFC1E6C  lea         rsp,[rbp+128 h]  

C'est pour une petite structure.

template <typename T>
size_t Func(T* arr,size_t arrSize)
{
000000013 FFC1EB0  mov         qword ptr [rsp+10 h],rdx  
000000013 FFC1EB5  mov         qword ptr [rsp+8],rcx  
000000013 FFC1EBA  push        rbp  
000000013 FFC1EBB  push        rdi  
000000013 FFC1EBC  sub         rsp,148 h  
000000013 FFC1EC3  lea         rbp,[rsp+20 h]  
000000013 FFC1EC8  mov         rdi,rsp  
000000013 FFC1ECB  mov         ecx,52 h  
000000013 FFC1ED0  mov         eax,0 CCCCCCCCh  
000000013 FFC1ED5  rep stos    dword ptr [rdi]  
000000013 FFC1ED7  mov         rcx,qword ptr [rsp+168 h]  
000000013 FFC1EDF  lea         rcx,[__116109BC_Test@cpp (013 FFD5029h)]  
000000013 FFC1EE6  call        __CheckForDebuggerJustMyCode (013 FFC10B9h)  
    // Write
    for (size_t i = 0; i <arrSize; ++i)
000000013 FFC1EEB  mov         qword ptr [rbp+8],0  
000000013 FFC1EF3  jmp         Func<STRUCT3>+50 h (013 FFC1F00h)  
000000013 FFC1EF5  mov         rax,qword ptr [rbp+8]  
000000013 FFC1EF9  inc         rax  
000000013 FFC1EFC  mov         qword ptr [rbp+8],rax  
000000013 FFC1F00  mov         rax,qword ptr [arrSize]  
000000013 FFC1F07  cmp         qword ptr [rbp+8],rax  
000000013 FFC1F0B  jae         Func<STRUCT3>+71 h (013 FFC1F21h)  
        arr[i].i = i;
000000013 FFC1F0D  imul        rax,qword ptr [rbp+8],58 h  
000000013 FFC1F12  mov         rcx,qword ptr [arr]  
000000013 FFC1F19  mov         edx,dword ptr [rbp+8]  
000000013 FFC1F1C  mov         dword ptr [rcx+rax],edx  
000000013 FFC1F1F  jmp         Func<STRUCT3>+45 h (013 FFC1EF5h)  

    size_t Sum = 0;
000000013 FFC1F21  mov         qword ptr [Sum],0  

    // Read
    for (size_t i = 0; i < arrSize; ++i)
000000013 FFC1F29  mov         qword ptr [rbp+48 h],0  
000000013 FFC1F31  jmp         Func<STRUCT3>+8 Eh (013 FFC1F3Eh)  
000000013 FFC1F33  mov         rax,qword ptr [rbp+48 h]  
000000013 FFC1F37  inc         rax  
000000013 FFC1F3A  mov         qword ptr [rbp+48 h],rax  
000000013 FFC1F3E  mov         rax,qword ptr [arrSize]  
000000013 FFC1F45  cmp         qword ptr [rbp+48 h],rax  
000000013 FFC1F49  jae         Func<STRUCT3>+0 BBh (013 FFC1F6Bh)  
        Sum += arr[i].i;
000000013 FFC1F4B  imul        rax,qword ptr [rbp+48 h],58 h  
000000013 FFC1F50  mov         rcx,qword ptr [arr]  
000000013 FFC1F57  movsxd      rax,dword ptr [rcx+rax]  
000000013 FFC1F5B  mov         rcx,qword ptr [Sum]  
000000013 FFC1F5F  add         rcx,rax  
000000013 FFC1F62  mov         rax,rcx  
000000013 FFC1F65  mov         qword ptr [Sum],rax  
000000013 FFC1F69  jmp         Func<STRUCT3>+83 h (013 FFC1F33h)  

    return Sum + arrSize;
000000013 FFC1F6B  mov         rax,qword ptr [arrSize]  
000000013 FFC1F72  mov         rcx,qword ptr [Sum]  
000000013 FFC1F76  add         rcx,rax  
000000013 FFC1F79  mov         rax,rcx  
}
000000013 FFC1F7C  lea         rsp,[rbp+128 h]  

C'est pour un grand.

VS2019, Debug x64, en release il les a inlined, mais la vitesse est la même.

La seule différence réside dans les instructions imul, le troisième opérande, à deux endroits. L'instruction ne fait que calculer l'offset dans le tableau, et le troisième opérande estla taille de la structure en octets.

Donc, pas de mysticisme - les lois de la physique en action.

 
Vladimir Simakov:

Donc, pas de mysticisme - les lois de la physique sont en action.

si vous écrivez de telles classes :

//+------------------------------------------------------------------+
struct STRUCT
{
   int i;
   double d;
   uchar uc[16];
};
//+------------------------------------------------------------------+
class A
{
private:
   int i;
   double d;
   uchar uc[16];
public:
   A(const STRUCT &ini) { i = ini.i; d = ini.d; ArrayCopy(uc,ini.uc); }
};
//+------------------------------------------------------------------+
class B
{
private:
   STRUCT data;
public:
   B(const STRUCT &ini) { data = ini; }
};
//+------------------------------------------------------------------+

D'après vos recherches, la classe B sera plus lente à exécuter si vous utilisez fréquemment des champs de structure dans les calculs ?