Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Оптимизация switch?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
1eXX
Привет народ!
Посоветуйте, как можно создать таблицу переходов для оптимизации switch (case-ов за сотню)?
"__even_in_range" в данном случае не очень универсален и ограничен 30 переходами.
Заранее благодарен за любую идею.
plombir
Попробуйте таблицей (массивом во flash) указателей, например, на функции. Обработчик переходов свой придётся писать, но он не сложнее switch. Примеры указателей пробегали в форуме.
А вот поймёт ли компилятор указатель на метку (как при goto), не пробовал. Но команда "Indirect Jump to (Z)" у AVR есть.
Rst7
Чето вопрос не совсем ясен. IAR при больших свичах создает таблицу переходов. Самостоятельно. А вообще - код в студию.
MrYuran
Цитата(1eXX @ Oct 7 2008, 22:39) *
"__even_in_range" в данном случае не очень универсален и ограничен 30 переходами.

Откуда такие сведения?
1eXX
Цитата(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), вразброс.
MrYuran
По-моему, switch-case в любом случае преобразуется в таблицу переходов, просто при __even_in_range производится дополнительная оптимизация - фактически адрес в таблице равен базовому плюс аргумент свитча.
IgorKossak
Цитата(1eXX @ Oct 8 2008, 10:52) *
...а у меня какие попало, с интервалом (0-10000), вразброс.

В этом случае компилятору действительно не хватит места или оно будет неоптимально использовано для создания таблицы. Подразумевается, что таблица должна быть непрерывной (ну, или почти непрерывной).
1eXX
Похоже одновременно изящного и эффективного решения нет, будем ставить костыли, ну, как-то так:
if (state<60)
{ switch(__even_in_range(state,58)) {...} }
else [if (state<120)]
{
state-=60;
switch(__even_in_range(state,58)) {...}
}
...
покеда :)
prottoss
Цитата(1eXX @ Oct 8 2008, 17:49) *
Похоже одновременно изящного и эффективного решения нет, будем ставить костыли, ну, как-то так:
Интресно - вы ЭТО относите к изящному или эффективному решению? smile.gif
Dog Pawlowa
Цитата(1eXX @ Oct 8 2008, 10:52) *
А какая грань, при которой он создает таблицу, не подскажете?

Я сам создаю таблицу при количестве case'ов больше десятка.
Все равно код становится длинным и нечитаемым.
1eXX
Цитата(Dog Pawlowa @ Oct 8 2008, 15:22) *
Я сам создаю таблицу при количестве case'ов больше десятка.
Все равно код становится длинным и нечитаемым.
Каким образом вы создаете таблицу, можете поведать?
Если он выполняется быстрее, то пускай он длинный и нечитаемый, для моего случая это не критично.
prottoss
Цитата(1eXX @ Oct 8 2008, 15:52) *
а у меня какие попало, с интервалом (0-10000), вразброс.
А чем это обусловлено и есть какая нить система в этих значениях?
Dog Pawlowa
Цитата(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]();
1eXX
Самое яблочко, Дог :beer:
Dog Pawlowa
Цитата(1eXX @ Oct 8 2008, 20:42) *
Самое яблочко, Дог beer.gif

Да ладно ... 05.gif
В каких-то вариантах помогает двумерный массив function[state, event].
Успехов smile.gif
Сергей Борщ
Цитата(Dog Pawlowa @ Oct 8 2008, 16:12) *
Код
...
#define     stERROR                  7
#define     stLOW_POWER            8
Для упрощения вставки/удаления элементов и исключения дублирования лучше использовать enum:
Код
enum state_t
{
    stINIT = 0,
    ....
    stERROR,
    stLOW_POWER,
};
Dog Pawlowa
Цитата(Сергей Борщ @ Oct 9 2008, 03:29) *
Для упрощения вставки/удаления элементов и исключения дублирования лучше использовать enum.

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

За ссылку спасибо, изучу.
На самом деле исключать вовсе не обязательно, поскольку непрерывность нужна только для состояний прибора, выбираемых из меню со скроллингом. Такие меню у меня содержат до 15 строчек, что не очень смертельно. Бывает, заказчик просит перетасовать пункты в меню, вот тогда да, обезьянья работа... Все остальные состояния выбираются явно, типа:
if (MIN_VOLTAGE>voltage) state=stLOW_VOLTAGE.
shasik
Цитата(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.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.