Нужна помощь в программе (С++)

Здесь принимаются все самые невообразимые вопросы... Главное - не стесняйтесь. Поверьте, у нас поначалу вопросы были еще глупее :)
Ответить
CheerfulCalf
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Чт мар 22, 2012 13:25:31
Откуда: Odense, Danmark

Нужна помощь в программе (С++)

Сообщение CheerfulCalf »

Всем добрый день.

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

Первично - возникла проблема разделения сигнала ЭКГ на циклы. Что в матлабе делалось мышкой (взять статистику по уровню, найти выбросы, по выбросам уже найти период, или непрерывное вейвлет преобразование, или автокорреляционная функция, или вычисление минимума функции на промежутке и т.п....) на атини просто не влазит в память. Попробовал сделать фильтр Гаусса с сплавающим весовым окном. Результат как на картинке:
Изображение
Теперь нахождение циклов - плёвое дело: берём любые три максимума подряд - самый большой и будет началом цикла - далее отсчитываем по три.
Проблема с кодом. Делает то он то что надо, но тормозит жутко, да и памяти жрёт немеренно. Вот он собственно сам:

Код: Выделить всё

int *MWGWF(int DATA[])
{
   double ALPHA = 2.5; char WINDOW = 31;
   int OUT[(sizeof DATA / sizeof DATA[0])];
   char j, i, n, x, N = WINDOW - 1;
   double power, h[WINDOW-1];
   for(i = - N / 2; i <= N / 2; i++)
   {
      if (i & 32768u) { n = 32768u - (i & 32767u); } else { n = i; }
      power = - 0.5 * (2.5 * n / 15.0);
      union { double d; int x[2]; } u = { power };
      u.x[1] = (int)(2 * (u.x[1] - 1072632447) + 1072632447); u.x[0] = 0;
      union { double df; int xf[2]; } uf = { 2.7 };
      uf.xf[1] = (int)(u.d * (uf.xf[1] - 1072632447) + 1072632447);
      uf.xf[0] = 0;
      h[i+(WINDOW-1)/2] = uf.df / 20;
   }
   x = (sizeof DATA / sizeof DATA[0]);
   for(i = 0; i < x; i++)
   {
      for(j = -1 * WINDOW; j <= WINDOW; j++)
      {
         if(j > -1 && j < x - i + 1)
            OUT[i] = OUT[i] + DATA[i+j] * h[j+WINDOW+1];
      }
   }
   return OUT;
}


Есть ли идеи как его можно оптимизировать?
Аватара пользователя
Леонид Иванович
Друг Кота
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск
Контактная информация:

Re: Нужна помощь в программе (С++)

Сообщение Леонид Иванович »

Т.е. Вы фактически доказали необходимость использования "суперкомпьютеров" с матлабами и прочей лабудой.
CheerfulCalf
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Чт мар 22, 2012 13:25:31
Откуда: Odense, Danmark

Re: Нужна помощь в программе (С++)

Сообщение CheerfulCalf »

Отнюдь. Размер файла для прошивки микроконтроллера после компиляции данного кода составляет 373 байта (для сравнения, размер файла полученного после компиляции кода созданного с помощью Matlab составил 91648 байт). Это уже не сравнивая количества итераций необходимых для получения того же результата (их в сотни раз меньше, одно только штатное возведение в сетпень чего стоит...).
У меня скудные познания в сишных языках, но я думаю у меня далеко не оптимальный вариант.
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Нужна помощь в программе (С++)

Сообщение YS »

Есть ли идеи как его можно оптимизировать?


Ниже - советы в порядке критичности.

Прежде всего - никакой плавающей точки. Тем более, double. В AVR нет FPU (какой там FPU, если есть аппаратный перемножитель - уже счастье), соответственно, только фиксированная точка.

Деление - очень ресурсоемкая операция. Про плавающую точку мы уже забыли, я про целочисленное деление. Где возможно, лучше заменить сдвигом.

Умножение тоже ресурсоемко, если нет аппаратного перемножителя. Опять же заменяем сдвигом где можно.

Ну и оптимизировать алгоритм. Тут мало что могу подсказать, т.к. лень въезжать во все это. :)

И да. Это не C++, а просто Си. Не путайте. :)
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
pyzhman
Друг Кота
Сообщения: 7016
Зарегистрирован: Вс июл 12, 2009 19:15:29
Откуда: Ижевск
Контактная информация:

Re: Нужна помощь в программе (С++)

Сообщение pyzhman »

+ уходить от вложенного цикла. Наверняка он и жрет время.
Docendo discimus
CheerfulCalf
Нашел транзистор. Понюхал.
Сообщения: 183
Зарегистрирован: Чт мар 22, 2012 13:25:31
Откуда: Odense, Danmark

Re: Нужна помощь в программе (С++)

Сообщение CheerfulCalf »

pyzhman писал(а):+ уходить от вложенного цикла. Наверняка он и жрет время.

Это весьма вероятно, но как уходить?
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

Re: Нужна помощь в программе (С++)

Сообщение blackx »

А по-моему лучше не пихать ATtiny туда где он не нужен. Еще и нейронные сети хотите писать. Эта задача для какой-нибудь DSP-шки мегагерц на 100-300. По-моему излишняя оптимизация кода, делающая его малопонятным - плохо.
Если это звучит неубедительно - перепишите свой код на асм :)))
Изображение only pure true norwegian blackx Изображение
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Нужна помощь в программе (С++)

Сообщение YS »

как уходить?


До посинения анализировать алгоритм и думать, как перейти к эквивалентному, но без вложенного цикла.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Аватара пользователя
Кот_Баюн
Опытный кот
Сообщения: 868
Зарегистрирован: Сб авг 07, 2010 13:48:30
Откуда: Одесса

Re: Нужна помощь в программе (С++)

Сообщение Кот_Баюн »

для таких целей используются сигнальные процессоры, к ним прикрепил внешнюю память и всё влезает. Как по мне, то ценные данные с кардиограммы просто утеряны... Как проанализировать инсульты, инфаркты и предшествующие состояния? Понимаю что задача так не стоит, но толку от такого кардиографа я не вижу...
Совет по поводу написания программы - забудьте С++, переходите на ассемблер, тогда возможно программа влезет и уж точно будет быстрее при исполнении!

По программе на С++ отвечу так! Зачем "чар" использовал для определения всех переменных - это нехороший тон при программировании!
переменную "и" просто другого типа сделать можно и пересмотреть остальное что там так прописано.
Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Нужна помощь в программе (С++)

Сообщение YS »

Зачем "чар" использовал для определения всех переменных - это нехороший тон при программировании!


Да, правильнее uint8_t. :)
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Ответить

Вернуться в «Теория»