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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Оптимизация switch?
1eXX
сообщение Oct 7 2008, 18:39
Сообщение #1





Группа: Новичок
Сообщений: 5
Регистрация: 15-06-08
Из: Кировская слобода
Пользователь №: 38 298



Привет народ!
Посоветуйте, как можно создать таблицу переходов для оптимизации switch (case-ов за сотню)?
"__even_in_range" в данном случае не очень универсален и ограничен 30 переходами.
Заранее благодарен за любую идею.
Go to the top of the page
 
+Quote Post
plombir
сообщение Oct 8 2008, 04:09
Сообщение #2


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

Группа: Участник
Сообщений: 99
Регистрация: 14-12-05
Пользователь №: 12 191



Попробуйте таблицей (массивом во flash) указателей, например, на функции. Обработчик переходов свой придётся писать, но он не сложнее switch. Примеры указателей пробегали в форуме.
А вот поймёт ли компилятор указатель на метку (как при goto), не пробовал. Но команда "Indirect Jump to (Z)" у AVR есть.
Go to the top of the page
 
+Quote Post
Rst7
сообщение Oct 8 2008, 05:23
Сообщение #3


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

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



Чето вопрос не совсем ясен. IAR при больших свичах создает таблицу переходов. Самостоятельно. А вообще - код в студию.


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


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

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



Цитата(1eXX @ Oct 7 2008, 22:39) *
"__even_in_range" в данном случае не очень универсален и ограничен 30 переходами.

Откуда такие сведения?


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
1eXX
сообщение Oct 8 2008, 07:52
Сообщение #5





Группа: Новичок
Сообщений: 5
Регистрация: 15-06-08
Из: Кировская слобода
Пользователь №: 38 298



Цитата(plombir @ Oct 8 2008, 08:09) *
А вот поймёт ли компилятор указатель на метку (как при goto), не пробовал. Но команда "Indirect Jump to (Z)" у AVR есть.
Хорошая мысль, да, вот только с меткой проблемы. Никак не удается получить ее адрес, да и goto не желает иметь переменной в качестве аргумента :(


Цитата(Rst7 @ Oct 8 2008, 09:23) *
Чето вопрос не совсем ясен. IAR при больших свичах создает таблицу переходов. Самостоятельно. А вообще - код в студию.
Хорошо бы знать директиву, чтобы компилятор создавал эту таблицу всегда, а не когда ему вздумается. Дело в том, что задача критична ко времени отклика, где каждый тик на счету и хорошо бы и на малых switch-ах реализовать эти переходы.
Код больно длинен, а вообще тоже самое, что и любой свитч с кучей case-ов, ничего сверхестественного.
А какая грань, при которой он создает таблицу, не подскажете?

Цитата(MrYuran @ Oct 8 2008, 09:27) *
Откуда такие сведения?
У меня при "switch(__even_in_range( state,60 ))" компилятор говорит что большой код (свободной flash-памяти завались) и реализуй-ка ты на "switch(state)", с 58 все ок. Отсюда 30 case-ов. И потом условие, при которых используется __even_in_range, требует четных state-ов, а у меня какие попало, с интервалом (0-10000), вразброс.
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Oct 8 2008, 08:04
Сообщение #6


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

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



По-моему, switch-case в любом случае преобразуется в таблицу переходов, просто при __even_in_range производится дополнительная оптимизация - фактически адрес в таблице равен базовому плюс аргумент свитча.


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


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(1eXX @ Oct 8 2008, 10:52) *
...а у меня какие попало, с интервалом (0-10000), вразброс.

В этом случае компилятору действительно не хватит места или оно будет неоптимально использовано для создания таблицы. Подразумевается, что таблица должна быть непрерывной (ну, или почти непрерывной).
Go to the top of the page
 
+Quote Post
1eXX
сообщение Oct 8 2008, 09:49
Сообщение #8





Группа: Новичок
Сообщений: 5
Регистрация: 15-06-08
Из: Кировская слобода
Пользователь №: 38 298



Похоже одновременно изящного и эффективного решения нет, будем ставить костыли, ну, как-то так:
if (state<60)
{ switch(__even_in_range(state,58)) {...} }
else [if (state<120)]
{
state-=60;
switch(__even_in_range(state,58)) {...}
}
...
покеда :)
Go to the top of the page
 
+Quote Post
prottoss
сообщение Oct 8 2008, 10:51
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(1eXX @ Oct 8 2008, 17:49) *
Похоже одновременно изящного и эффективного решения нет, будем ставить костыли, ну, как-то так:
Интресно - вы ЭТО относите к изящному или эффективному решению? smile.gif


--------------------
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Oct 8 2008, 11:22
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(1eXX @ Oct 8 2008, 10:52) *
А какая грань, при которой он создает таблицу, не подскажете?

Я сам создаю таблицу при количестве case'ов больше десятка.
Все равно код становится длинным и нечитаемым.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
1eXX
сообщение Oct 8 2008, 11:58
Сообщение #11





Группа: Новичок
Сообщений: 5
Регистрация: 15-06-08
Из: Кировская слобода
Пользователь №: 38 298



Цитата(Dog Pawlowa @ Oct 8 2008, 15:22) *
Я сам создаю таблицу при количестве case'ов больше десятка.
Все равно код становится длинным и нечитаемым.
Каким образом вы создаете таблицу, можете поведать?
Если он выполняется быстрее, то пускай он длинный и нечитаемый, для моего случая это не критично.
Go to the top of the page
 
+Quote Post
prottoss
сообщение Oct 8 2008, 12:23
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(1eXX @ Oct 8 2008, 15:52) *
а у меня какие попало, с интервалом (0-10000), вразброс.
А чем это обусловлено и есть какая нить система в этих значениях?


--------------------
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Oct 8 2008, 13:12
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(1eXX @ Oct 8 2008, 14:58) *
Каким образом вы создаете таблицу, можете поведать?
Если он выполняется быстрее, то пускай он длинный и нечитаемый, для моего случая это не критично.

Примитивноsmile.gif

//определения аргументов case, имен функций, и текста для вывода в одном месте
Код
...
#define     stERROR                  7
#define      nm7               "Error"
#define   F7                fError
    
#define     stLOW_POWER            8
#define    nm8e               "Low power"
#define   nm8g               "Unterspannung"
#define   F8                fLowPower
...

// массив функций
const VECTORS function[stQty] =
Код
{  f0,  f1,  f2,  f3,  f4,  f5,  f6,  f7,  f8,  f9...f103   };


//собственно "switch" в теле программы
Код
  function[state]();


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
1eXX
сообщение Oct 8 2008, 17:42
Сообщение #14





Группа: Новичок
Сообщений: 5
Регистрация: 15-06-08
Из: Кировская слобода
Пользователь №: 38 298



Самое яблочко, Дог :beer:
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Oct 8 2008, 18:02
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(1eXX @ Oct 8 2008, 20:42) *
Самое яблочко, Дог beer.gif

Да ладно ... 05.gif
В каких-то вариантах помогает двумерный массив function[state, event].
Успехов smile.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 9 2008, 00:29
Сообщение #16


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Dog Pawlowa @ Oct 8 2008, 16:12) *
Код
...
#define     stERROR                  7
#define     stLOW_POWER            8
Для упрощения вставки/удаления элементов и исключения дублирования лучше использовать enum:
Код
enum state_t
{
    stINIT = 0,
    ....
    stERROR,
    stLOW_POWER,
};


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Oct 9 2008, 05:23
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Сергей Борщ @ Oct 9 2008, 03:29) *
Для упрощения вставки/удаления элементов и исключения дублирования лучше использовать enum.

Хороший вопрос, необходимость корректировок иногда возникает. Делаю дыры или их забиваю. smile.gif
Конечно, я думал об этом, но к номеру состояния у меня привязаны еще массивы - как минимум массив функций обработки состояния.
То есть все равно при исключении элемента из enum, нужно по имени найти и исключить подобный элемент из другого массива, строго соблюдая порядок. А их сотня. То есть рядом в тексте не расположить.
А здесь я на видимом участке текста вижу все.
Может, как-то макросами можно извратиться - не придумал.
Если подскажете удобный способ, с меня beer.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 9 2008, 07:01
Сообщение #18


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Dog Pawlowa @ Oct 9 2008, 08:23) *
То есть все равно при исключении элемента из enum, нужно по имени найти и исключить подобный элемент из другого массива, строго соблюдая порядок. А их сотня.
При исключении из #define, скажем, 80-го элемента, вам придется перенумеровать оставшиеся до конца 20, чтобы сохранить непрерывность. А при исключени 2-го вообще будет так: ;( Посмотрите это сообщение ReAl, пройдите по ссылке из него - похоже там то, что вам подойдет.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Oct 9 2008, 08:24
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Сергей Борщ @ Oct 9 2008, 10:01) *
При исключении из #define, скажем, 80-го элемента, вам придется перенумеровать оставшиеся до конца 20, чтобы сохранить непрерывность. А при исключени 2-го вообще будет так: ;( Посмотрите это сообщение ReAl, пройдите по ссылке из него - похоже там то, что вам подойдет.

За ссылку спасибо, изучу.
На самом деле исключать вовсе не обязательно, поскольку непрерывность нужна только для состояний прибора, выбираемых из меню со скроллингом. Такие меню у меня содержат до 15 строчек, что не очень смертельно. Бывает, заказчик просит перетасовать пункты в меню, вот тогда да, обезьянья работа... Все остальные состояния выбираются явно, типа:
if (MIN_VOLTAGE>voltage) state=stLOW_VOLTAGE.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
shasik
сообщение Oct 10 2008, 18:09
Сообщение #20


Местный
***

Группа: Свой
Сообщений: 319
Регистрация: 3-09-05
Из: Беларусь, Новополоцк
Пользователь №: 8 188



Цитата(Dog Pawlowa @ Oct 8 2008, 16:12) *
Код
  function[state]();

Небольшая модификация предложенного Dog Pawlowa.
Исходная ситуация: код команды - 1 байт, всего используемых команд около - 40.
Решение: массив указателей на функции-обработчики для каждой возможной команды (длина массива 256). Для "нереализованных" команд просто вызывается функция-заглушка. Т.е. то, что предложил Dog Pawlowa

Наш Всевышний и Генеральный решил, что отныне код команды будет 2 байта, при этом, естественно, не все команды будут реализованы.
Прикинул я сколько займет теперь массив указателей, и понял что "это ж весь мой рост", в смысле память. Теперь делаю так:
Код
index = binary_search(state, StateArr);
FunctionArr[index]();

Массив StateArr, естественно, отсортирован (у меня по возрастанию). Когда юзвер добавляет очередную команду, то добаляем в массив StateArr очередной "идентификатор команды", а в FunctionArr адрес обработчика этой команды. После чего сортируем массив StateArr, при этом синхронно тасуется и массив FunctionArr. Процедура добавления новой команды некритична ко времени.
На данный момент максимально возможное количество команд пользователя 2048. Проверяли худший случай, работает шустро.
Замечание: когда команд немного (10-20), то быстрее оказался простой линейный просмотр массива StateArr, чем binary_search.
Go to the top of the page
 
+Quote Post

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

 


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


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