Очистка массива от заданного (ых) элементов - страница 15

 
Sergey Dzyublik:

про оператор [] уже был разговор, что он как-то слишком медленный для C++ подобного языка. Не думал что прям настолько что ArrayCopy его рвет как тузик грелку.

про инкремент внутри оператора отдельный вопрос.

 
Stanislav Dray:

Чтож вы себя исправили а меня выкинули ? нехорошо

Ни кого не выкидывал. Что скачал, то и вернул )))

 
Konstantin Nikitin:

Ни кого не выкидывал. Что скачал, то и вернул )))

ну так вы скачали 11-й, мой -12-й(ниже), а вы исправили 11-й и вернули как 13-й.

 
TheXpert:

про оператор [] уже был разговор, что он как-то слишком медленный для C++ подобного языка. Не думал что прям настолько что ArrayCopy его рвет как тузик грелку.

про инкремент внутри оператора отдельный вопрос.

Да тут даже лишние операции ни к чему. Если идет прогон по циклу. Незачем сравнивать при копировании текущего элемента, вышел он за пределы, или нет. Будет в пределах. Да и что-то складывать смысла, так-же нет и тянуть еще одну переменную. Если по умолчанию, есть i.
Короче так мелочевка всякая. Чисто для инфы написал

 
Stanislav Dray:

ну так вы скачали 11-й, мой -12-й(ниже), а вы исправили 11-й и вернули как 13-й.

Не обратил внимание. Заменил файл.

 

ещё набросал в этот беспощадный конкурс :-)

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

Опять-же не проверял :-) должно по идее работать..

 
Stanislav Dray:

Закоментил тесты содержащие ошибки (Semko и Pavlov) .

Спасибо, исправил.

Maxim Kuznetsov:

ещё набросал в этот беспощадный конкурс :-)

Опять-же не проверял :-) должно по идее работать..

включил, но с первым вариантом что-то не так

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 микросекунд
Файлы:
 

Возвращаюсь к непонятой для меня разницы во времени выполнения почти на 100 % одинаковых по логике и количеству проверок и сумм двух циклов:

Итак, повторяюсь, почему такой вариант из кода Кузнецова:

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

работает более чем в два раза быстрее, чем такой, делающий абсолютно тоже самое:

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

Что за чудеса компилятора?
Неужели для такой конструкции:

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

компилятор находит какую то особенную ассемблерную команду поиска для процессора? Но ведь внутри стоит дополнительная проверка i<j?

ведь тоже самое через for выполняется заметнее медленнее:

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

Код демонстрирующего скрипта прилагаю

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

Вот так часто бывает. Вроде занимаешься какой-то ненужной фигней и выясняешь для себя что-то весьма интересное.

Разработчики,  Вы можете глянуть исполняемый код, за счет чего такая разница?

Ведь нужно понимать логику компилятора, чтобы в дальнейшем создавать более оптимальные алгоритмы.

Файлы:
TestLoop.mq5  10 kb
 
Nikolai Semko

Интересное наблюдение. и ради интереса прогнал код

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:

Возвращаюсь к непонятой для меня разницы во времени выполнения почти на 100 % одинаковых по логике и количеству проверок и сумм двух циклов:

Итак, повторяюсь, почему такой вариант из кода Кузнецова:

работает более чем в два раза быстрее, чем такой, делающий абсолютно тоже самое:

Что за чудеса компилятора?
Неужели для такой конструкции:

компилятор находит какую то особенную ассемблерную команду поиска для процессора? Но ведь внутри стоит дополнительная проверка i<j?

ведь тоже самое через for выполняется заметнее медленнее:

Код демонстрирующего скрипта прилагаю

Вот так часто бывает. Вроде занимаешься какой-то ненужной фигней и выясняешь для себя что-то весьма интересное.

Разработчики,  Вы можете глянуть исполняемый код, за счет чего такая разница?

Ведь нужно понимать логику компилятора, чтобы в дальнейшем создавать более оптимальные алгоритмы.

думаю удачно совпали флаги:
http://osinavi.ru/asm/4.php

а для for лишние операторы/сравнения...

Причина обращения: