Dichiarare le variabili dietro il ciclo o dentro il ciclo? - pagina 2

 
Georgiy Merts:

No, non lo sono.

Naturalmente, un compilatore normale in questo caso dovrebbe mettere la dichiarazione della variabile all'interno del ciclo all'esterno del ciclo.

Penso solo che dovresti sempre fidarti del compilatore e fidarti di te stesso. È uno standard del compilatore che una variabile locale viene creata quando viene dichiarata e viene rimossa quando si esce dal blocco in cui è stata dichiarata. Quindi dovreste concentrarvi su questo principio in primo luogo e non aspettare che il compilatore migliori il vostro codice per voi.

Quindi io dico che se volete "fare meglio", andate in assemblatore, se avete bisogno di controllare tutto da soli... Dopo tutto, il caso che hai appena descritto non è niente di che. Ci sono cose molto più complicate. OOP è sicuramente controindicato per te. Non saprete se il compilatore ha degenerato o meno un particolare metodo virtuale in una chiamata regolare, o se ha tagliato un inutile controllo del puntatore... Cosa si può fare in un MQL gestito con tale paranoia? )

E modificare il codice per adattarlo alle peculiarità del compilatore (e a quelle immaginarie), a scapito della correttezza e dell'affidabilità del codice, non è ovviamente ciò che un buon programmatore dovrebbe fare. E qui stiamo parlando esattamente di scorrettezza del codice. La variabile deve essere dichiarata direttamente nel blocco in cui viene utilizzata.

 
Vict:

Amico, questo è solo selvaggiamente stupido, cosa c'è da commentare, una completa mancanza di comprensione di come funziona il debugger.

Tu lo fai.
 
Alexey Navoykov:
Tu lo fai.

Come all'asilo ))) Spiego per coloro che sono nel serbatoio: prima compiliamo g++ 1.cpp, non ci sono punti di rottura, il compilatore non sa nulla di loro. Poi eseguire il debugger: gdb a.out, e solo ora mettere punto di interruzione.

Ti rendi conto delle sciocchezze che hai detto?

 
Alexey Navoykov:

È possibile rilevare l'ottimizzazione solo compilando il codice o misurando le sue prestazioni. Questa è la prima cosa da fare. E calmati )

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()));
  }
//+------------------------------------------------------------------+
 
Ho scavato sotto il debugger per un codice simile, ma senza operatore utente nuovo, beh, ci potrebbero essere dei dubbi - l'operatore utente non è ottimizzato. Catturata una chiamata di malloc() da libc. Il risultato: stringa in loop - una chiamata prima di ogni stampa, fuori dal loop - una chiamata prima di un gruppo di stampe. Non c'è dubbio, solo la prima variante è migliore. Naturalmente, è possibile che qualcosa sia diverso in µl, ma è meglio essere guidati da lingue mature.
 
#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 Test (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;} \

Amico, la "barra spaziatrice" non funziona per te? Non è la prima volta che lo noto, o stai salvando dei byte sul tuo disco rigido? )

 
Alexey Navoykov:

Stai scherzando? È una situazione così banale per un compilatore che non c'è nulla di cui parlare. Ma non puoi essere così paranoico a riguardo. ) Anche se anche questo sta diventando insensato al giorno d'oggi. Dovrai provare duramente a battere l'ottimizzazione dei compilatori moderni.

p.s. Forse sono stato un po' eccitato dalla banalità qui, perché sto parlando di una stringa buffer. Ma è garantito il salvataggio in MQL, non solo all'interno del ciclo ma anche tra le chiamate di funzione. Questo argomento è stato discusso qui più di una volta

Ho il sospetto che l'autore di questa dichiarazione non sappia affatto come funzionano il processore, la memoria e il compilatore... Scommetto che qualsiasi tuo codice può essere accelerato almeno dieci volte, o anche centinaia di volte. A causa di tali codificatori di merda la maggior parte dei prodotti sono ora incredibilmente lenti su computer potenti con decine di core, mentre tu hai solo bisogno di pensare un po'... Ma alcuni pensano: "Perché pensare? Devi codificare..."

Per vostra informazione, nessun compilatore al momento ha imparato a capire cosa il programmatore voleva ottenere come risultato. Può srotolare alcuni cicli e ottimizzare alcuni accessi alla memoria per mantenere i dati nella cache del processore, ma se il codice non è stato ottimizzato per cominciare ed è scritto attraverso un solo punto, nessun compilatore può aiutarvi...

P.S. Leggete a vostro piacimento un libro divertente di Chris Kaspersky"Program Optimization Technique".Uso efficiente della memoria".

 
Alexey Volchanskiy:

Georges ha ragione, non è garantito.

E otteniamo una conversione implicita di warping da 'numero' a 'stringa


Ed è esattamente così che ci si libera dell'ambiguità e della deformazione.

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

È così che ho sempre fatto.

string st = (string)i;

E a che serve la statica? L'assegnazione funzionerà solo una volta nella prima iterazione.


Ho deciso di misurare la velocità di esecuzione.

   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());

Il risultato:

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

L'ha eseguito molte volte, il risultato è stabile, il codice con la dichiarazione di una variabile dopo il ciclo, funziona più velocemente

 
Alexey Navoykov:

Amico, la "barra spaziatrice" non funziona per te? Non è la prima volta che lo noto, o stai salvando dei byte sul tuo disco rigido? )

No, questo codice non è mio, l'ho raffinato un po' - ho copiato il codice per me stesso dal thread sulla "ricerca dei punti e virgola" e lo uso per le domande controverse, sono troppo pigro per cambiarlo,

Ho degli spazi e sono troppo pigro per farlo ))))

ZS: datemi un codice modello, lo copierò a me stesso, sarà come volete in futuro, sono in principio, non mi dà fastidio

ZS: qui 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);}
Motivazione: