Preguntas sobre POO en MQL5 - página 70

 
Maxim Kuznetsov:

esto se llama "loop unrolling" y lo hace el compilador sin ningún tipo de OO y plantillas (al menos así debería ser).

Si miras en el código intermedio (ensamblador), sólo hay operaciones N consecutivas en lugar de un bucle.

¿Y puede decirnos qué ocurre cuando se llama a una función de forma recursiva?

 
Dmitry Fedoseev:

¿Puede decirme qué ocurre cuando se llama a una función de forma recursiva?

no hay ninguna llamada recursiva a las funciones de destino :-)

En el ejemplo anterior N:=const, la recursión se produce sólo cuando el código se genera a partir de una plantilla y ésta se adapta. En el enlace, un giro inteligente es colapsar el ciclo const en la recursión de la plantilla y llamarlo una palabra inteligente

si las macros tuvieran bucles se escribiría así

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

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

#endfor

y después del macroprocesador se desdoblaría en una secuencia de N príncipes. (lo que realmente ocurrió, sólo a través de las clases de plantillas)

Es decir, el truco sólo funciona si se conoce N en tiempo de compilación

 
Maxim Kuznetsov:

y no hay ninguna llamada recursiva a las funciones de destino :-)

En el ejemplo que se da en el enlace N:=const, la recursividad es sólo en la generación de código a partir de una plantilla y ésta está adaptada. En el enlace, un giro inteligente es colapsar el ciclo const en la recursión de la plantilla y llamarlo una palabra inteligente

si las macros tuvieran bucles se escribiría así

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

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

#endfor

y después del macroprocesador se desdoblaría en una secuencia de N príncipes. (lo que realmente ocurrió, sólo a través de las clases de plantillas)

Así que el truco sólo funciona si N se conoce en tiempo de compilación

No te lo vas a creer, pero sé cómo funcionan las plantillas y qué N hay, y cuál es el resultado. Y mi pregunta sobre la llamada a la función recursiva era exactamente sobre la llamada a la función recursiva, no sobre cómo allí?

 
Dmitry Fedoseev:

No te lo vas a creer, pero sé cómo funcionan las plantillas y cuál es la N y cuál es el resultado. Y mi pregunta sobre la llamada a la función recursiva era exactamente sobre la llamada a la función recursiva, no sobre cómo allí?

¿es como un examen de "reto"? :-) De alguna manera pensé que este ejemplo se estaba discutiendo... Me equivoqué :-)

Si el compilador puede convertir la recursión en una cola (o es explícitamente así, o se le dijo que lo hiciera), entonces físicamente no habrá recursión - se hará un bucle (vuelta atrás) y cada iteración "pisoteará" el marco de pila anterior.

 
Maxim Kuznetsov:

¿es una especie de examen de "desafío"? :-) De alguna manera pensé que este ejemplo se estaba discutiendo... me equivoqué :-)

Si el compilador puede convertir la recursión en una recursión de cola (o es explícitamente así o se le ha dicho que lo haga), entonces físicamente no habrá recursión - se hará un bucle (vuelta atrás) y cada iteración "pisoteará" el marco de pila anterior.

¿Qué tiene que ver esto con la debilidad? Sólo una pregunta. Bueno, no, así que no.

 
fxsaber:

No quiero ni molestarme. Hice estructuras simples.



No entiendo por qué el acceso al primer campo de una estructura simple depende de su tamaño.

Huh. Es trivial - el número de bits a multiplicar es más)))) Asegúrese de que el número de bits en la representación binaria del tamaño de la estructura era el mismo)))) Estúpido procesador, así como un hombre, más tiempo para multiplicar 1111*101 que 1111*10)
 
Vladimir Simakov:
Huh. Es trivial: el número de bits para la multiplicación es más)))) Asegúrese de que el número de bits en la representación binaria del tamaño de la estructura era el mismo)) Estúpido procesador, así como un hombre, más tiempo para multiplicar 1111*101 que 1111*10)

No voy a comprobarlo, hay muchas otras tareas. Pero me cuesta creerlo.

 

En ME, trabajo con mqh, presiono ALT+N - la vista de árbol en la ventana del Navegador muestra la ubicación del archivo.

Ahora quiero incluirlo en un archivo mq5 abierto. Arrastro mqh del árbol a mq5, pero no se genera ninguna línea de inclusión apropiada.

 
fxsaber:

No voy a comprobarlo, hay muchas otras tareas. Pero me cuesta creerlo.

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]  

Es para una estructura pequeña.

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]  

Esto es para uno grande.

VS2019, Debug x64, en release los inline, pero la velocidad es la misma.

La única diferencia está en las instrucciones imul, el tercer operando, en dos lugares. La instrucción es sólo eso, calcular el desplazamiento en el array, y el tercer operando esel tamaño de la estructura en bytes.

Por lo tanto, no hay misticismo: las leyes de la física en acción.

 
Vladimir Simakov:

Por lo tanto, no hay misticismo - las leyes de la física están en acción.

si escribe tales clases:

//+------------------------------------------------------------------+
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; }
};
//+------------------------------------------------------------------+

A juzgar por tu investigación, la clase B será más lenta de ejecutar si utilizas frecuentemente campos de estructura en los cálculos?

Razón de la queja: