|
Оптимизация switch? |
|
|
|
Oct 7 2008, 18:39
|

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

|
Привет народ! Посоветуйте, как можно создать таблицу переходов для оптимизации switch (case-ов за сотню)? "__even_in_range" в данном случае не очень универсален и ограничен 30 переходами. Заранее благодарен за любую идею.
|
|
|
|
|
Oct 8 2008, 07:52
|

Группа: Новичок
Сообщений: 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), вразброс.
|
|
|
|
|
Oct 8 2008, 09:49
|

Группа: Новичок
Сообщений: 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)) {...} } ... покеда :)
|
|
|
|
|
Oct 8 2008, 11:58
|

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

|
Цитата(Dog Pawlowa @ Oct 8 2008, 15:22)  Я сам создаю таблицу при количестве case'ов больше десятка. Все равно код становится длинным и нечитаемым. Каким образом вы создаете таблицу, можете поведать? Если он выполняется быстрее, то пускай он длинный и нечитаемый, для моего случая это не критично.
|
|
|
|
|
Oct 8 2008, 13:12
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(1eXX @ Oct 8 2008, 14:58)  Каким образом вы создаете таблицу, можете поведать? Если он выполняется быстрее, то пускай он длинный и нечитаемый, для моего случая это не критично. Примитивно //определения аргументов 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]();
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Oct 8 2008, 17:42
|

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

|
Самое яблочко, Дог :beer:
|
|
|
|
|
Oct 9 2008, 00:29
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Oct 9 2008, 05:23
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(Сергей Борщ @ Oct 9 2008, 03:29)  Для упрощения вставки/удаления элементов и исключения дублирования лучше использовать enum. Хороший вопрос, необходимость корректировок иногда возникает. Делаю дыры или их забиваю. Конечно, я думал об этом, но к номеру состояния у меня привязаны еще массивы - как минимум массив функций обработки состояния. То есть все равно при исключении элемента из enum, нужно по имени найти и исключить подобный элемент из другого массива, строго соблюдая порядок. А их сотня. То есть рядом в тексте не расположить. А здесь я на видимом участке текста вижу все. Может, как-то макросами можно извратиться - не придумал. Если подскажете удобный способ, с меня
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Oct 9 2008, 07:01
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Oct 9 2008, 08:24
|
Гуру
     
Группа: Свой
Сообщений: 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.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Oct 10 2008, 18:09
|

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

|
Цитата(Dog Pawlowa @ Oct 8 2008, 16:12)  Небольшая модификация предложенного 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.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|