Merkmale der Sprache mql5, Feinheiten und Techniken - Seite 84

 
Alain Verleyen:

Können Sie den Benchmark-Code zur Verfügung stellen, um dies zu demonstrieren?

#define  BENCH(A)                                                              \
{                                                                             \
  const ulong StartTime = GetMicrosecondCount();                              \
  A;                                                                          \
  Print("Time[" + #A + "] = " + (string)(GetMicrosecondCount() - StartTime)); \
}

double Bench1( const int Size, const string Str )
{
  double Tmp = 0;
  
  for (int i = 0; i < Size; i++)
    Tmp += (double)Str;

  return(Tmp);
}

double Bench2( const int Size, const string Str )
{
  double Tmp = 0;;
  
  for (int i = 0; i < Size; i++)
    Tmp += StringToDouble(Str);

  return(Tmp);
}

double Bench3( const int Size, const string Str )
{
  double Tmp = 0;
  
  for (int i = 0; i < Size; i++)
    Tmp += StringToDouble2(Str); // https://www.mql5.com/ru/forum/170952/page83#comment_7121066

  return(Tmp);
}

void OnStart()
{  
  const string Str = "123.456";
  
  BENCH(Print(Bench1(1 e7, Str)));
  BENCH(Print(Bench2(1 e7, Str)));
  BENCH(Print(Bench3(1 e7, Str)));
}


Ergebnis(Freigabe)

1234559999.924436
Time[Print(Bench1(1 e7,Str))] = 1656182
1234559999.924436
Time[Print(Bench2(1 e7,Str))] = 1639179
1234559999.924436
Time[Print(Bench3(1 e7,Str))] = 147382


Und so sieht es aus, wenn Sie das Programm im Profiling-Modus ausführen

1234559999.924436
Time[Print(Bench1(1 e7,Str))] = 1757705
1234559999.924436
Time[Print(Bench2(1 e7,Str))] = 1877177
1234559999.924436
Time[Print(Bench3(1 e7,Str))] = 4578266

Leider kann man dem Profiler in diesem Fall nicht trauen.

 
fxsaber:


Ergebnis ( Freigabe )


HH Und so sieht es aus, wenn ich es im Profiling-Modus ausführe

Es ist nicht nur unmöglich, dem Profiler in diesem Fall zu glauben, sondern Bench1 läuft 10 Mal schneller als in der Release-Version!

Vielen Dank dafür.

Ergebnis ( Freigabe )

Time [Bench1( 1 e7,Str)] = 1680754
Time [Bench2( 1 e7,Str)] = 1646789
Time [Bench3( 1 e7,Str)] = 143408     more then 10 times faster !!! 

Getestet mit Expert Advisor nach Strategie.

2018.04.16 14:24:28.049    Core 1    OnTester result 39725470 (µs bench1)
2018.04.16 14:26:14.629    Core 1    OnTester result 39270950 (µs bench2)
2018.04.16 14:27:13.566    Core 1    OnTester result 20467067 (µs bench3)

Weitere 2 Mal schneller (aber nicht mehr als 10 Mal schneller, was sicherlich auf die Compiler-Optimierung zurückzuführen ist).

Dateien:
170952.mq5  6 kb
 
Alain Verleyen:

Getestet mit einem Strategieberater.

2018.04.16 14:24:28.049    Core 1    OnTester result 39725470 (µs bench1)
2018.04.16 14:26:14.629    Core 1    OnTester result 39270950 (µs bench2)
2018.04.16 14:27:13.566    Core 1    OnTester result 20467067 (µs bench3)

Es ist immer noch 2-mal schneller (aber nicht mehr als 10-mal schneller, was natürlich auf die Compiler-Optimierung zurückzuführen ist).

Sie messen die Zeit für die Tick-Erzeugung, nicht nur für die OnTick-Berechnung.

Hier ist nur die OnTick-Messung

#define  PROFILER_OnTick // Замеряет чистое время выполнения всех OnTick - немного замедляет общую работу
#include <TesterBenchmark.mqh> // https://www.mql5.com/ru/code/18804

input int bench=1;// between 1 and 3

void OnTick()
{
  static const string Str = "123.456";

  switch(bench)
  {
    // https://www.mql5.com/ru/forum/170952/page84#comment_7121207
    case 1 : Bench1(1, Str); break;
    case 2 : Bench2(1, Str); break;
    case 3 : Bench3(1, Str); break;
  }  
}


Bank1

i = 0 Pass = 0 OnTester = 3.729 s.: OnTick Profiler: Count = 7197033, Interval = 1.895 s., 3796990.9 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 1 Pass = 1 OnTester = 3.843 s.: OnTick Profiler: Count = 7197033, Interval = 1.950 s., 3690523.1 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795


Sitzbank3

i = 0 Pass = 0 OnTester = 2.280 s.: OnTick Profiler: Count = 7197033, Interval = 0.631 s., 11404799.6 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795
i = 1 Pass = 1 OnTester = 2.340 s.: OnTick Profiler: Count = 7197033, Interval = 0.640 s., 11242184.6 unit/sec , Agent = C:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000 build = 1795


Um das Dreifache. Sie können nicht 10-mal schneller werden, weil Sie die BenchX-Funktion mehrfach aufrufen. StringToDouble2 selbst ist tatsächlich 10 Mal schneller.

 
fxsaber:

Sie messen die Zeit noch für die Erzeugung von Ticks, nicht nur für die Berechnung von OnTick.

...

Sie haben Recht.

Ich bin wirklich überrascht, dass es 10x schneller ist, aber Ihre Funktion kann nur verwendet werden, wenn Sie wissen, dass die Zeichenfolge einen gültigen Doppelwert enthält.

2018.04.16 17: 14: 16.183 170952_180416 (EURUSD, H1) StringToDouble2 (abcdef) = 5456784.0

 
Aleksey Vyazmikin:

Danke, aber auch dieses Skript speichert nicht korrekt.

Auf meinem Monitor ist die Begrenzung auf der rechten Seite mit einer vertikalen Linie markiert, und der Screenshot liegt weit jenseits dieser Linie.

Ich zitiere die Antwort des Dienstesk:

In diesem Fall sollte die ChartScreenShot-Hilfe wörtlich genommen werden

align_mode=ALIGN_RIGHT

[in] Modus für eine schmale Screenshot-Ausgabe. Wert der Aufzählung ENUM_ALIGN_MODE. ALIGN_RIGHT gibt die Ausrichtung am rechten Rand an (Ausgabe vom Ende her). ALIGN_LEFT gibt die linke Ausrichtung an.

Das heißt, wenn Sie die Ausrichtung ALIGN_RIGHT angeben, wird das Diagramm zwangsweise an den rechten Rand gescrollt, was der Ausführung des Befehls

ChartNavigate(0,CHART_END,0);

Dieses Verhalten wurde vor vielen Jahren eingeführt (also historisch), als es noch keine ChartNavigate()-Funktion gab. Die Einstellung align_mode=ALIGN_RIGHT garantiert, dass genau der rechte Rand des Diagramms entfernt wird.

Als die Funktion ChartNavigate() hinzugefügt wurde, wurde das Verhalten der Funktion ChartScreenShot nicht geändert.

Wenn Sie also den gewünschten Effekt erzielen wollen (das Diagramm wird nicht zum rechten Rand gescrollt), verwenden Sie den Wert ALIGN_LEFT für den Parameter align_mode.

 
Alain Verleyen:

kann Ihre Funktion nur verwendet werden, wenn Sie wissen, dass die Zeichenkette einen gültigen Double-Wert enthält.

2018.04.16 17: 14: 16.183 170952_180416 (EURUSD, H1) StringToDouble2 (abcdef) = 5456784.0

Behoben, jetzt funktioniert es wie das Original

#define  PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{    
  const string Str[] = {"123.456", "-asdf1234", "12as", ".34 a", "..23", "1.."};

  for (int i = 0; i < ArraySize(Str); i++)
  {
    PRINT(Str[i]);
    
    PRINT((double)Str[i]);
    PRINT(StringToDouble2(Str[i])); // https://www.mql5.com/ru/forum/170952/page83#comment_7121066
    
    Print("");
  }
}
 

Wenn Sie die hervorgehobene Konstante entfernen, wird sich die Ausführungszeit der Funktion verdoppeln. Dies zeigt, dass der Compiler nicht immer optimalen Code erzeugt und diese Art von Hinweisen benötigt.

 
fxsaber:

Wenn wir das markierte const entfernen, verdoppelt sich die Laufzeit der Funktion. Dies zeigt, dass der Compiler nicht immer einen optimalen Code erzeugt und diese Art von Hinweisen benötigt.

Interessant, danke.

Bitte bearbeiten Sie Ihren Code nicht mehr, wenn Sie bereits eine Antwort erhalten haben. Ich habe keine Benachrichtigung erhalten, dass Sie ihn aktualisiert haben.

 
fxsaber:

Wenn wir das markierte const entfernen, verdoppelt sich die Laufzeit der Funktion. Dies zeigt, dass der Compiler nicht immer einen optimalen Code erzeugt und diese Art von Hinweisen benötigt.

Sehr interessant...
Haben Sie eine Idee, warum das passiert?

Was ist der Mechanismus?

 

Um die Breite eines mit MQL5 aufgenommenen Screenshots zu bestimmen, der alle Balken für einen bestimmten Zeitraum enthält, wird die folgende Lösung angeboten.

Als Besonderheit hat sich herausgestellt, dass die Breite des Screenshots bei unterschiedlicher Annäherung an das Diagramm korrigiert werden muss.

Es stellte sich heraus, dass die tatsächlichen "Koeffizienten" für die Variante mit und ohne Skala unterschiedlich waren (speziell für mich).

 if (Use_Shakala==false)
 
 {
   ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,0);//Показывать или нет ценовую шкалу
   int TotalPixel=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);   // Ширина графика в пикселях
   int WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));            // сколько пикселей между барами
   int FirstBar=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);   // номер первого (левого) бара на экране
   int VisibleBars=(int)ChartGetInteger(0,CHART_VISIBLE_BARS);     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(-1);              // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(-1):((FirstBar-BarNr)*WidthBar);  // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar<0)?(-1):LeftPixelOfBar+WidthBar-1;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel-1;  // проверяем не за пределами ли экрана 

      if (Zoom==0)ZoomX=6;
      if (Zoom==1)ZoomX=5;
      if (Zoom==2)ZoomX=5;
      if (Zoom==3)ZoomX=4;
      if (Zoom==4)ZoomX=2;
      if (Zoom==5)ZoomX=0;

  pp=WidthBar*((Shift_Start-Shift_Stop)*(-1)+2)+ZoomX;
}

  if (Use_Shakala==true)
  {
   ChartSetInteger(0,CHART_SHOW_PRICE_SCALE ,1);//Показывать или нет ценовую шкалу
   int TotalPixel=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);   // Ширина графика в пикселях
   int WidthBar=int(1<<ChartGetInteger(0,CHART_SCALE));            // сколько пикселей между барами
   int FirstBar=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);   // номер первого (левого) бара на экране
   int VisibleBars=(int)ChartGetInteger(0,CHART_WIDTH_IN_BARS);     // количество видимых баров на экране
   int BarNr= FirstBar-(Shift_Start-Shift_Stop)*(-1);              // номер искомого бара, допустим на 12 баров правее самого левого бара 
   int LeftPixelOfBar=((FirstBar-BarNr)>=VisibleBars || FirstBar<BarNr)?(-1):((FirstBar-BarNr)*WidthBar);  // левый пиксель искомого бара, если бара нет на экране тогда -1
   int RightPixelOfBar =(LeftPixelOfBar<0)?(-1):LeftPixelOfBar+WidthBar-1;                                 //правый пиксель искомого бара, если бара нет на экране тогда -1
   if (RightPixelOfBar>=TotalPixel) RightPixelOfBar=TotalPixel-1;  // проверяем не за пределами ли экрана 

      if (Zoom==0)ZoomX=1;
      if (Zoom==1)ZoomX=1;
      if (Zoom==2)ZoomX=1;
      if (Zoom==3)ZoomX=3;
      if (Zoom==4)ZoomX=2;
      if (Zoom==5)ZoomX=0;    
  pp=WidthBar*((Shift_Start-Shift_Stop)*(-1)+2-0.5)+ZoomX+Schkala;
  
  }
//pp 		 - ширина скриншота
//Shift_Start    - номер левого бара, который целиком должен попасть на скрин
//Shift_Stop     - номер правого бара, который целиком должен попасть на скрин
//Schkala        - ширина цифровой шкалы по методу fxsaber
//Zoom           - степень приближение экрана