Effacement d'un tableau d'élément(s) défini(s) - page 15

 
Sergey Dzyublik:

Il y a déjà eu une discussion à propos de l'opérateur [], selon laquelle il est en quelque sorte trop lent pour un langage C++ comme celui-ci. Je ne pensais pas que c'était si lent qu'ArrayCopy puisse le démolir.

C'est une question distincte sur les incréments dans les opérateurs.

 
Stanislav Dray:

Pourquoi tu t'es arrangé tout seul et m'as jeté dehors ? Pas bon.

Je n'ai jeté personne dehors. Ce que , je l'ai renvoyé ;)))

 
Konstantin Nikitin:

Il n'a jeté personne dehors. Ce que , vous le rendez à ))))

donc vous avez téléchargé le 11, le mien est le 12 (ci-dessous) et vous avez corrigé le 11 et l'avez rendu comme le 13.

 
TheXpert:

Il y a déjà eu une discussion à propos de l'opérateur [], selon laquelle il est en quelque sorte trop lent pour un langage C++ comme celui-ci. Je ne pensais pas que c'était si lent qu'ArrayCopy puisse le démolir.

C'est une question distincte sur les incréments dans les opérateurs.

Il n'y a même aucune raison d'effectuer des opérations inutiles ici. Si le bouclage est en cours. Il n'est pas nécessaire de vérifier si l'élément actuel est hors limites lorsqu'il est copié. Il sera à l'intérieur des limites. Et il n'y a aucun sens à ajouter quelque chose, ou à tirer une variable de plus. Si par défaut, il y a un i.
Bref, il y a toutes sortes de choses banales. Pour information

 
Stanislav Dray:

donc vous avez téléchargé le 11, le mien est le 12 (ci-dessous) et vous avez corrigé le 11 et l'avez rendu comme le 13.

Je n'ai pas fait attention. J'ai remplacé le fichier.

 

également dessiné dans le cadre de ce concours impitoyable :-)

template <typename T>
int copyFilter1(const T &src[],T &dst[],T x)
{
        int i=0,j=0,k;
        int total=ArraySize(src);
        ArrayResize(dst,total);
        for(;;) {
                // считаем сколько копировать
                for(k=0;k<total && src[i]!=x;)
                        k++;
                // копируем
                if (k) {        
                        ArrayCopy(dst,src,j,i,k);
                        i+=k;
                        j+=k;
                        total-=k;
                }
                // пропускаем
                for(k=0;k<total && src[i]==x;) 
                        k++;
                if (k) {
                        i+=k;
                        total-=k;
                } else break;
        }
        ArrayResize(dst,j);
        return j;
}

template <typename T>
int copyFilter2(const T &src[],T &dst[],T x)
{
        int i=0,j=0,k;
        int total=ArraySize(src);
        ArrayResize(dst,total);
        for(;i<total;) {
                // копируем всё что не равно x
                for(;i<total && src[i]!=x;i++,j++)
                        dst[j]=src[i];
                // пропускаем всё что равно x
                for(;i<total && src[i]==x;)
                        i++;
        }
        ArrayResize(dst,j);
        return j;
}

Encore une fois, non vérifié :-) devrait fonctionner...

 
Stanislav Dray:

Ont recommandé des tests contenant des erreurs (Semko et Pavlov) .

Merci, c'est réparé.

Maxim Kuznetsov:

également esquissé dans ce concours impitoyable :-)

Je n'ai pas revérifié :-) ça devrait marcher...

inclus, mais il y a un problème avec la première variante

2018.11.15 06:19:01.929 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Pastushak   : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения - 141053 микросекунд
2018.11.15 06:19:01.934 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Korotky     : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   2494 микросекунд
2018.11.15 06:19:01.938 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Fedoseev    : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   1869 микросекунд
2018.11.15 06:19:01.941 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Semko       : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -    785 микросекунд
2018.11.15 06:19:01.945 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Nikitin     : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   2039 микросекунд
2018.11.15 06:19:01.952 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Vladimir    : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   4385 микросекунд
2018.11.15 06:19:01.961 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Peter       : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   7476 микросекунд
2018.11.15 06:19:01.965 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант fann95      : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   1255 микросекунд
2018.11.15 06:19:01.969 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Kuznetsov1  : Контрольная сумма = 7219.502578; элементов - 1000000; время выполнения -   2016 микросекунд
2018.11.15 06:19:01.975 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Kuznetsov2  : Контрольная сумма = 7225.756203; элементов - 998992; время выполнения -   3965 микросекунд
2018.11.15 06:19:01.975 ArrayDeleteValue__13 (.BrentCrud,M1)    
2018.11.15 06:19:01.975 ArrayDeleteValue__13 (.BrentCrud,M1)    === Порядок в массиве не сохраняется ===
2018.11.15 06:19:01.978 ArrayDeleteValue__13 (.BrentCrud,M1)    вариант Kuznetsov3  : Контрольная сумма = 7222.657252; элементов - 998992; время выполнения -    694 микросекунд
Dossiers :
 

Je reviens à ma différence incomprise de temps d'exécution de deux boucles presque 100% identiques en logique et en nombre de contrôles et de sommes :

Donc, encore une fois, pourquoi une telle variante du code de Kuznetsov :

    for(;;)
     {
      while(arr[i]!=x && i<j) i++;
      while(arr[j]==x && i<j) j--;
      if(i<j)
        {
         arr[i++]=arr[j--];
        }
      else break;
     }

fonctionne plus de deux fois plus vite que celui-ci, qui fait exactement la même chose :

   while(i<j)
     {
      if(arr[i]==x)
         if(arr[j]!=x) arr[i++]=arr[j--];
      else j--;
      else i++;
     }

Quelles sont les merveilles du compilateur ?
Est-ce vraiment possible pour un tel design :

while(arr[i]!=x && i<j) i++;

le compilateur trouve une commande spéciale de recherche de l'assembleur pour le processeur ? Mais il y a une vérification supplémentaire i<j à l'intérieur, n'est-ce pas ?

Parce que la même chose à travers pour est exécutée beaucoup plus lentement :

for (;;) if (arr[i]!=x && i<j) i++; else break;

Je joins le code du script de démonstration

2018.11.15 13:30:51.354 TestLoop (EURUSD,D1)    вариант while:    Контрольная сумма = 7697.499145747599; элементов - 998975; время выполнения = 771 микросекунд
2018.11.15 13:30:51.357 TestLoop (EURUSD,D1)    вариант for:      Контрольная сумма = 7697.499145747599; элементов - 998975; время выполнения = 1051 микросекунд
2018.11.15 13:30:51.360 TestLoop (EURUSD,D1)    вариант slow:     Контрольная сумма = 7697.499145747599; элементов - 998975; время выполнения = 1531 микросекунд

C'est ainsi que cela se passe souvent. Vous vous occupez de quelques déchets inutiles et vous découvrez quelque chose de plutôt intéressant.

Développeurs, pourriez-vous jeter un coup d'œil au code exécutable et voir ce qui fait cette différence ?

Vous devez comprendre la logique du compilateur afin de créer des algorithmes plus optimaux à l'avenir.

Dossiers :
TestLoop.mq5  10 kb
 
Nikolai Semko

Observation intéressante. et pour l'intérêt, j'ai exécuté le code

void OnStart()
{
     int array[], arr[];
     ArrayResize(arr,1000000);
     for(int i=0; i<1000000;i++)
          arr[i] = rand()%1000;

     int i=0;
     ulong t=GetMicrosecondCount();
     for(; i<1000000; i++)
          int j = arr[i];
     t = GetMicrosecondCount()-t;
     Print("FOR: ", t);
     
     t=GetMicrosecondCount();
     i=0;
     for(;;)
     {
          if( i>=1000000 )
               break;
          int j = arr[i];
          i++;
     }
     t = GetMicrosecondCount()-t;
     Print("FOR-1: ", t);
     
     t=GetMicrosecondCount();
     i=0;
     while(i<1000000)
     {
          int j = arr[i];
          i++;
     }
     t = GetMicrosecondCount()-t;
     Print("WHILE: ", t);
     
     t=GetMicrosecondCount();
     i=0;
     while(true)
     {
          if( i>=1000000 )
               break;
          int j = arr[i];
          i++;
     }
     t = GetMicrosecondCount()-t;
     Print("WHILE-1: ", t);
}


 
Nikolai Semko:

Je reviens à ma différence incomprise de temps d'exécution de deux boucles presque 100% identiques en logique et en nombre de contrôles et de sommes :

Donc, encore une fois, pourquoi une telle variante du code de Kuznetsov :

fonctionne plus de deux fois plus vite qu'une autre qui fait exactement la même chose :

Quelles sont les merveilles du compilateur ?
Est-ce vraiment possible pour une construction comme celle-ci :

le compilateur trouve une commande spéciale de recherche de l'assembleur pour le processeur ? Mais il y a une vérification supplémentaire i<j à l'intérieur, n'est-ce pas ?

Parce que la même chose à travers pour est exécutée beaucoup plus lentement :

Je joins le code du script de démonstration

C'est ainsi que cela se passe souvent. Vous vous occupez de quelques déchets inutiles et vous découvrez quelque chose de plutôt intéressant.

Développeurs, pourriez-vous jeter un coup d'œil au code exécutable et voir ce qui fait cette différence ?

Vous devez comprendre la logique du compilateur afin de créer des algorithmes plus optimaux à l'avenir.

Je pense que c'est un bon match pour les drapeaux :
http://osinavi.ru/asm/4.php

Et pour les opérateurs/comparaisons inutiles...