Borrar una matriz de elementos definidos - página 15

 
Sergey Dzyublik:

Ya hubo una discusión sobre el operador [], que es de alguna manera demasiado lento para el lenguaje C++ como este. No pensé que fuera tan lento como para que ArrayCopy lo destrozara.

Esa es una pregunta aparte sobre los incrementos dentro de los operadores.

 
Stanislav Dray:

¿Por qué te arreglaste y me echaste? No es bueno.

No he echado a nadie. Lo que , lo he devuelto )))

 
Konstantin Nikitin:

No echó a nadie. Lo que lo devolvió ))))

Bueno, así que descargaste el 11, el mío es el 12 (abajo) y arreglaste el 11 y lo devolviste como el 13.

 
TheXpert:

Ya hubo una discusión sobre el operador [], que es de alguna manera demasiado lento para el lenguaje C++ como este. No pensé que fuera tan lento como para que ArrayCopy lo destrozara.

Esa es una pregunta aparte sobre los incrementos dentro de los operadores.

Ni siquiera hay operaciones innecesarias aquí. Si el bucle está en curso. No es necesario comprobar si el elemento actual está fuera de los límites cuando se está copiando. Estará dentro de los límites. Y no tiene sentido añadir algo, o sacar una variable más. Si por defecto, hay una i.
En fin, hay todo tipo de cosas triviales. Sólo para información

 
Stanislav Dray:

Bueno, así que descargaste el 11, el mío es el 12 (abajo) y arreglaste el 11 y lo devolviste como el 13.

No prestó atención. Reemplazar el archivo.

 

también dibujado en este despiadado concurso :-)

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

De nuevo, no lo he comprobado :-) debería funcionar...

 
Stanislav Dray:

Han recomendado pruebas que contienen errores (Semko y Pavlov) .

Gracias, lo he arreglado.

Maxim Kuznetsov:

también esbozado en este despiadado concurso :-)

De nuevo, no lo he comprobado :-) debería funcionar...

incluido, pero hay algo que falla en la primera 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 микросекунд
Archivos adjuntos:
 

Vuelvo a mi malentendida diferencia de tiempo de ejecución de casi el 100% idéntica en lógica y número de comprobaciones y sumas de dos bucles:

Así que, de nuevo, por qué esa variante del código 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;
     }

funciona más del doble de rápido que éste, que hace exactamente lo mismo:

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

¿Cuáles son las maravillas del compilador?
¿Es realmente posible un diseño así?

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

el compilador encuentra algún comando de búsqueda especial del ensamblador para el procesador? Pero hay una comprobación adicional i<j dentro, ¿no?

Porque lo mismo a través de for se ejecuta mucho más lento:

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

Adjunto el código del script de demostración

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 микросекунд

Así es como suele ocurrir. Estás ocupado con alguna basura innecesaria y descubres algo bastante interesante.

Desarrolladores, ¿podríais echar un vistazo al código ejecutable y ver a qué se debe esta diferencia?

Hay que entender la lógica del compilador para poder crear algoritmos más óptimos en el futuro.

Archivos adjuntos:
TestLoop.mq5  10 kb
 
Nikolai Semko

Interesante observación. y por el bien de interés, corrió el código

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:

Vuelvo a mi malentendida diferencia de tiempo de ejecución de casi el 100% idéntica en lógica y número de comprobaciones y sumas de dos bucles:

Así que, de nuevo, por qué esa variante del código de Kuznetsov:

funciona más del doble de rápido que uno que hace exactamente lo mismo:

¿Cuáles son las maravillas del compilador?
¿Es realmente posible que una construcción como esta:

el compilador encuentra algún comando de búsqueda especial del ensamblador para el procesador? Pero hay una comprobación adicional i<j dentro, ¿no?

Porque lo mismo a través de for se ejecuta mucho más lento:

Adjunto el código del script de demostración

Así es como suele ocurrir. Estás ocupado con alguna basura innecesaria y descubres algo bastante interesante.

Desarrolladores, ¿podríais echar un vistazo al código ejecutable y ver a qué se debe esta diferencia?

Hay que entender la lógica del compilador para poder crear algoritmos más óptimos en el futuro.

Creo que es un buen partido para las banderas:
http://osinavi.ru/asm/4.php

Y para los operadores/comparadores innecesarios...