Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Оптимизация конструкции switch

#c


Есть код вида
unsigned char toggle;
unsigned char value[255];

/* ... */

switch (toggle)
{
    case 0: 
        /* Первое действие над value[toggle] */
        break;
    case 1: 
        /* Второе действие над value[toggle] */
        break;
    case 255: 
        /* Последнее действие над value[toggle] */
        break;
}

И этот код очень интенсивно крутится в цикле. Какие есть возможности для его ускорения?    


Ответы

Ответ 1



Если ничего конкретного не известно про действия, то рекомендации могут быть только общими: Заставьте компилятор сгенерировать jump table вместо кучи if-else. Если уж не получается jump table, самый часто встречающиеся альтернативы перенесите наверх (хотя это зависит от компилятора — некоторые генерят if-else код не в том порядке, в котором записан switch). Добавлено: Вот, например, про gcc. Судя по тому, что там написано, если я правильно понял Ваш вопрос (т.е. у Вас используются все 256 вариантов, а не только три по краям), то есть реальный шанс получить jump table.

Ответ 2



Как вариант - создать массив с указателями на функции: typedef void(*func)(unsigned char& value); unsigned char toggle; unsigned char value[255]; void f1(unsigned char& _value){/* ... */} void f2(unsigned char& _value){/* ... */} void f3(unsigned char& _value){/* ... */} /* ссылки в аргументах здесь нужны, если массив value вне зоны видимости. Если же функции и value в одной скопе, то можно сделать и так: typedef void(*func)(void); void f1(){value[toggle] = 20;} ... */ func handlers[255]{f1, f2, f3 /* ... */}; void loop() { // Здесь вместо switch можно просто поставить вызов функции по указателю: handlers[toggle](value[toggle]); } Вызов функций или твой свитч - мне кажется, что обращение к массиву быстрее серии if-ов, генерируемых компилятором. И да, жрёт память.

Ответ 3



Никаких. Только вставки на Ассемблере. Это все что можно сказать из того что вы написали.

Ответ 4



в том варианте который вы написали - ничего умного в голову по оптимизации не приходит. Если реально тормозит то смотрите на задачу шире: может стоит поменять архитектуру в целом нежели отдельный switch. Конечно советовать легко, если есть куча кода (особенно не тобой написанного) - то делать тяжело, сначала ответьте на вопрос что делает программа в целом и отдельныее ее модули в частности, возможно можно будет перейти на многопоточность. У меня был в практике код, правда писал его я сам - потому понимал что там написанно. Сначала на коленке (быстро) надо было написать такой вот функционал: приходит на сайт пользователь от яндекса гугла и т.п. - возможно содержит в запросе поисковый запрос, как раз анализ этого запроса интересен. если запрос 'идентичен' какому то из списка интересных нам запросов ... что то делаем. первая версия (на коленке) самый обычный strstr. при этом каждый запрос пользователя проходит по списку интересных нам запросов и strstr. нагрузка зависит от количества интересующих нас запросов и количества пользователей пришедших на сайт с поисковым запросом. Архитектурно программу не улучшить - многопоточная можно разносить по машинам. Алгоритмически оказалось что можно улучшить. сначала ЦП юзался на 30 % - терпимо (сервис написан был на java - ввиду быстроты написания, множества стандартных готовых классов типа пула потоков, какой то анализ URL). потом стали добавлять новые запросы нам интересные - очень много в итоге ЦП - 200 - 250 % - надо что то делать .... версия номер 2. все осталось на яве (не думайте что переписывал на С/С++ :) ). архитектура приложения та же. алгоритм поиска поменял. вместо strstr. создал некое подобие поисковой машины. перешел к хешам слов от них хеши поисковых фраз. в итоге поиск свелся к наличию в сете (или хеше не помню уже) интов. сразу же нагрузка на ЦП снизилась до 2-4%. и остались прежние плюсы по архитектуре (нити, масштибируемость). Это просто мой пример - работало хреново, решать можно было вводом в строй новых компов - но надо чтобы сервис и сам код были горизонтально масштбируемы, в моем случае это так а нужные нам фразы - они хоть и есть на каждом компе - но их не много и память которую они едят для нас пока не критична - упремся в нее - будем думать дальше - например не будем хранить сами исходные фразы (нужны для логов сейчас). второй путь - что то сделать с самим алгоритмом - он как раз долго выполнялся запросы как текли примерно 50 в сек так и текут но вот обработка одного запроса она удлинялась с добавлением новых поисковых фраз, в итоге новые потоки и ЦП 250%. ну в общем теперь это самое некритичное место системы. Думайте. успехов. сложные задачи решать интересно. :)

Комментариев нет:

Отправить комментарий