Страница 1 из 1

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

Добавлено: Чт май 02, 2013 08:56:56
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;
}
Есть ли идеи как его можно оптимизировать?

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

Добавлено: Чт май 02, 2013 10:47:33
Леонид Иванович
Т.е. Вы фактически доказали необходимость использования "суперкомпьютеров" с матлабами и прочей лабудой.

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

Добавлено: Чт май 02, 2013 10:53:30
CheerfulCalf
Отнюдь. Размер файла для прошивки микроконтроллера после компиляции данного кода составляет 373 байта (для сравнения, размер файла полученного после компиляции кода созданного с помощью Matlab составил 91648 байт). Это уже не сравнивая количества итераций необходимых для получения того же результата (их в сотни раз меньше, одно только штатное возведение в сетпень чего стоит...).
У меня скудные познания в сишных языках, но я думаю у меня далеко не оптимальный вариант.

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

Добавлено: Чт май 02, 2013 16:42:30
YS
Есть ли идеи как его можно оптимизировать?
Ниже - советы в порядке критичности.

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

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

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

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

И да. Это не C++, а просто Си. Не путайте. :)

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

Добавлено: Чт май 02, 2013 18:24:29
pyzhman
+ уходить от вложенного цикла. Наверняка он и жрет время.

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

Добавлено: Чт май 02, 2013 19:13:48
CheerfulCalf
pyzhman писал(а):+ уходить от вложенного цикла. Наверняка он и жрет время.
Это весьма вероятно, но как уходить?

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

Добавлено: Чт май 02, 2013 20:04:27
blackx
А по-моему лучше не пихать ATtiny туда где он не нужен. Еще и нейронные сети хотите писать. Эта задача для какой-нибудь DSP-шки мегагерц на 100-300. По-моему излишняя оптимизация кода, делающая его малопонятным - плохо.
Если это звучит неубедительно - перепишите свой код на асм :)))

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

Добавлено: Чт май 02, 2013 21:13:32
YS
как уходить?
До посинения анализировать алгоритм и думать, как перейти к эквивалентному, но без вложенного цикла.

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

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

По программе на С++ отвечу так! Зачем "чар" использовал для определения всех переменных - это нехороший тон при программировании!
переменную "и" просто другого типа сделать можно и пересмотреть остальное что там так прописано.

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

Добавлено: Сб май 04, 2013 13:21:43
YS
Зачем "чар" использовал для определения всех переменных - это нехороший тон при программировании!
Да, правильнее uint8_t. :)