C# нуб вопрос по производительности

Kent1331

Почему такой код работает значительно дольше

private List<double> sort_list(List<double> inlist, int count_limit)
     {
     List<double> ret_val = new List<double>


     int one_per_limit = inlist.Count / (count_limit / 2);
     int i = 0;
     int c = 0;
     double min = inlist[0];
     double max = inlist[0];
     bool flagmaxfirst = false;

     for (c = 0; c < inlist.Count; c++)
     {
     if (inlist[c] > max)
     {
     max = inlist[c];
     flagmaxfirst = false;
    
     }
     if (inlist[c] < min)
     {
     min = inlist[c];
     flagmaxfirst = true;
    
     }

     if (i >= one_per_limit)
     {
     if (flagmaxfirst)
     {
     ret_val.Add(max);
     ret_val.Add(min);
     }else{
     ret_val.Add(min);
     ret_val.Add(max);
     }

     if (c + 1 < inlist.Count)
     {
     max = inlist[c + 1];
     min = inlist[c + 1];
    
     }
     i = -1;
     }
     i++;

     }

     return ret_val;
     }

чем этот код

private List<double> sort_list(List<double> inlist, int count_limit)
     {
     List<double> ret_val = new List<double>


     int one_per_limit = inlist.Count / (count_limit / 2);
     int i = 0;
     int c = 0;
     double min = inlist[0];
     double max = inlist[0];
     bool flagmaxfirst = false;

     for (c = 0; c < inlist.Count; c++)
     {
     if (inlist[c] > max)
     {
     max = inlist[c];
     //flagmaxfirst = false;
    
     }
     if (inlist[c] < min)
     {
     min = inlist[c];
     //flagmaxfirst = true;
    
     }

     if (i >= one_per_limit)
     {
     //if (flagmaxfirst)
     //{
     ret_val.Add(max);
     ret_val.Add(min);
     //}else{
     // ret_val.Add(min);
     // ret_val.Add(max);
     //}

     if (c + 1 < inlist.Count)
     {
     max = inlist[c + 1];
     min = inlist[c + 1];
    
     }
     i = -1;
     }
     i++;

     }

     return ret_val;
     }

Разница во времени нескольких раз. из-за флага компилятор не может оптимизировать?
Подскажите как оптимальнее всего написать подобную функцию.

Dasar

Почему такой код работает значительно дольше
кода внутри цикла больше, он хуже влазит целиком в кэш процессора.

Varvara2002

4/2 List.Add

Kent1331

4/2 List.Add
не понял что ты имел ввиду.

Dasar

что ты, вообще, кстати хочешь сделать? прореживание? оставить от интервала только min/max, сохранив порядок их появления?

agaaaa

Если ты гоняешь релиз, то ответ очевиден, на самом деле. Во втором варианте flagmaxfirst компилятор считает равным false и поэтому вообще его не проверяет. То есть из цикла выпадают два условия, что должно сильно влиять на работу конвейера.

Kent1331

что ты, вообще, кстати хочешь сделать? прореживание? оставить от интервала только min/max, сохранив порядок их появления?
Именно так.
Раздробить входной список на одинаковые интервалы, взять min max в интервалах и добавить в выходной список сохраняя порядок.
Можешь посоветовать как лучше в С# такое реализовать?

Dasar

код не проверял.
Можно еще повыжимать производительность по мелочи: использовать массивы вместо List-а, отдельно обрабатывать (вне цикла) хвостовой интервал и т.д.

public static List<double> ResamplingDown(List<double> values, int count_limit)
{
var result = new List<double>(count_limit); //заранее выделяем память под list

var interval_len = values.Count / (count_limit / 2);
if (interval_len * (count_limit / 2) < values.Count)
interval_len++;

for (var i = 0; i < values.Count; )
{
var interval_end = i + interval_len;
if (values.Count < interval_end)
interval_end = values.Count;

var min = values[i];
var max = values[i];

var isMaxFirst = false;
//выносим по максимуму код из под внутреннего цикла
for (++i; i < interval_end; ++i)
{
var v = values[i];
if (v > max)
{
max = v;
isMaxFirst = false;
}
else if (v < min)
{
min = v;
isMaxFirst = true;
}
}
if (isMaxFirst)
{
result.Add(max);
result.Add(min);
}
else
{
result.Add(min);
result.Add(max);
}
}

return result;
}

Kent1331

Спасибо огромное.
про вынос из внутреннего цикла я бы врядли допер.
Оставить комментарий
Имя или ник:
Комментарий: