Deklarieren von Variablen hinter der Schleife oder innerhalb der Schleife? - Seite 2

 
Georgiy Merts:

Nein, das bin ich nicht.

Natürlich sollte ein normaler Compiler in diesem Fall eine Variablendeklaration innerhalb einer Schleife nach außen bringen.

Ich denke einfach, dass man dem Compiler und sich selbst immer vertrauen sollte. Es ist ein Compiler-Standard, dass eine lokale Variable bei ihrer Deklaration angelegt und bei Beendigung des Blocks, in dem sie deklariert wurde, wieder entfernt wird. Sie sollten sich also in erster Linie auf dieses Prinzip konzentrieren und nicht darauf warten, dass der Compiler Ihren Code für Sie verbessert.

Ich sage also, wenn Sie es "besser machen" wollen, gehen Sie zu Assembler, wenn Sie alles selbst kontrollieren müssen... Der Fall, den Sie gerade beschrieben haben, ist nämlich gar nichts. Es gibt viel kompliziertere Dinge. OOP ist für Sie definitiv kontraindiziert. Sie werden nicht wissen, ob der Compiler eine bestimmte virtuelle Methode zu einem regulären Aufruf degeneriert hat oder nicht, oder ob er eine unnötige Zeigerüberprüfung gestrichen hat... Was kann man in einer verwalteten MQL mit einer solchen Paranoia tun? )

Und die Anpassung des Codes an die Eigenheiten des Compilers (noch dazu an imaginäre) auf Kosten der Korrektheit und Zuverlässigkeit des Codes ist natürlich nicht das, was ein guter Programmierer tun sollte. Und hier geht es genau um die Fehlerhaftigkeit des Codes. Die Variable muss direkt in dem Block deklariert werden, in dem sie verwendet wird.

 
Vict:

Mann, das ist einfach total dumm, was gibt es da zu kommentieren, ein komplettes Unverständnis, wie der Debugger funktioniert.

Sie tun es.
 
Alexey Navoykov:
Sie tun es.

Wie im Kindergarten ))) Ich erkläre es für diejenigen, die im Tank sind: zuerst kompilieren wir g++ 1.cpp, dort gibt es keine Haltepunkte, der Compiler weiß nichts davon. Starten Sie dann den Debugger: gdb a.out, und setzen Sie erst jetzt einen Haltepunkt.

Verstehen Sie, was für einen Unsinn Sie gesagt haben?

 
Alexey Navoykov:

Sie können eine Optimierung nur feststellen, indem Sie den Code kompilieren oder seine Leistung messen. Das ist das Erste, was Sie tun sollten. Und beruhigen Sie sich)

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()));
  }
//+------------------------------------------------------------------+
 
Ich grub unter dem Debugger für ähnlichen Code, aber ohne Benutzer-Operator neu, gut, es könnte einige Zweifel sein - der Benutzer-Operator ist nicht optimiert. Es wurde ein Aufruf von malloc() von libc gefangen. Das Ergebnis: String in der Schleife - ein Aufruf vor jedem Druck, außerhalb der Schleife - ein Aufruf vor einer Reihe von Drucken. Es besteht kein Zweifel daran, dass nur die erste Variante besser ist. Es ist natürlich möglich, dass in µl etwas anders ist, aber es ist besser, sich an ausgereiften Sprachen zu orientieren.
 
#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;} \

Funktioniert die Leertaste bei Ihnen nicht? Das ist nicht das erste Mal, dass ich das bemerke. Oder speichern Sie Bytes auf Ihrer Festplatte? )

 
Alexey Navoykov:

Machst du Witze? Für einen Compiler ist das eine so triviale Situation, dass es keinen Grund gibt, darüber zu reden. Aber du kannst nicht so paranoid sein. ) Obwohl selbst das heutzutage sinnlos wird. Du wirst dich anstrengen müssen, um die Optimierung moderner Compiler zu schlagen.

p.s. Vielleicht war ich ein bisschen aufgeregt über die Trivialität im Falle des String-Puffers. Aber sie wird in MQL garantiert gespeichert, nicht nur innerhalb der Schleife, sondern auch zwischen Funktionsaufrufen. Dieses Thema wurde hier mehr als einmal diskutiert

Ich habe den Verdacht, dass der Autor dieser Aussage überhaupt nicht weiß, wie der Prozessor, der Speicher und der Compiler funktionieren... Ich wette, dass jeder Ihrer Codes mindestens um das Zehnfache oder sogar um das Hundertfache beschleunigt werden kann. Wegen solch beschissener Programmierer sind die meisten Produkte jetzt unglaublich langsam auf leistungsstarken Computern mit Dutzenden von Kernen, während Sie nur ein wenig denken müssen... Aber manche Leute denken: "Warum denken? Du musst kodieren..."

Zu Ihrer Information: Kein Compiler hat derzeit gelernt zu verstehen, was der Programmierer als Ergebnis haben wollte. Er kann einige Schleifen abrollen und einige Speicherzugriffe optimieren, um Daten im Cache des Prozessors zu halten, aber wenn der Code nicht von Anfang an optimiert wurde und durch eine Stelle geschrieben wird, kann Ihnen kein Compiler helfen...

P.S. Lesen Sie in Ruhe ein unterhaltsames Buch von Chris Kaspersky"Program Optimization Technique". Effiziente Speichernutzung".

 
Alexey Volchanskiy:

Georges hat recht, es ist nicht garantiert.

Und wir erhalten eine verzerrende implizite Umwandlung von 'Zahl' in 'String'


Und das ist genau die Art und Weise, wie man Zweideutigkeiten und Verzerrungen beseitigt.

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

So habe ich es immer gemacht.

string st = (string)i;

Die Zuweisung wird nur einmal in der ersten Iteration funktionieren.


Ich beschloss, die Geschwindigkeit der Ausführung zu messen.

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

Das Ergebnis:

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

Viele Male ausgeführt, das Ergebnis ist stabil, der Code mit der Deklaration einer Variablen nach der Schleife, funktioniert schneller

 
Alexey Navoykov:

Funktioniert die Leertaste bei Ihnen nicht? Das ist nicht das erste Mal, dass ich das bemerke. Oder speichern Sie Bytes auf Ihrer Festplatte? )

Nein, dieser Code ist nicht von mir, ich habe ihn ein wenig verfeinert - ich habe den Code für mich aus dem Thread über "Suche nach Semikolons" kopiert und verwende ihn für kontroverse Fragen, ich bin zu faul, ihn zu ändern,

Ich habe Lücken und bin zu faul, es zu tun ))))

ZS: geben Sie mir ein Modell-Code, kopieren Sie es mir, wird, wie Sie in Zukunft wollen, ich bin im Prinzip, es stört mich nicht

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