реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> [avr-gcc]Как побороть лишнюю оптимизацию?
UniBomb
сообщение Feb 4 2009, 13:38
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



Добрый день. Столкнулся вот с какой незадачей - компиляция программы происходит так, что часть одной функции как бы выбрасывается из программы. Ошибок в функции нет, но что там говорить, вот эта функция:

(функция "как есть", в целях понимания ничего не убирал, надеюсь поймёте)

Код
void processing_data(void)
{
if(mdns.mdfl[U] <= mdns.mdfl[PGSU1])
  { mdns.mdfl[Conc] = mdns.mdfl[A1]*mdns.mdfl[U] + mdns.mdfl[B1]; }
else
  { mdns.mdfl[Conc] = mdns.mdfl[A2]*mdns.mdfl[U] + mdns.mdfl[B2]; }
  
char _s_disrec = 0;
if(mdns.mdfl[Conc] < 0) { mdns.mdfl[Conc] = 0; }
if(mdns.mdfl[Conc] >= mdns.mdfl[Pr])
  { pereg(); }
else if(mdns.mdfl[Conc] >= /*mdns.mdfl[P2]*/0.88)
  {
   _s_disrec = 1;
   if((flags&0x03 == 0) || (flags&0x03 == 1)) //если нет порогов или только первый
    {
     mdns.mdui[P1Count]++;
     mdns.mdui[P2Count]++;  
     WriteByteIntoExtEEPROM(0X3E, mdns.mdWorkSpace[0X46]);
     WriteByteIntoExtEEPROM(0X3F, mdns.mdWorkSpace[0X47]);
     WriteByteIntoExtEEPROM(0X40, mdns.mdWorkSpace[0X48]);
     WriteByteIntoExtEEPROM(0X41, mdns.mdWorkSpace[0X49]);    
     modbus_buf[9] = mdns.mdWorkSpace[0x48];//p2
     modbus_buf[8] = mdns.mdWorkSpace[0x49];//p2    
     modbus_buf[7] = mdns.mdWorkSpace[0x46];//p1
     modbus_buf[6] = mdns.mdWorkSpace[0x47];//p1    
    }
   flags |= (1 << 1);
   flags &= ~(1 << 0);
   modbus_buf[2] = flags;  
  }
else if(mdns.mdfl[Conc] >= mdns.mdfl[P1])
  {
   if(flags&0x03 == 0)         //если небыло до этого порога
    {
     mdns.mdui[P1Count]++;
     WriteByteIntoExtEEPROM(0X3E, mdns.mdWorkSpace[0X46]);
     WriteByteIntoExtEEPROM(0X3F, mdns.mdWorkSpace[0X47]);
     modbus_buf[9] = mdns.mdWorkSpace[0x48];//p2
     modbus_buf[8] = mdns.mdWorkSpace[0x49];//p2    
    }
   flags |= (1 << 0);      
   flags &= ~(1 << 1);
   modbus_buf[2] = flags;  
  }
else
  {
   flags &= ~(1 << 0);
   flags &= ~(1 << 1);
   modbus_buf[2] = flags;    
  }
  if(_s_disrec == 0)
   stop_disrec |= 0x0F;
}


если упрощённо, то функция делает следующее:

Код
void processing_data(void)
{
расчитываем некое значение mdns.mdfl[Conc]
  
if(проверяем - невышло ли значение сверх всяких норм)
  если да, то орём всем, чем можем и записываем сей факт в журнале

else if(проверяем - не слишком ли близко подошло значение к "сверх всяких норм")
  {
    верещим пищалкой, зажигаем два светодиода и делаем запись в журнале
  }

else if(проверяем - не превысило ли значение из ряда "нормальных значений")
  {
    верещим пищалкой, зажигаем один светодиод и делаем запись в журнале
  }

else
  {
   всё хорошо, продолжаем как ни в чём небыло
  }

}


Так вот - вне зависимости от значения во второй и тетий if программа незаходит. Т.е. зачение расчитывается, я его спрашиваю по модбасу, оно соответсвует действительности, но ни один светодиод не загорается и звуковой извещатель всё время молчит. Поэтому я даже не знаю - толи эти if'ы не вошли в готовую программу, либо всё время заходит в последний иф. В живую получить значения выше mdns.mdfl[Pr] у меня нет возможности, поэтому этот if мне не проверить.

В процессе отладки я закомментировал расчёты mdns.mdfl[Conc] просто присваивал этой переменной различные значения. Результат тотже (это в принципе неудивительно, тут ещё можно поверить оптимизатору), но если я этой переменной присваивал значение выше чем mdns.mdfl[Pr], то в первый if программа заходит. Из этого я могу сделать вывод, что оптимизации поддались все остальные if'ы. Можно ли это как-нибудь побороть?


прочие исходные данные : avr-gcc (WinAVR 20080512) 4.3.0; уровень оптимизации "s" (меньше ставить нельзя, больше смысла нет).
Go to the top of the page
 
