Fehler, Irrtümer, Fragen - Seite 2667

 
Der von mir beschriebene Fehler ist also nicht von Interesse für die Entwickler, OK...
 
MT5-Bug (Build 2345) Ich konnte lange Zeit nicht verstehen, warum der Profiler zwar läuft und funktioniert, aber nirgendwo Ergebnisse angezeigt werden.
Es stellt sich heraus, dass der Profiler für das Skriptprojekt nur dann Ergebnisse anzeigt, wenn die Optimierung deaktiviert ist, wenn die Optimierung aktiviert ist, läuft alles, funktioniert, aber ohne Ergebnisse.
 
Sergey Dzyublik:
Ich hatte einen Fehler in MT5 (Build 2345) und verstand nicht, warum der Profiler zwar läuft und funktioniert, aber keine Ergebnisse angezeigt werden.
Es stellt sich heraus, dass der Profiler für das Skriptprojekt nur Ergebnisse anzeigt, wenn die Optimierung deaktiviert ist, wenn die Optimierung aktiviert ist, dann läuft alles und funktioniert, aber ohne Ergebnis.

Der Profiler funktioniert nicht für alle Indikatoren (ohne Optimierung). Ich habe zweimal im Forum darüber geschrieben und den Code per PM an die Entwickler geschickt - keine Antwort.

 
Ich habe mit dem Profiler in MT5 (Build 2345) gearbeitet,
Grob gesagt, habe ich mich gefragt, warum zwei Algorithmen bei unterschiedlichen Geschwindigkeiten am Ende das gleiche Ergebnis liefern, nämlich einen 1,7-fachen Drawdown im Optimierungsmodus.

#include <stl_vector.mqh>

// TickCounts: 850
vector<int>::move test_vector_move_return_assign_by_index(int n){
   vector<int> v(n);
   for(int i = 0; i < n; i++){
      v[i].UNREF  = i;
   }
   return v;
};

// TickCounts: 1450
vector<int>::move test_vector_move_return_push_back(int n){
   vector<int> v;
   // lazy implementation  
   v.reserve(n);                      
   for(int i = 0; i < n; i++){
      v.push_back(i);
   }
   return v;
};


void OnStart()
{
   for(int i = 0; i < 20000; i++){
       vector<int> v_int_move = test_vector_move_return_assign_by_index(1000);
   }
   
   for(int i = 0; i < 20000; i++){
      vector<int> v_int_move = test_vector_move_return_push_back(1000);
   }
}


So konnten wir praktische Erfahrungen mit dem MT5-Profiler sammeln und eine Reihe von Mängeln in seiner Funktionsweise feststellen.
Da nicht klar ist, ob die Entwickler an diesen Informationen interessiert sind, und man nicht stundenlang Zeit für die Lokalisierung von Fehlern aufwenden möchte, werden nur kurze Informationen über die gefundenen Probleme gegeben:

1) Es gibt keine Möglichkeit, die Geschwindigkeiten der verschiedenen Algorithmen zu vergleichen.
So kann ein Algorithmus, der dreimal so schnell ist wie andere, sowohl mit als auch ohne aktivierte Optimierung, im Profiler als der langsamste erscheinen.
Offensichtlich gibt es eine Art von Profiler-Overhead, der sich auf die Ausführungszeit von Algorithmen auswirkt. In diesem Fall hat es keinen Sinn, die Leistungsgeschwindigkeit von Algorithmen im Profiler zu vergleichen.

2) Falscher Zählwert in den Tooltips des Histogramms auf dem Bildschirm.
Der Profiler sagt, dass die Funktion 80K mal gestartet wurde und nicht 20K mal wie erwartet, zur gleichen Zeit innerhalb der Funktion für verschiedene Zeilen überschreitet Count mehrere Male, für einige Zeilen drei Mal und für andere zwei Mal.

3) Falscher Wert für Zeit in den Histogramm-Tooltips auf dem Bildschirm.
Es gibt Fälle, in denen der Profiler anzeigt, dass der Algorithmus in 99,90 % der Fälle in die Bedingung eintrat, obwohl dies in Wirklichkeit nur einmal bei 20 000 Durchläufen der Fall ist.

 

Das ist kein Fehler, sondern eher ein Kommentar!


mt 5 build 2340.

Als ich gestern das Datenverzeichnis öffnete, habe ich nicht bemerkt, dass der Ordner "Indicators" in den Ordner "Experts" verschoben wurde. Dann habe ich mt5 deaktiviert und heute wieder aktiviert, die Indikatoren können auch vom Navigator aus verwendet werden, als ob nichts passiert wäre. Wenn ich jedoch den Datenordner erneut öffne, gibt es einen leeren Indikatorenordner, und wenn ich einen Indikator dorthin verschiebe, wird er nicht im Navigator angezeigt. Sie wird nicht im Navigator angezeigt. Die Rückkehr des Ordners Indicators zurück zu MQL5\Indicators löst das Problem.

 

MT5 (Build 2347) Warum ist der Overhead so groß, wenn man ein Element nach dem anderen zu einem Array mit ArrayResize hinzufügt, wenn der Speicher für diese Elemente im Voraus reserviert wurde?

#define  K 1000
#define  M (1000 * K)

#define    SpeedTest(test_count,msg,EX)        {uint mss=GetTickCount(); ulong count=test_count;for(ulong ii=0;ii<count&&!_StopFlag;ii++){EX;} \
                                              printf("%-60s: loops=%i ms=%u",msg,count,GetTickCount()-mss);}
                                              
class A{
public:
   int data;
};

struct B{
   int data;
};

template<typename T>
void test1(const int test_count, const int array_size){
   SpeedTest(
   test_count,"Test Class ArrayResize all",
   {
      T class_array[];
      for(int i = 1; i <= array_size; i++){
         ArrayResize(class_array, array_size);
      }
   }
   )
};

template<typename T>
void test2(const int test_count, const int array_size){
   SpeedTest(
   test_count,"Test Class ArrayResize one by one with reserved memory",
   {
      T class_array[];
      ArrayResize(class_array, 1, array_size - 1);
      for(int i = 2; i <= array_size; i++){
         ArrayResize(class_array, i);
      }
   }
   )
};

void OnStart()
{
  const int test_count = 5*K;
  const int array_size = 5*K;  
  
  test1<int>(test_count, array_size);            // Avg time: 100
  test2<int>(test_count, array_size);            // Avg time: 190
  test1<int>(test_count, array_size);
  test2<int>(test_count, array_size);
  test1<int>(test_count, array_size);
  test2<int>(test_count, array_size);
  test1<int>(test_count, array_size);
  test2<int>(test_count, array_size);
  
printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
  test1<A>(test_count, array_size);              // Avg time: 810
  test2<A>(test_count, array_size);              // Avg time: 1460
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  test1<A>(test_count, array_size);
  test2<A>(test_count, array_size);
  
printf("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
  test1<B>(test_count, array_size);              // Avg time: 110
  test2<B>(test_count, array_size);              // Avg time: 770
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
  test1<B>(test_count, array_size);
  test2<B>(test_count, array_size);
}

Bitte erwägen Sie die Verbesserung des internen Reservierungsalgorithmus mit ArrayResize.

Bei Klassen können wir beispielsweise davon ausgehen, dass sie neben dem Konstruktoraufruf eine Art "internes Register in Listen" durchführen.
Und im Rahmen der Reservierung mit ArrayResize kann man neben der direkten Speicherzuweisung versuchen, den Prozess zu optimieren:
- Daten aus dem benachbarten erstellten Element übernehmen (z. B. Zeiger auf eine virtuelle Funktionstabelle);
- eine Vorabregistrierung oder eine Platzreservierung für die "interne Registrierung" von Klassen, die noch nicht erstellt wurden;

 
Sergey Dzyublik:

MT5 (Build 2347) Warum ist der Overhead so groß, wenn man ein Element nach dem anderen zu einem Array mit ArrayResize hinzufügt, wenn der Speicher für diese Elemente im Voraus reserviert wurde?

Selbst das hilft nicht.

      ArrayResize(class_array, 1, array_size - 1);
      for(int i = 0; i < array_size; i++){
//         ArrayResize(class_array, i);
         ArrayResize(class_array, i, array_size - 1);

Es macht einfach keinen Sinn. Anstatt sich zu beschleunigen, wird sie nur langsamer.


ZZZ Seltsam, das Ergebnis des Beispiels aus der Dokumentation ist Null.

--- Test Fast: ArrayResize(arr,100000,100000)
1. ArraySize(arr)=100000 Time=0 ms
2. ArraySize(arr)=200000 Time=0 ms
3. ArraySize(arr)=300000 Time=0 ms
---- Test Slow: ArrayResize(slow,100000)
1. ArraySize(slow)=100000 Time=0 ms
2. ArraySize(slow)=200000 Time=0 ms
Документация по MQL5: Операции с массивами / ArrayResize
Документация по MQL5: Операции с массивами / ArrayResize
  • www.mql5.com
При успешном выполнении функция возвращает количество всех элементов, содержащихся в массиве после изменения размера; в противном случае возвращает -1 и массив не меняет размеры. Если ArrayResize() применена к статическому массиву, таймсерии или индикаторному буферу, то размер массива остается прежним – такие массивы не могут быть...
 
Sergey Dzyublik :
Arbeitet mit Profiler in MT5 (Build 2345),
Grob gesagt, habe ich mich gefragt, warum zwei Algorithmen, die am Ende das gleiche Ergebnis liefern, mit unterschiedlicher Geschwindigkeit laufen, nämlich mit einem Drawdown von 1,7 Mal im Optimierungsmodus.


...

Leider ist dieser Langzeit-Profiler für jedes wichtige Projekt unbrauchbar. Ich habe bereits versucht, dies zu melden, aber die Entwickler hatten kein Interesse daran.
 
Sergey Dzyublik :

MT5 (Build 2347) Warum ist der Overhead so groß, wenn man ein Element nach dem anderen zu einem Array mit ArrayResize hinzufügt, wenn der Speicher für diese Elemente im Voraus reserviert wurde?

Wenn Sie vergleichen wollen, sollten Sie das tun:

 void test1 ( const int test_count, const int array_size){
   SpeedTest(
   test_count,"Test Class ArrayResize all",
   {
      T class_array[];
       for ( int i = 0 ; i < array_size; i++){
         ArrayResize (class_array,  i );
      }
   }
   )
 
Alain Verleyen:

Wenn Sie vergleichen wollen, sollten Sie das tun:

Auf meiner Seite war der Vergleich so, wie er sein sollte.
Ich weiß, wie viele Elemente in das Array eingefügt werden sollen, und statt sie alle auf einmal zu erstellen, reserviere ich Speicher für nicht erstellte Elemente.
Das Problem ist, wenn ich Speicher reservieren und Array-Elemente nacheinander zu erstellen, dauert es viele Male länger als nur erstellen sie alle auf einmal.
Bei Strukturen ist es also 7 Mal langsamer.
Und bei den Datentypen class und int ist es doppelt so langsam.

Dies ist ein sehr großer Unterschied, den die Entwickler meines Erachtens beseitigen können, wenn sie dies wünschen.