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

 

Scusate gente, l'ottimizzazione è stata disattivata nelle impostazioni del progetto

Codice:

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


Non ottimizzato

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

Con l'ottimizzazione

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

Con l'ottimizzazione sì, è il contrario, ho controllato molte volte

 
Aleksandr Matveev:

Dovresti prima imparare le basi e poi dimostrare il tuo punto di vista. Capireste il risultato senza alcun test, se aveste letto almeno un libro sul funzionamento della CPU e della memoria. Vi ho offerto il più ingegnoso e se volete avanzare un po' nella programmazione lo leggerete sicuramente.

Cosa c'entrano la memoria e la CPU? Si tratta di ottimizzazione, teorico libresco).

 
Igor Makanu:

Non è strano, bisogna essere in grado di testare gli operatori e le operazioni più semplici in MQL - perché dovrei aggiungere srand(GetTickCount()) al mio test? ?

;)

A proposito, guardate bene, il risultato nel vostro ciclo non è preso in considerazione in alcun modo, il che significa che può essere facilmente tagliato dal compilatore.

 
Alexey Navoykov:

A proposito, ho guardato attentamente, il risultato nel tuo ciclo non è preso in considerazione in alcun modo, quindi il compilatore può facilmente tagliarlo.

Rimosso anche rand() - il suo compilatore lo inlinea perfettamente, fatto un tale test:

#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;  test(N,"1. s1=rand()",s1=(string)tst);
   string s2;  test(N,"2. s2=rand()",s2=(string)tst);
   string s3;  test(N,"3. s3=rand()",s3=(string)tst);
   string s4;  test(N,"4. s4=rand()",s4=(string)tst);
   string s5;  test(N,"5. s5=rand()",s5=(string)tst);

   test(N,"1. q=rand()",string q=(string)tst);
   test(N,"2. q=rand()",string q=(string)tst);
   test(N,"3. q=rand()",string q=(string)tst);
   test(N,"4. q=rand()",string q=(string)tst);
   test(N,"5. q=rand()",string q=(string)tst);
  }
//+------------------------------------------------------------------+

2019.08.18 11:55:41.457 SpeedTest (EURUSD,H1) 1. s1=rand(): loops=100000000 ms=7672

2019.08.18 11:55:49.085 SpeedTest (EURUSD,H1) 2. s2=rand(): loops=100000000 ms=7625

2019.08.18 11:55:56.796 SpeedTest (EURUSD,H1) 3. s3=rand(): loops=100000000 ms=7719

2019.08.18 11:56:04.495 SpeedTest (EURUSD,H1) 4. s4=rand(): loops=100000000 ms=7703

2019.08.18 11:56:12.113 SpeedTest (EURUSD,H1) 5. s5=rand(): loops=100000000 ms=7610

2019.08.18 11:56:17.695 SpeedTest (EURUSD,H1) 1. q=rand(): loops=100000000 ms=5578

2019.08.18 11:56:23.362 SpeedTest (EURUSD,H1) 2. q=rand(): loops=100000000 ms=5672

2019.08.18 11:56:28.970 SpeedTest (EURUSD,H1) 3. q=rand(): loops=100000000 ms=5609

2019.08.18 11:56:34.637 SpeedTest (EURUSD,H1) 4. q=rand(): loops=100000000 ms=5672

2019.08.18 11:56:40.277 SpeedTest (EURUSD,H1) 5. q=rand(): loops=100000000 ms=5640


 
Alexey Navoykov:

Quindi sto dicendo, se vuoi "farlo bene", allora vai all'assemblatore. Se hai bisogno di controllare tutto da solo... 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 un particolare metodo virtuale in una chiamata regolare o ha tagliato un controllo inutile del puntatore... Cosa si può fare in un MQL gestito con questa paranoia? )

E adattare il codice 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 di scorrettezza del codice. Una variabile deve essere dichiarata direttamente nel blocco in cui viene utilizzata.

Ha ha ha... Alexey, tu affermi (diciamo "tu") che "OOP è decisamente controindicato" a uno dei principali adepti di OOP sul forum.

Il codice non deve essere adattato alle peculiarità del compilatore, ma alle peculiarità del PROPRIO pensiero. In questo caso, la dichiarazione di una variabile all'interno di un ciclo in teoria riduce l'efficienza. Perché secondo le convenzioni, la variabile deve essere creata ogni volta e distrutta ogni volta.

Non è nemmeno una questione di efficienza. Il codice solido è un codice trasparente, chiaro e facile da modificare e mantenere.

Personalmente non mi piace avere un sacco di variabili sparse in tutto il programma e dover cercare ogni volta dove viene creata una particolare variabile. Perciò, se possibile, cerco di dichiarare le variabili all'inizio della funzione, tutte insieme - solo per vedere dove vengono create e capire quando verranno eliminate.

In questo caso, l'esempio è solo molto breve. Quando ci sono decine di linee tra la creazione di una variabile e il suo utilizzo, e un mucchio di funzioni annidate - per me, è molto più affidabile quando la variabile è dichiarata fuori dal blocco, in anticipo.

 
pivalexander:

Scusate gente, l'ottimizzazione è stata disattivata nelle impostazioni del progetto

Codice:


Non ottimizzato

Con l'ottimizzazione

Con l'ottimizzazione, sì, è il contrario, l'ho controllato molte volte.

Nel tuo esempio, l'intero corpo del ciclo avrebbe potuto essere tagliato con l'ottimizzazione.

 

In generale, tutto si svolge come previsto, che non c'è bisogno di fare sciocchezze, cercando problemi inesistenti e creandone di reali.

Se hai prurito e pensi di essere un hacker figo, scrivi in assembler, oppure fatti da parte e lascia che il compilatore faccia il suo lavoro.

 
Aleksandr Matveev:

Nel tuo esempio, l'intero corpo del ciclo avrebbe potuto essere tagliato con l'ottimizzazione.

Il risultato dell'esecuzione con un corpo del ciclo vuoto, molto diverso, funziona molto più velocemente

Без оптимизации:
Test1, время выполнения: 0.027539 сек.

С оптимизацией:
Test1, время выполнения: 0.005448 сек.
 
Alexey Navoykov:

In generale, tutto si svolge come previsto, che non c'è bisogno di fare sciocchezze, cercando problemi inesistenti e creandone di reali.

Se hai prurito e pensi di essere un hacker figo, scrivi in assembler, altrimenti fatti da parte e lascia che il compilatore faccia il suo lavoro.

Il problema principale è proprio che non mi considero un coolhacker. Questo è il motivo per cui le variabili, secondo me, dovrebbero essere dichiarate al di fuori del ciclo. E meglio - all'inizio della funzione, tutto in una volta.

E solo i koolhousers possono dichiarare le variabili come necessario, all'interno del codice.

 
Georgiy Merts:

Il problema principale è proprio che non mi considero un coolhacker. Ecco perché le variabili, secondo me, dovrebbero essere dichiarate fuori dal ciclo. E preferibilmente all'inizio della funzione, tutto in una volta.

I Koolhacker possono dichiarare le variabili come necessario all'interno del codice.

Preferisco rompere il mio codice in blocchi logici e dichiarare le variabili necessarie in quei blocchi piuttosto che creare un mucchio di variabili all'inizio di una funzione, la maggior parte delle quali sono necessarie solo in un blocco, da qualche parte molto più in basso