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

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Нужно оптимизировать код, Есть идеи как?
skyled
сообщение Jan 20 2011, 14:56
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868



Есть такой кусок кода:
Код
if((pwm>pgm_read_byte(&brightness[pwm_ch[0]]))|(pwm==0)){pd &= ~(1<<0);}//1
        else {pd |= (1<<0);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[1]]))|(pwm==0)){pd &= ~(1<<1);}//2    
        else {pd |= (1<<1);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[2]]))|(pwm==0)){pa &= ~(1<<1);}//3
        else {pa |= (1<<1);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[3]]))|(pwm==0)){pa &= ~(1<<0);}//4
        else {pa |= (1<<0);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[4]]))|(pwm==0)){pd &= ~(1<<2);}//5
        else {pd |= (1<<2);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[5]]))|(pwm==0)){pd &= ~(1<<3);}//6
        else {pd |= (1<<3);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[6]]))|(pwm==0)){pd &= ~(1<<4);}//7
        else {pd |= (1<<4);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[7]]))|(pwm==0)){pd &= ~(1<<5);}//8
        else {pd |= (1<<5);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[8]]))|(pwm==0)){pb &= ~(1<<4);}//9
        else {pb |= (1<<4);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[9]]))|(pwm==0)){pb &= ~(1<<3);}//10
        else {pb |= (1<<3);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[10]]))|(pwm==0)){pb &= ~(1<<2);}//11
        else {pb |= (1<<2);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[11]]))|(pwm==0)){pb &= ~(1<<1);}//12
        else {pb |= (1<<1);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[12]]))|(pwm==0)){pb &= ~(1<<0);}//13
        else {pb |= (1<<0);}
        if((pwm>pgm_read_byte(&brightness[pwm_ch[13]]))|(pwm==0)){pd &= ~(1<<6);}//14
        else {pd |= (1<<6);}
Он обрабатывается за 345 тактов. Мне нужно менее 300. Это возможно? А можно это как-то оформить ассемблерной вставкой? Спасибо.
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 20 2011, 15:07
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Проверку pgm==0 из каждого условия уберите, сделав проверку один раз и при выполнении ее сбрасывайте все биты одним чохом. Остальные проверки можно попробовать сделать в виде цикла с табличным преобразованием результата.
Go to the top of the page
 
+Quote Post
codier
сообщение Jan 20 2011, 15:14
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 21-01-05
Пользователь №: 2 113



Жуть sm.gif

А побитное или ("|") в условиях вместо логического ("||") применено осознанно?

Что этот код делает? Я так понимаю что-то типа конвертации grayscale в 2бит на какой-нить индикатор?

Сообщение отредактировал codier - Jan 20 2011, 15:20
Go to the top of the page
 
+Quote Post
skyled
сообщение Jan 20 2011, 15:21
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868



Спасибо за совет! Код действительно полегчал. Как я раньше этого не видел... А что Вы имели ввиду на счет табличного преобразования? Не совсем понимаю идею.

Цитата(codier @ Jan 20 2011, 18:14) *
Жуть sm.gif

А побитное или ("|") в условиях вместо логического ("||") применено осознанно?

Что этот код делает? Я так понимаю что-то типа конвертации grayscale в 2бит на какой-нить индикатор?

Формирует 14 каналов програмного ШИМ в соответствии с табличкой логарифмического изменения яркости светодиода.
Go to the top of the page
 
+Quote Post
codier
сообщение Jan 20 2011, 15:26
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 21-01-05
Пользователь №: 2 113



А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1])
Go to the top of the page
 
+Quote Post
skyled
сообщение Jan 20 2011, 15:47
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868



Цитата(codier @ Jan 20 2011, 18:26) *
А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1])

Ну тут идея какая... ШИМ тикает 256 раз. В программе, откуда я этот кусок выдрал, значения могли меняться в любой момент времени. Во-вторых проверять нужно каждый тик на предмет выключить лампочку чтобы обеспечить глубину 8 бит. Да вобщемто уставка меняется не каждый период, но всеравно меняется. Так что деваться по сути всеравно некуда. Можно было бы выгрузить это в ОЗУ, но ОЗУ нет почти. Tiny2313.

Сообщение отредактировал skyled - Jan 20 2011, 15:50
Go to the top of the page
 
+Quote Post
follow_me
сообщение Jan 20 2011, 18:03
Сообщение #7


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

Группа: Участник
Сообщений: 182
Регистрация: 4-11-10
Пользователь №: 60 646



избавьтесь от операций сдвига это забирает один так

1 << 0 = 1
1 << 1 = 2 и тд

хотя нифига это не даст sad.gif компилятор умный это и сам при компиляции сделает

Сообщение отредактировал follow_me - Jan 20 2011, 18:14
Go to the top of the page
 
+Quote Post
777777
сообщение Jan 20 2011, 18:08
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(follow_me @ Jan 20 2011, 21:03) *
избавьтесь от операций сдвига это забирает один так

1 << 0 = 1
1 << 1 = 2 и тд

А ты оттранслируй и посмотри. Чисто из любопытства. sm.gif
Go to the top of the page
 
+Quote Post
follow_me
сообщение Jan 20 2011, 18:40
Сообщение #9


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

Группа: Участник
Сообщений: 182
Регистрация: 4-11-10
Пользователь №: 60 646



pwm>pgm_read_byte(&brightness[pwm_ch[7]])

что лежит в pwm ?
что возвращает pgm_read_byte() ?

как я понимаю brightness[] это собственно табличка логорифмического преобразования а pwm_ch[] это то значение которое мы получили ?
Go to the top of the page
 
+Quote Post
smk
сообщение Jan 20 2011, 19:09
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Цитата(follow_me @ Jan 20 2011, 20:40) *
pwm>pgm_read_byte(&brightness[pwm_ch[7]])

что лежит в pwm ?
что возвращает pgm_read_byte() ?

как я понимаю brightness[] это собственно табличка логорифмического преобразования а pwm_ch[] это то значение которое мы получили ?

совершенно верно.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
follow_me
сообщение Jan 20 2011, 20:32
Сообщение #11


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

Группа: Участник
Сообщений: 182
Регистрация: 4-11-10
Пользователь №: 60 646



Цитата(smk @ Jan 20 2011, 21:09) *
совершенно верно.

меня с точки зрения оптимизации волнует больше что возвращает pgm_read_byte

потому что очень большое чувство что можно там сократить до pgm_read_byte (pwm_ch[] ) или вообще привести к статичной табличке потому что у вас
результат прямо и однозначно зависит от значения которое лежит в pwm_ch[] значит и конечный результат можно предварительно вычислить и получить в виде val [pwm_ch[]] и тогда код сведется к красивому виду вроде
pb = (pwm > val[pwm_ch[]]) ? (pb & ~1) : (pb | 1);
а так как вы передаёте значения по ссылке то компилятор не сможет сделать этого за вас

UPD -----------------------------------------------------------------------------------------------------
Набросал небольшой кусочек кода , прошу общественность ногами не пинать , давно не писал на С сейчас пишу на языке более высокого уровня потому мог какие-то фенички оттуда утащить
Код
#проверяем и сбрасываем сразу при нуле
#два массива мапят порты (кто хочет можно массивом двумерных массивов , но по моему так проще)
#цикл проверки каналов и задания соответствующих значений (тут считается что автор пересчитал свой массивчик brightness до статических значений )
if ( pwm == 0 ) { pa |= 3; pb |= 31; pd |= 127; } else {
  int     log2phy[] = { pd, pd, pa, pa, pd, pd, pd, pd, pb, pb, pb, pb, pb, pd };
  char  log2val[] = {  1,  2,  2,  1,  4,  8, 16, 32, 16,  8,  4,  2,  1, 64 };
  for (int i = 0; i < 14; ++i )
   { log2phy[i] = (pwm > brightness[pwm_ch[i]]) ? (log2phy[i] & ~log2val[i]]) : (log2phy[i] | log2val[i]); }
}


Сообщение отредактировал follow_me - Jan 20 2011, 23:09
Go to the top of the page
 
+Quote Post
777777
сообщение Jan 21 2011, 07:18
Сообщение #12


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Еще можно для оптимизации вытащить brightness из флэш и поместить в ОЗУ. К нему обращение будет немного быстрее.
Go to the top of the page
 
+Quote Post
codier
сообщение Jan 21 2011, 07:38
Сообщение #13


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 21-01-05
Пользователь №: 2 113



2follow_me:
2777777:

Глянул искомый девайс:
Цитата
2KB of In-System Self-Programmable Flash, 128 Bytes In-System Programmable EEPROM, 128 Bytes Internal SRAM


В принципе, зависит от задачи, но мне кажется, что лучше RAM не забивать лишними данными. По приведённому коду есть одно сомнение, оно же - идея для оптимизации. Надо чтобы для установки/сброса битов использовались инструкции SBR и CBR, а не логическая арифметика.

А вообще, ШИМ контроллер, хоть и программный должен ШИМ-ом заниматься, а не осуществлять ещё и логарифмические преобразования :-)

IMHO

UPD: Я имел ввиду SBI, CBI :-)

Сообщение отредактировал codier - Jan 21 2011, 07:46
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 21 2011, 08:54
Сообщение #14


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Все чаще и чаще наблюдаются жутковатые перлы. По теме:
CODE

#include <avr/io.h>
#include <avr/pgmspace.h>
PROGMEM char brightness[] = "888888888888888888888888888";

volatile unsigned char pwm;
volatile unsigned int pd;
volatile unsigned char pwm_ch[14];

int main(void)
{
if(pwm)
{
unsigned char *pwmch = &pwm_ch;
int d = 0;
for(char i=0; i<14; i++)
{
unsigned int msk = 1;
if(pwm <= pgm_read_byte(&brightness[*pwmch++])) pd |= msk;
msk <<= 1;
}
pd = d;
}
else
{
pd = 0;
}
return 0;
}

В таком (страшненьком) виде (-О2) - уже 317 тактов на меге 8
Копнуть можно, если выровнять таблицу констант на границу 256 байт и упростить обращения к 16-битному pd |= msk;


Несколько апдейтов.
1. if(pwm <= pgm_read_byte(&brightness[*pwmch++])) pd |= msk; - конечно же надо
if(pwm <= pgm_read_byte(&brightness[*pwmch++])) d |= msk;

2. При -О3 дало 192 такта - попробуйте работоспособность, листинг на вид рабочий, больше не разбирался.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jan 21 2011, 14:01
Сообщение #15


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(777777 @ Jan 21 2011, 10:18) *
Еще можно для оптимизации вытащить brightness из флэш и поместить в ОЗУ. К нему обращение будет немного быстрее.

Ага 2 такта вместо 3 при косвенной - крутотень какая:-).
На общем фоне капля в море - даже и не заметишь (к примеру 150 или 151 так).


Цитата(_Pasha @ Jan 21 2011, 11:54) *
В таком (страшненьком) виде (-О2) - уже 317 тактов на меге 8
При -О3 дало 192 такта

А при -Оs сколько?


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

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

 


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


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