+Quote Post
injen-d
сообщение Feb 4 2009, 17:31
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 91
Регистрация: 10-10-07
Из: Воронежа
Пользователь №: 31 250



Приведите объявления переменных, в частности mdns.mdfl - какого типа?


--------------------
- Бендер, ты же робот, зачем тебе пить пиво?
- Незачем! Я могу бросить в любой момент!
Go to the top of the page
 
+Quote Post
UniBomb
сообщение Feb 5 2009, 05:58
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



Код
union
{
  float mdfl[22];
  unsigned int mdui[45];
  char mdch[90];
  unsigned char mduc[90];
  unsigned char mdWorkSpace[90];
} mdns; //ModBusNameSpace

unsigned char flags;

unsigned char modbus_buf[16];


Соответсвенно все "Conc", "U", "A1" и т.д. - это const unsigned char.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 5 2009, 06:12
Сообщение #4


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



А без оптимизации работает?


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
UniBomb
сообщение Feb 5 2009, 06:26
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



а без оптимизации размер программ превышает размер памяти мк smile.gif Самый низкий уровень оптимизации, на выходе которой рзмер программы позволяет прошиться в мк - 2. Но при этом всё остаёться без изменений...
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 5 2009, 06:37
Сообщение #6


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(UniBomb @ Feb 5 2009, 09:26) *
а без оптимизации размер программ превышает размер памяти мк smile.gif

Значит, надо взять пожирнее. Делать что-то без запаса - неразумно. Я за год одну прошивку последовательно пропатчил с 15 до 22 кБ.
А вы что будете делать потом, ели вдруг (да наверняка) ещё что-нибудь добавится?

PS: буферы свои объявите volatile, наверняка в прерывании их меняете


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
UniBomb
сообщение Feb 5 2009, 06:57
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



Цитата(MrYuran @ Feb 5 2009, 09:37) *
Значит, надо взять пожирнее. Делать что-то без запаса - неразумно. Я за год одну прошивку последовательно пропатчил с 15 до 22 кБ.
А вы что будете делать потом, ели вдруг (да наверняка) ещё что-нибудь добавится?

PS: буферы свои объявите volatile, наверняка в прерывании их меняете


Насчёт запаса - просто есть уже готовое устройство, которое прошло все стадии разработок и меняться уже не будет. Более того - программа по всё это дело тоже уже готовая и запас свободного места составляет 25%. Эта ерунда проявилась после последней правки программы (до этого всё было нормально) и принципиально нового в принципе уже ничего не добавиться. Также следуя правилу о преждевременной оптимизации кода я этой оптимизацией и не занимался (я имею в виду С-шный код, который я пишу, а не компилятор). Думаю после этого свободного места будет процентов 40. Сейчас размер прошивки ~6,3 кб, использую восьмую атмегу с 8кб памяти.


насчёт постскриптума - а разве volatile влияет на то, что эти переменные как то изменяются в прерывании? Объясните этот момент поподробней пожалуйста (я правда это не знаю biggrin.gif )
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Feb 5 2009, 07:38
Сообщение #8


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(UniBomb @ Feb 5 2009, 09:57) *
принципиально нового в принципе уже ничего не добавиться

к.г. правка программы заканчивается со смертью программиста biggrin.gif (и то не всегда)
Цитата
насчёт постскриптума - а разве volatile влияет на то, что эти переменные как то изменяются в прерывании?

volatile объясняет компилятору, что не нужно слишком умничать и оптимизировать данную переменную.
Он же не знает, что она может измениться где-то в другом потоке, и может решить, что раз переменная явно нигде не меняется, то и результат сравнения будет "как в прошлый раз".
Я утрирую конечно, но просто все переменные, которые используются одновременно в прерываниях и где-то ещё, всегда объявляют как volatile.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
UniBomb
сообщение Feb 5 2009, 08:03
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



Цитата(MrYuran @ Feb 5 2009, 10:38) *
к.г. правка программы заканчивается со смертью программиста biggrin.gif (и то не всегда)

biggrin.gif


Цитата(MrYuran @ Feb 5 2009, 10:38) *
volatile объясняет компилятору, что не нужно слишком умничать и оптимизировать данную переменную.
Он же не знает, что она может измениться где-то в другом потоке, и может решить, что раз переменная явно нигде не меняется, то и результат сравнения будет "как в прошлый раз".
Я утрирую конечно, но просто все переменные, которые используются одновременно в прерываниях и где-то ещё, всегда объявляют как volatile.

Объявил с volatile. Ничего не изменилоь... И кстате свои буферы я изменяю в каждой второй функции. Я не зря объявил msdn как union - этот буфер я передаю по модбасу, по своему "техническому" протоколу как по частям, так и всем буфером сразу, в процессе работы отдельные части изменяються постояно.
Go to the top of the page
 
+Quote Post
Rst7
сообщение Feb 5 2009, 09:47
Сообщение #10


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Поэтому я даже не знаю - толи эти if'ы не вошли в готовую программу, либо всё время заходит в последний иф.


А в чем проблема? Натравите на данный модуль гнуся с ключем -S (т.е. остановится на ассемблировании), почитайте асмовский листинг. Может тогда станет понятно, что и как.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
alx2
сообщение Feb 5 2009, 11:05
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 340
Регистрация: 25-10-05
Из: Пермь, Россия
Пользователь №: 10 091



Цитата(UniBomb @ Feb 4 2009, 18:38) *
В процессе отладки я закомментировал расчёты mdns.mdfl[Conc] просто присваивал этой переменной различные значения. Результат тотже (это в принципе неудивительно, тут ещё можно поверить оптимизатору), но если я этой переменной присваивал значение выше чем mdns.mdfl[Pr], то в первый if программа заходит. Из этого я могу сделать вывод, что оптимизации поддались все остальные if'ы. Можно ли это как-нибудь побороть?
Напрашивается вывод, что mdns.mdfl[Pr] имеет значение меньшее, чем 0.88 и mdns.mdfl[P1]


--------------------
Всего наилучшего,
Alex Mogilnikov
Go to the top of the page
 
+Quote Post
injen-d
сообщение Feb 5 2009, 17:08
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 91
Регистрация: 10-10-07
Из: Воронежа
Пользователь №: 31 250



Вообще оптимизатор может "похозяйничать" с конструкцией типа if(){} только в том случае, если по его мнению условие в скобках всегда истино или всегда ложно. Отсюда следует вывод, что если оптимизатор проанализировав вычисление mdns.mdfl[Conc] решит что эта переменная всегда будет больше нуля, то первый if он выбросит. Аналогично и со вторым if. А вы mdns.mdfl[Conc] константы присваивали для проверки непосредственно перед if-ами? И при этом, при mdns.mdfl[Conc]=(например)10; в первый if все равно не заходит? Ну в этом случае, помнится мне были какие-то ключики для GCC (-funsigned-char, -funsigned-bitfields и кажется что-то еще было), чтобы он при компиляции без явного объявления переменной signed, по умолчанию считает переменную unsigned, в этом случае получилась бы как раз Ваша ситуация. Проверьте наличие таких ключей в make-файле. Все это справедливо, если причина "молчания" Вашего девайса действительно в оптимизаторе.


--------------------
- Бендер, ты же робот, зачем тебе пить пиво?
- Незачем! Я могу бросить в любой момент!
Go to the top of the page
 
+Quote Post
UniBomb
сообщение Feb 6 2009, 06:29
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



Цитата(Rst7 @ Feb 5 2009, 12:47) *
А в чем проблема? Натравите на данный модуль гнуся с ключем -S (т.е. остановится на ассемблировании), почитайте асмовский листинг. Может тогда станет понятно, что и как.

Не то, что бы я не разбирался в ассемблерном коде, но на продолжительный взгляд всё там хорошо. И вот какая странность - в отладчике вроде всё работает...

Цитата(alx2 @ Feb 5 2009, 14:05) *
Напрашивается вывод, что mdns.mdfl[Pr] имеет значение меньшее, чем 0.88 и mdns.mdfl[P1]

Нет, это искючено. Я проверял значения во время работы (путём опроса по 485-му) и всё значения были в норме.

Цитата(injen-d @ Feb 5 2009, 20:08) *
Вообще оптимизатор может "похозяйничать" с конструкцией типа if(){} только в том случае, если по его мнению условие в скобках всегда истино или всегда ложно. Отсюда следует вывод, что если оптимизатор проанализировав вычисление mdns.mdfl[Conc] решит что эта переменная всегда будет больше нуля, то первый if он выбросит. Аналогично и со вторым if. А вы mdns.mdfl[Conc] константы присваивали для проверки непосредственно перед if-ами? И при этом, при mdns.mdfl[Conc]=(например)10; в первый if все равно не заходит? Ну в этом случае, помнится мне были какие-то ключики для GCC (-funsigned-char, -funsigned-bitfields и кажется что-то еще было), чтобы он при компиляции без явного объявления переменной signed, по умолчанию считает переменную unsigned, в этом случае получилась бы как раз Ваша ситуация. Проверьте наличие таких ключей в make-файле. Все это справедливо, если причина "молчания" Вашего девайса действительно в оптимизаторе.

Нет, значения присваивал в самом начале, перед всеми ифами. В этом случае всё происходит нормально... Насчёт ключей - щас гляну...
Go to the top of the page
 
+Quote Post
UniBomb
сообщение Feb 9 2009, 11:01
Сообщение #14


Частый гость
**

Группа: Свой
Сообщений: 148
Регистрация: 26-05-05
Пользователь №: 5 416



Всем спасибо за внимание, проблема разрешилась. Я немного упростил эту функцию и часть её вынес в другую. Всё заработало, хотя о причинах этого глюка я до сих пор могу только догадываться.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 07:34
Рейтинг@Mail.ru


Страница сгенерированна за 0.01517 секунд с 7
ELECTRONIX ©2004-2016