¿Declaración de variables detrás del bucle o dentro del bucle? - página 2

 
Georgiy Merts:

No, no lo estoy.

Por supuesto, un compilador normal en este caso tendría que poner la declaración de la variable dentro del bucle fuera del bucle.

Creo que siempre hay que confiar en el compilador y en uno mismo. Es un estándar del compilador que una variable local se crea cuando se declara y se elimina cuando se sale del bloque en el que se declaró. Por lo tanto, debes centrarte en este principio en primer lugar y no esperar a que el compilador mejore tu código por ti.

Así que digo que si quieres "hacerlo mejor", vete a ensamblador, si necesitas controlar todo tú mismo... Después de todo, el caso que acaba de describir no es nada. Hay cosas mucho más complicadas. El OOP está definitivamente contraindicado para ti. No sabrás si el compilador ha degenerado o no un método virtual concreto en una llamada normal, o si ha cortado una comprobación de punteros innecesaria... ¿Qué puedes hacer en un MQL gestionado con semejante paranoia? )

Y retocar el código para adaptarlo a las peculiaridades del compilador (y a las imaginarias), en detrimento de la corrección y fiabilidad del código, no es, obviamente, lo que debe hacer un buen programador. Y aquí estamos hablando exactamente de incorrección del código. La variable debe declararse directamente en el bloque en el que se utiliza.

 
Vict:

Hombre, eso es una tontería salvaje, qué hay que comentar, una falta total de comprensión de cómo funciona el depurador.

Lo haces.
 
Alexey Navoykov:
Lo haces.

Como en el jardín de infancia ))) Lo explico para los que están en el tanque: primero compilamos g++ 1.cpp, ahí no hay puntos de ruptura, el compilador no sabe nada de ellos. A continuación, ejecute el depurador: gdb a.out, y sólo ahora poner punto de interrupción.

¿Entiendes las tonterías que has dicho?

 
Alexey Navoykov:

Sólo se puede detectar la optimización compilando el código o midiendo su rendimiento. Eso es lo primero que hay que hacer. Y cálmate )

2019.08.18 10:28:12.826 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=100000000 ms=7031

2019.08.18 10:28:19.885 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=100000000 ms=7063

2019.08.18 10:28:27.037 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=100000000 ms=7140

2019.08.18 10:28:34.045 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=100000000 ms=7016

2019.08.18 10:28:41.135 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=100000000 ms=7094

2019.08.18 10:28:47.896 SpeedTest (EURUSD,H1) 1. q=rand(): loops=100000000 ms=6750

2019.08.18 10:28:54.659 SpeedTest (EURUSD,H1) 2. q=rand(): loops=100000000 ms=6765

2019.08.18 10:29:01.447 SpeedTest (EURUSD,H1) 3. q=rand(): loops=100000000 ms=6797

2019.08.18 10:29:08.257 SpeedTest (EURUSD,H1) 4. q=rand(): loops=100000000 ms=6797

2019.08.18 10:29:15.102 SpeedTest (EURUSD,H1) 5. q=rand(): loops=100000000 ms=6844

//+------------------------------------------------------------------+
//|                                                    SpeedTest.mq5 |
//|                                                            IgorM |
//|                              https://www.mql5.com/ru/users/igorm |
//+------------------------------------------------------------------+
#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
#define  N 8

#define    test(M,S,EX) {uint mss=GetTickCount();ulong nn=(ulong)pow(10,M);for(ulong tst=0;tst<nn&&!_StopFlag;tst++){EX;} \
                        printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   string s1; srand(GetTickCount()); test(N,"1. s1=rand()",s1=IntegerToString(rand()));
   string s2; srand(GetTickCount()); test(N,"2. s2=rand()",s2=IntegerToString(rand()));
   string s3; srand(GetTickCount()); test(N,"3. s3=rand()",s3=IntegerToString(rand()));
   string s4; srand(GetTickCount()); test(N,"4. s4=rand()",s4=IntegerToString(rand()));
   string s5; srand(GetTickCount()); test(N,"5. s5=rand()",s5=IntegerToString(rand()));

   srand(GetTickCount()); test(N,"1. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"2. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"3. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"4. q=rand()",string q=IntegerToString(rand()));
   srand(GetTickCount()); test(N,"5. q=rand()",string q=IntegerToString(rand()));
  }
//+------------------------------------------------------------------+
 
He escarbado bajo el depurador en busca de un código similar, pero sin operador de usuario nuevo, bueno, podría haber algunas dudas - el operador de usuario no está optimizado. Capturada una llamada de malloc() de libc. El resultado: cadena en bucle - una llamada antes de cada impresión, fuera de bucle - una llamada antes de un lote de impresiones. No cabe duda de que sólo la primera variante es mejor. Por supuesto, es posible que algo sea diferente en µl, pero es mejor guiarse por las lenguas maduras.
 
#define  N 9

2019.08.18 10:37:59.620 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=1000000000 ms=70672

2019.08.18 10:39:10.352 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=1000000000 ms=70719

2019.08.18 10:40:21.908 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=1000000000 ms=71562

2019.08.18 10:41:32.315 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=1000000000 ms=70407

2019.08.18 10:42:42.996 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=1000000000 ms=70687

2019.08.18 10:43:50.964 SpeedTest (EURUSD,H1) 1. q=rand(): loops=1000000000 ms=67969

2019.08.18 10:44:58.887 SpeedTest (EURUSD,H1) 2. q=rand(): loops=1000000000 ms=67922

2019.08.18 10:46:06.829 SpeedTest (EURUSD,H1) 3. q=rand(): loops=1000000000 ms=67937

2019.08.18 10:47:14.602 SpeedTest (EURUSD,H1) 4. q=rand(): loops=1000000000 ms=67766

2019.08.18 10:48:22.428 SpeedTest (EURUSD,H1) 5. q=rand(): loops=1000000000 ms=67828

 

Igor Makanu:

#define    test(M,S,EX) {uint mss=GetTickCount();ulong nn=(ulong)pow(10,M);for(ulong tst=0;tst<nn&&!_StopFlag;tst++){EX;} \

Hombre, ¿la "barra espaciadora" no te funciona? No es la primera vez que lo noto. ¿O es que guardas bytes en tu disco duro? )

 
Alexey Navoykov:

¿Bromeas? Es una situación tan trivial para un compilador que no hay nada que hablar. Puedes codificar código puramente en ensamblador con tanta paranoia ) Aunque incluso eso se está convirtiendo en algo sin sentido hoy en día. Tendrás que esforzarte para superar la optimización de los compiladores modernos.

p.d. Tal vez me haya entusiasmado un poco con la trivialidad en el caso del buffer de cadenas. Pero está garantizado que se guarda en MQL, no sólo dentro del bucle, sino incluso entre las llamadas a funciones. Este tema se discutió aquí más de una vez

Tengo la sospecha de que el autor de esta afirmación no sabe en absoluto cómo funcionan el procesador, la memoria y el compilador... Apuesto a que cualquiera de sus códigos puede ser acelerado al menos diez veces, o incluso cientos de veces. Por culpa de estos codificadores de mierda, la mayoría de los productos son ahora insoportablemente lentos en la mayoría de los ordenadores potentes con docenas de núcleos, mientras que sólo hay que pensar un poco... Pero algunos piensan: "¿Por qué pensar? Tienes que codificar..."

Para su información, ningún compilador de momento ha aprendido a entender lo que el programador quería obtener como resultado. Puede desenrollar algunos bucles y optimizar algunos accesos a la memoria para mantener los datos en la caché del procesador, pero si el código no estaba optimizado para empezar y se escribe por un sitio, ningún compilador puede ayudarle...

P.D. Lea con calma un entretenido libro de Chris Kaspersky"Técnica de optimización de programas". Uso eficiente de la memoria".

 
Alexey Volchanskiy:

Georges tiene razón, no está garantizado.

Y obtenemos una conversión implícita de 'número' a 'cadena'


Y así es exactamente como se elimina la ambigüedad y la deformación.

for (int i = 0; i < 1000; i++)
   {
      static string st = IntegerToString(i);
      ...
   }

Así es como lo he hecho siempre.

string st = (string)i;

¿Y qué sentido tiene la estática? La asignación sólo funcionará una vez en la primera iteración.


Decidí medir la velocidad de ejecución.

   CStopWatch sw; // Секундомер, для замера времени
   
   sw.Start();
   for (int i = 0; i < 10000000; i++)
   {
      string st = (string)i;
   }
   pr("Test1, время выполнения: " + sw.Stop());

   sw.Start();
   string st = "";
   for (int i = 0; i < 10000000; i++)
   {
      st = (string)i;
   }
   pr("Test2, Время выполнения: " + sw.Stop());

El resultado:

Test1, время выполнения: 0.548275 сек.
Test2, Время выполнения: 0.313978 сек.

Lo he ejecutado muchas veces, el resultado es estable, el código con la declaración de una variable después del bucle, funciona más rápido

 
Alexey Navoykov:

Hombre, ¿la "barra espaciadora" no te funciona? No es la primera vez que lo noto. ¿O es que guardas bytes en tu disco duro? )

No, este código no es mío, lo refiné un poco - me copié el código del hilo sobre "búsqueda de puntos y comas" y lo uso para las preguntas controvertidas, soy demasiado perezoso para cambiarlo,

Tengo espacios y me da pereza hacerlo ))))

ZS: dame un código de modelo, me lo copio, será como quieras en el futuro, estoy en principio, no me molesta

ZS: aquí AD :

#define    test(M,S,EX) {                                 \
uint mss=GetTickCount();                                 \
ulong nn=(ulong)pow(10,M);                               \
for(ulong tst=0;tst<nn && !_StopFlag;tst++) \
{ EX; }                                                  \
printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}
Razón de la queja: