Erreurs, bugs, questions - page 2667

 
bug MT5 (build 2345) pendant longtemps, je n'ai pas pu comprendre pourquoi le profileur fonctionne, mais aucun résultat n'est affiché nulle part.
Il s'avère que le profileur du projet de script n'affiche les résultats que lorsque l'optimisation est désactivée, si l'optimisation est activée, tout tourne, fonctionne, mais sans aucun résultat.
 
Sergey Dzyublik:
J'ai eu un bug de MT5 (build 2345) et je n'ai pas compris pourquoi le profiler tourne et fonctionne mais aucun résultat n'est affiché.
Il s'avère que le profileur du projet de script ne montre des résultats que lorsque l'optimisation est désactivée, si l'optimisation est activée, tout fonctionnera mais sans aucun résultat.

Le profileur ne fonctionne pas pour tous les indicateurs (sans optimisation). J'ai écrit à ce sujet deux fois sur le forum, j'ai envoyé le code aux développeurs dans un MP - pas de réponse.

 
J'ai travaillé avec le profileur dans MT5 (build 2345),
En gros, je me demandais pourquoi deux algorithmes donnant le même résultat au final à des vitesses différentes, un drawdown de 1,7x en mode optimisation.

#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);
   }
}


Nous avons ainsi pu acquérir une expérience pratique du profileur MT5 et détecter un certain nombre de défauts dans son fonctionnement.
Comme il n'est pas certain que les développeurs soient intéressés par ces informations, et qu'il n'y a aucune envie de passer des heures à localiser les bogues, seules de brèves informations sur les problèmes détectés seront données :

1) Il n'y a aucun moyen de comparer les vitesses des différents algorithmes.
Ainsi, un algorithme qui est trois fois plus rapide que les autres, que l'optimisation soit activée ou non, peut apparaître comme le plus lent dans le profileur.
Apparemment, il existe une sorte de surcharge du profileur, qui affecte le temps d'exécution des algorithmes. Dans ce cas, il est inutile de comparer la vitesse d'exécution des algorithmes dans le profileur.

2) Valeur de comptage incorrecte dans les infobulles de l'histogramme à l'écran.
Le profileur indique que la fonction a été lancée 80K fois et non 20K fois comme prévu, de la même manière le compte est dépassé de plusieurs fois pour différentes chaînes de caractères, trois fois pour certaines chaînes et deux fois pour d'autres.

3) Valeur incorrecte du temps dans les infobulles de l'histogramme à l'écran.
Il y a des cas où le profileur montre que l'algorithme est entré dans la condition 99,90% des fois, et cela ne se produit en fait qu'une fois sur 20K passages.

 

Ce n'est pas un bug, c'est plutôt une observation !


mt 5 build 2340.

Hier, lorsque j'ai ouvert Data Directory, je n'ai pas remarqué que le dossier Indicateurs avait été déplacé vers le dossier Experts. J'ai ensuite désactivé mt5 et l'ai réactivé aujourd'hui, les indicateurs peuvent également être utilisés depuis le Navigateur comme si rien ne s'était passé. Cependant, si je rouvre le dossier de données, un dossier Indicateurs vide apparaît et si j'y déplace un indicateur, il n'apparaîtra pas dans le Navigateur. Il n'apparaîtra pas dans le Navigateur. Le retour du dossier Indicateurs à MQL5\Indicators résout le problème.

 

MT5 (build 2347) Pourquoi une si grande surcharge lors de l'ajout d'un élément à la fois à un tableau en utilisant ArrayResize, si la mémoire a été réservée pour eux à l'avance ?

#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);
}

Veuillez envisager d'améliorer l'algorithme de réservation interne avec ArrayResize.

Par exemple, pour les classes, nous pouvons supposer qu'elles effectuent une sorte de "registre interne dans les listes" en plus de l'appel au constructeur.
Et dans le cadre de la réservation avec ArrayResize, outre l'allocation directe de mémoire, vous pouvez essayer d'optimiser le processus :
- prendre des données de l'élément créé adjacent (par exemple, un pointeur vers une table de fonctions virtuelles) ;
- pré-exécuter ou réserver un espace pour "l'inscription interne" de classes qui n'ont pas encore été créées ;

 
Sergey Dzyublik:

MT5 (build 2347) Pourquoi une si grande surcharge lors de l'ajout d'un élément à la fois à un tableau en utilisant ArrayResize, si la mémoire a été réservée pour eux à l'avance ?

Même ça, ça n'aide pas.

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

Ça n'a aucun sens. Au lieu d'accélérer, il ralentit.


ZZ C'est étrange, le résultat de l'exécution de l'exemple de la documentation est zéro.

--- 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 :
Fonctionne avec le profileur dans MT5 (build 2345),
En gros, je me demandais pourquoi deux algorithmes, donnant le même résultat au final, tournent à des vitesses différentes, le drawdown est 1,7 fois en mode optimisation.


...

Malheureusement, ce profileur de longue durée est inutile pour tout projet important. J'ai déjà essayé de le signaler, mais les développeurs n'y ont pas prêté attention.
 
Sergey Dzyublik :

MT5 (build 2347) Pourquoi une si grande surcharge lors de l'ajout d'un élément à la fois à un tableau en utilisant ArrayResize, si la mémoire a été réservée pour eux à l'avance ?

Si vous voulez comparer, il faut le faire :

 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:

Si vous voulez comparer, il faut le faire :

De mon côté, la comparaison était ce qu'elle était censée être.
Je sais combien d'éléments seront placés dans le tableau et au lieu de les créer tous en même temps, je réserve de la mémoire pour les éléments non créés.
Le problème est que si je réserve de la mémoire et que je crée les éléments du tableau un par un, cela prend beaucoup plus de temps que de les créer tous en même temps.
Pour les structures, il est donc 7 fois plus lent.
Et il est deux fois plus lent pour les types de données class et int.

Il s'agit d'une très grande différence, que les développeurs peuvent, à mon avis, éliminer s'ils le souhaitent.

 
Sergey Dzyublik:

Le problème est que si je réserve de la mémoire et que je crée les éléments du tableau un par un, cela prend plusieurs fois plus de temps que de les créer tous en même temps.

Je n'avais pas remarqué ça dans le code. Cela s'explique alors, car il n'y a qu'un seul si déclenché, où si la taille n'a pas changé, on sort.

Raison: