Limpar um conjunto de elementos definidos - página 15

 
Sergey Dzyublik:

Já havia uma discussão sobre [] operador, que de alguma forma é lento demais para uma linguagem C++ como esta. Não achei que fosse tão lento que o ArrayCopy pudesse desfazê-lo.

Essa é uma pergunta à parte sobre os incrementos dentro dos operadores.

 
Stanislav Dray:

Por que você se consertou e me expulsou? Não é bom.

Eu não joguei ninguém fora. O que , eu devolvi ))))

 
Konstantin Nikitin:

Não jogou ninguém fora. O que você retornou ))))

bem, então você fez o download do 11º, o meu é o 12º (abaixo) e você fixou o 11º e o devolveu como o 13º.

 
TheXpert:

Já havia uma discussão sobre [] operador, que de alguma forma é lento demais para uma linguagem C++ como esta. Não achei que fosse tão lento que o ArrayCopy pudesse desfazê-lo.

Essa é uma pergunta à parte sobre os incrementos dentro dos operadores.

Aqui não há nem mesmo operações desnecessárias. Se o looping estiver em andamento. Não há necessidade de verificar se o item atual está fora dos limites quando ele está sendo copiado. Estará dentro dos limites. E não faz sentido acrescentar algo ou puxar para cima mais uma variável. Se por padrão, há um i.
De qualquer forma, há todo tipo de coisas triviais. Só para informação

 
Stanislav Dray:

bem, então você fez o download do 11º, o meu é o 12º (abaixo) e você fixou o 11º e o devolveu como o 13º.

Não prestou atenção. Substituiu o arquivo.

 

também esboçada nesta competição impiedosa :-)

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

Novamente, não verificado :-) deve funcionar...

 
Stanislav Dray:

Ter recomendado testes contendo erros (Semko e Pavlov) .

Obrigado, consertou-o.

Maxim Kuznetsov:

também esboçada neste concurso impiedoso :-)

Novamente, não verificado :-) deve funcionar...

incluído, mas há algo errado com a primeira 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 микросекунд
Arquivos anexados:
 

Volto à minha diferença incompreendida no tempo de execução de quase 100% idêntica em lógica e número de verificações e somas de dois loops:

Então, mais uma vez, por que uma tal variante do 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 mais do dobro da velocidade daquele que faz exatamente a mesma coisa:

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

Quais são as maravilhas do compilador?
Será realmente possível um projeto desse tipo?

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

o compilador encontra algum comando especial de busca da montadora para o processador? Mas há uma verificação adicional i<j dentro, não há?

Porque a mesma coisa é executada muito mais lentamente:

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

Eu anexo o código do roteiro de demonstração

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

É assim que acontece com freqüência. Você está ocupado com algumas porcarias desnecessárias e descobre algo bastante interessante.

Desenvolvedores, vocês poderiam dar uma olhada no código executável e ver o que faz essa diferença?

Você precisa entender a lógica do compilador para criar algoritmos mais otimizados no futuro.

Arquivos anexados:
TestLoop.mq5  10 kb
 
Nikolai Semko

Observação interessante. e por uma questão de interesse, executou o 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:

Volto à minha diferença incompreendida no tempo de execução de quase 100% idêntica em lógica e número de verificações e somas de dois loops:

Então, mais uma vez, por que uma tal variante do código de Kuznetsov:

funciona mais do dobro da velocidade de um que faz exatamente a mesma coisa:

Quais são as maravilhas do compilador?
É realmente possível uma construção como esta:

o compilador encontra algum comando especial de busca da montadora para o processador? Mas há uma verificação adicional i<j dentro, não há?

Porque a mesma coisa é executada muito mais lentamente:

Eu anexei o código do roteiro de demonstração

É assim que acontece com freqüência. Você está ocupado com algumas porcarias desnecessárias e descobre algo bastante interessante.

Desenvolvedores, vocês poderiam dar uma olhada no código executável e ver o que faz essa diferença?

Você precisa entender a lógica do compilador a fim de criar algoritmos mais otimizados no futuro.

Acho que é uma boa combinação para as bandeiras:
http://osinavi.ru/asm/4.php

E para os operadores/comparações desnecessárias...