2016-05-20 2 views
2

Я пытаюсь улучшить скорость моей текущей программы, программа регистрирует данные с нескольких датчиков, но одна часть в конкретном случае очень медленная.C Сохранение массива работающего сигнала отсортировано

В этой части я храню данные сигнала в целочисленном массиве размером 50 и извлекаю максимум и минимум, чтобы получить (сырую) индикацию амплитуды. Это делается для 3 датчиков каждую секунду, но сортировка массива для получения минимума и максимума занимает очень много времени.

Моя первая мысль заключалась в хранении данных в отсортированном списке, но как отслеживать, какая последняя точка сигнала должна быть удалена?

Текущий код:

static int movement[AD_SENSORS][AD_MOVEMENT_SIZE]; 
    static int totals[AD_SENSORS]; 
    int movement_sorted[AD_MOVEMENT_SIZE]; 
    int difference = 0; 
    static unsigned int i; // Movement index 
    int k = 0; 

    //Update positions 
    if (++i>(AD_MOVEMENT_SIZE-1)){i=0;} //increment index of movement array 

    //Initialise signal value 
    struct tty_data_t *Current = NULL; 
    Current = head_tty; 

    //Add signals to movement array 
    while (Current != NULL){ 
     totals[Current->ID] = totals[Current->ID] - movement[Current->ID][i]; 
     movement[Current->ID][i] = Current->AD_signal; 
     totals[Current->ID] = totals[Current->ID] + movement[Current->ID][i]; 
     Current->AD_average = totals[Current->ID]/AD_MOVEMENT_SIZE; 
     for (k = 0; k<AD_MOVEMENT_SIZE; k++){ 
      movement_sorted[k] = movement[Current->ID][k]; 
     } 
     qsort (movement_sorted, AD_MOVEMENT_SIZE, sizeof(int), Compare); 
     Current->AD_amplitude = movement_sorted[AD_MOVEMENT_SIZE-1] - movement_sorted[0]; 
     difference += movement_sorted[AD_MOVEMENT_SIZE-1] - movement_sorted[0]; 
     Current = Current->next; 
    } 
    g_movement = difference; 
+0

Зачем вам нужно, чтобы удалить последнюю точку сигнала? Почему вы не храните только максимальные и минимальные сигналы и не обновляете один из них каждый раз, если это необходимо? – GMichael

+0

«действительно ли сортировка массива для получения минимума и максимума занимает очень много времени»? «целочисленный массив размером 50», «3 датчика в секунду»? На чем вы работаете, счеты? :) Плюс, что @Michael говорит - продолжайте работать max/min. –

+0

Ну, на самом деле сейчас это не займет много времени, но есть план увеличить его до 8 датчиков со скоростью 100 раз в секунду на малине Pi и, глядя на callgrind, эта функция занимает 70% времени. * И как отслеживать max/min, если следующий datapoint добавлен в конец массива, а первый удаляется, как узнать, что такое max/min? – Enigma1991

ответ

1

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

Однако, вы, вероятно, на самом деле не необходимо сортировать. Предполагая, что у вас есть подвижный массив из последних пятидесяти элементов, вам нужно только отрегулировать min и max (и количество элементов, соответствующих им, mincount и maxcount) при ограниченных обстоятельствах. Я дам вам шаги только для максимального значения, но легко просто дублировать логику как минимум. Все эти взаимоисключающие ситуации и должны быть проверены в порядке, указанном (первый матч вы найдете исключает все остальные следующий его):

  • При добавлении элемента в пустой список, установите max к этому элементу и установите maxcount к одному.
  • Если вы добавляете то же значение, которое вы удаляете, ничего не делайте.
  • Если вы добавляете значение, то же самое, что и max, просто добавьте его в maxcount.
  • Если вы добавляете значение, большее, чем текущее max, установите max на это значение и установите maxcount. Если значение, которое вы удаляете, совпадает с max и maxcount больше одного, просто уменьшите maxcount.
  • В противном случае, если значение, которое вы удаляете, равно текущему max (в этот момент maxcount должно быть одним), сканируйте элементы в списке, чтобы пересчитать новый max и установите соответствующие значения.

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

И не обязательно обеспокоен производительностью. Даже восемь датчиков со сто отсчетов в секунду будут давать только 800 точек данных. С небольшим набором данных сортировка может быть ошибочной ошибкой, так как при сканировании многие элементы последовательно будут по-прежнему очень быстрыми (особенно если вам не нужно это делать каждые время обновления данных проката.

+0

Спасибо, что я, конечно, усложнил проблему, тогда он читал это, и снова на данный момент это действительно очень быстро, но я уже улучшаю его для следующего шага, где увеличивается скорость чтения и количество датчиков. – Enigma1991

+0

@ Enigma1991, даже 800 элементов можно сканировать последовательно в очень быстрое время. Я оставил бы сортировку, пока не будет * актуальная проблема с производительностью. – paxdiablo

+0

Я обновил код и пробовал его на полной скорости, я вижу увеличение на 8 измерений в секунду, и теперь функция теперь отображается только внизу кода callgrind, теперь я читаю 8 датчиков со скоростью 49 раз в секунду, а массив составляет 50 точек, поэтому около 1 секунды. Это все работает на малине pi 2, но теперь выполнение sqlite выполняется в верхней части callgrind, поэтому проблема действительно лежит в другом месте. – Enigma1991

1

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

for (k = 0; k < AD_MOVEMENT_SIZE; k++){ 
      movement_sorted[k] = movement[Current->ID][k]; 
     } 

Вместо того, чтобы копировать массив для сортировки (в O(nlogn) времени) просто проверить, если каждый элемент является максимальным или минимальным и получить их в O(n) время.

int max = INT_MIN; 
int min = INT_MAX; 
for (k = 0; k<AD_MOVEMENT_SIZE; k++){ 
      if (movement[Current->ID][k] < min) min = movement[Current->ID][k]; 
      if (movement[Current->ID][k] > max) max = movement[Current->ID][k]; 
     } 

Отказ от ответственности: Я знаю, что большой-O-нотация не говорит много в массивах 50 элементов, но важно, в более общем случае

Смежные вопросы