|
Нужно оптимизировать код, Есть идеи как? |
|
|
|
Jan 20 2011, 14:56
|
Местный
  
Группа: Участник
Сообщений: 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. Это возможно? А можно это как-то оформить ассемблерной вставкой? Спасибо.
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 36)
|
Jan 20 2011, 15:14
|
Участник

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

|
Жуть  А побитное или ("|") в условиях вместо логического ("||") применено осознанно? Что этот код делает? Я так понимаю что-то типа конвертации grayscale в 2бит на какой-нить индикатор?
Сообщение отредактировал codier - Jan 20 2011, 15:20
|
|
|
|
|
Jan 20 2011, 15:21
|
Местный
  
Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868

|
Спасибо за совет! Код действительно полегчал. Как я раньше этого не видел... А что Вы имели ввиду на счет табличного преобразования? Не совсем понимаю идею. Цитата(codier @ Jan 20 2011, 18:14)  Жуть  А побитное или ("|") в условиях вместо логического ("||") применено осознанно? Что этот код делает? Я так понимаю что-то типа конвертации grayscale в 2бит на какой-нить индикатор? Формирует 14 каналов програмного ШИМ в соответствии с табличкой логарифмического изменения яркости светодиода.
|
|
|
|
|
Jan 20 2011, 15:26
|
Участник

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

|
А нельзя pgm_read_byte(&brightness[pwm_ch[1]]) делать 1 раз при смене уставки ШИМ-а? Или уставка меняется каждый период и смысла нет? Тогда условие упростится до (pwm > pwm_ch[1])
|
|
|
|
|
Jan 20 2011, 15:47
|
Местный
  
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 20 2011, 18:03
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 4-11-10
Пользователь №: 60 646

|
избавьтесь от операций сдвига это забирает один так 1 << 0 = 1 1 << 1 = 2 и тд хотя нифига это не даст  компилятор умный это и сам при компиляции сделает
Сообщение отредактировал follow_me - Jan 20 2011, 18:14
|
|
|
|
|
Jan 20 2011, 20:32
|
Частый гость
 
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 21 2011, 07:38
|
Участник

Группа: Участник
Сообщений: 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
|
|
|
|
|
Jan 21 2011, 08:54
|
;
     
Группа: Участник
Сообщений: 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 такта - попробуйте работоспособность, листинг на вид рабочий, больше не разбирался.
|
|
|
|
|
Jan 21 2011, 14:01
|

неотягощённый злом
     
Группа: Свой
Сообщений: 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 сколько?
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Jan 21 2011, 18:50
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(demiurg_spb @ Jan 21 2011, 18:01)  А при -Оs сколько? тоже где-то 317-325 было Цитата(follow_me @ Jan 21 2011, 19:34)  В циклах кстати для ... Это, как и предпочтения do{}while вместо for() - суетная часть. Где-то работает, где-то компилер умнее. Я вот, недавно бодаясь с МСС18, прогнулся так, что было стыдно. Потом перестал это делать - результат оказался хуже на 2-3 процента. Оно не надо.
|
|
|
|
|
Jan 23 2011, 22:41
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Концептуально можно ускорить код - если вместо проверки каждого канала в каждом "Loop'e" таймера, организовать всего 14+1 прерываний от таймера за период в 256 тиков. (Где 14 прерываний соответствуют 14-ти каналам PWM, 15-ое - сброс всех каналов в исходное состояние). Итого для 8-ми битной глубины у вас будет не 256 прерываний за период длительностью меньше 300 тактов на обработку каждого, а всего 14+1 с ресурсом 256 * 300 / 15 = 5120 тактов на каждое. Если время срабатывания расчитывать на цикл вперед, то обработчики прерывания будут очень короткими. Программировать время следующего срабатывания каждого из прерываний можно например при сбросе всех каналов в исходное состояние. код сведется к чему-то такому: Код Timer_CompA_ISR() { turn_off( CurrentChan++ );
if (CurrentChan > MAX_CHAN_COUNT) { CurrentChan = 0; return; }
OCRA = ChanGetLifeTime( CurrentChan ); }
Timer_OvrISR() { // врубить все turn_on( AllChannels );
// посчитать такт отключения каждого из каналов (время "жизни") UpdateLifeTime( ... );
// отсортировать каналы по времени жизни по-возрастанию SortChannelsByTimeAscending( ... ); } А можно и в основном цикле программы. Обработка частных случаев (кода время жизни нескольких каналов будет совадать) тоже большого труда не составит: Код Timer_CompA_ISR() { turn_off( CurrentChan++ );
if (CurrentChan > MAX_CHAN_COUNT) { CurrentChan = 0; return; }
if (OCRA == ChanGetLifeTime( CurrentChannel ) ) Timer_CompA_ISR(); // запустить сл. канал прямо сейчас (лучше всего rjmp'ом) else OCRA = ChanGetLifeTime( CurrentChan ); // проапдейтить таймер на прерывание в нужное время }
|
|
|
|
|
Jan 24 2011, 15:05
|
Местный
  
Группа: Участник
Сообщений: 270
Регистрация: 29-06-06
Пользователь №: 18 445

|
У меня на 3 канала было вот так сделано: Код // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Reinitialize Timer 0 value TCNT0=256-39+4; //PWM----------------------- pwr_cnt++; if (red_a>pwr_cnt) { PORTD.7=1;} else {PORTD.7=0;}; if (green_a>pwr_cnt) {PORTD.6=1;} else {PORTD.6=0;}; if (blue_a>pwr_cnt) {PORTD.5=1;} else {PORTD.5=0;}; }
Оттранслировалось в: _timer0_ovf_isr: RCALL __SAVEISR ; 49 // Reinitialize Timer 0 value ; 50 TCNT0=256-39+4; LDI R30,LOW(221) OUT 0x32,R30 ; 51 //PWM----------------------- ; 52 pwr_cnt++; LDS R30,_pwr_cnt SUBI R30,-LOW(1) STS _pwr_cnt,R30 ; 53 if (red_a>pwr_cnt) {PORTD.7=1;} LDS R26,_red_a CP R30,R26 BRSH _0x2B SBI 0x12,7 ; 54 else {PORTD.7=0;}; RJMP _0x2C _0x2B: CBI 0x12,7 _0x2C: ; 55 if (green_a>pwr_cnt) {PORTD.6=1;} LDS R30,_pwr_cnt LDS R26,_green_a CP R30,R26 BRSH _0x2D SBI 0x12,6 ; 56 else {PORTD.6=0;}; RJMP _0x2E _0x2D: CBI 0x12,6 _0x2E: ; 57 if (blue_a>pwr_cnt) {PORTD.5=1;} LDS R30,_pwr_cnt LDS R26,_blue_a CP R30,R26 BRSH _0x2F SBI 0x12,5 ; 58 else {PORTD.5=0;}; RJMP _0x30 _0x2F: CBI 0x12,5 _0x30: ; 59 } RCALL __LOADISR RETI
Сообщение отредактировал pokos - Jan 24 2011, 15:21
|
|
|
|
|
Jan 24 2011, 17:37
|
Местный
  
Группа: Участник
Сообщений: 270
Регистрация: 29-06-06
Пользователь №: 18 445

|
Цитата(defunct @ Jan 24 2011, 19:22)  Должен быть выигрышь однозначно... Выигрыш будет, если забить на разницу между каналами меньше времени обработки прерывания. Если не забивать, то там ещё тот гемор получается. С соответствующей потерей бытродействия, понятно. Поэтому, я просто уменьшил разрядность ШИМа до 6-ти, когда понадобилось моргать быстрее. На глаз это уменьшение было слабо заметно (в моём случае, понятно).
|
|
|
|
|
Jan 25 2011, 10:11
|
Местный
  
Группа: Участник
Сообщений: 217
Регистрация: 11-06-10
Пользователь №: 57 868

|
Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов. Код for(unsigned char i=0;i<14;i++) { if((a & (1<<i))&(b & (1<<i))) {pwm_ch[i]=255;}//1и1 if((a & (1<<i))&(!(b & (1<<i)))) {pwm_ch[i]=255;}//1и0 if((!(a & (1<<i)))&(b & (1<<i))) {pwm_ch[i]=0;}//0и1 if((!(a & (1<<i)))&(!(b & (1<<i)))) {pwm_ch[i]=0;}//0и0 } Даже если уменьшить разрядность ШИМ втрое... уже и не знаю как и быть.
|
|
|
|
|
Jan 25 2011, 10:15
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(pokos @ Jan 24 2011, 18:05)  Код ...Оттранслировалось в: _timer0_ovf_isr: RCALL __SAVEISR .... RCALL __LOADISR RETI А теперь в азм листинге проставте тайминги. Только колл-рэт у вас 8 тактов. итого 16 ненужных тактов в плюсе. я не говорю у же о повторе одного и того же действия подряд аж 3 раза  юзается один порт. результат = обнуление определённых пинов. и если необходимая переменная больше ... то выставляем в единичку. Вам подсказать как три пина одновременно можно обнулить?  кстати можно не засовывать сразу в порт результат. ну надеюсь "куда копать" показал. думаю можно уложиться в 20-30 тактов. если в ущерб регистров - то и того меньше. короче говоря оптимизировать вагон и маленькую тележку можно ышо. хотите оптимально - пишите на азм-е. оптимизатор может "оптимизнуть" готовые функции из библиотеки - на 5+, а вот логику - тут уж сильно зависит от опыта того кто писал оптимизатор и за сколько вы его купили. чиссо ИМХО: собственно если пишите в одни руки, доводите проекты до коммерческого ума - то юзать выше чем азм не совсем в струю. удачи вам (круглый)
|
|
|
|
|
Jan 25 2011, 10:46
|
Местный
  
Группа: Участник
Сообщений: 416
Регистрация: 18-04-06
Из: Челябинск
Пользователь №: 16 219

|
Цитата(pokos @ Jan 24 2011, 19:05)  У меня на 3 канала было вот так сделано: Код // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // Reinitialize Timer 0 value TCNT0=256-39+4; //PWM----------------------- pwr_cnt++; if (red_a>pwr_cnt) { PORTD.7=1;} else {PORTD.7=0;}; if (green_a>pwr_cnt) {PORTD.6=1;} else {PORTD.6=0;}; if (blue_a>pwr_cnt) {PORTD.5=1;} else {PORTD.5=0;}; } Попробуйте так Код // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { char _tmp; // Reinitialize Timer 0 value TCNT0=256-39+4; //PWM----------------------- _tmp = ++pwr_cnt; if (red_a > _tmp) { PORTD.7=1;} else {PORTD.7=0;}; if (green_a > _tmp) {PORTD.6=1;} else {PORTD.6=0;}; if (blue_a > _tmp) {PORTD.5=1;} else {PORTD.5=0;}; }
|
|
|
|
|
Jan 25 2011, 11:39
|
Местный
  
Группа: Участник
Сообщений: 270
Регистрация: 29-06-06
Пользователь №: 18 445

|
Цитата(kolobok0 @ Jan 25 2011, 13:15)  А теперь в азм листинге проставте тайминги. Проставлял, было дело. Преехал на IAR по этому поводу. Цитата ...Вам подсказать как три пина одновременно можно обнулить? Спасибо, я в курсе. А как одновременно обнулить 14 пинов, не подскажете? Которые в разных портах. И чтобы при этом максимальный коэф. заполнения был ровно 1? Займитесь на досуге этими вопросами, увидите, что моё решение не самое плохое. Цитата хотите оптимально - пишите на азм-е. Не хочу писать на Асме, надоело. Оптимально - это когда задача выполнена за требуемое время. Потому и не хочу. Цитата(_Bill @ Jan 25 2011, 13:46)  Попробуйте так ..._tmp = ++pwr_cnt;... Да, конечно. В конечном варианте pwr_cnt и так в регистре сидит. Тогда присваивание - лишнее, только тормозит. Цитата(skyled @ Jan 25 2011, 13:11)  Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов. Само собой. Индексация в массиве - это конь прожорливый. Цикл развернуть в линиию, указатель на массив сделать отдельным. Инкрементировать его. Помнится, IAR такие вещи правильно оптимизировал. Попробуйте. И я не очень понимаю, зачем этот странный наворот со сдвигами. В чём его цель?
Сообщение отредактировал pokos - Jan 25 2011, 11:34
|
|
|
|
|
Jan 25 2011, 11:52
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(skyled @ Jan 25 2011, 13:11)  Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов. Код for(unsigned char i=0;i<14;i++) { if((a & (1<<i))&(b & (1<<i))) {pwm_ch[i]=255;}//1и1 if((a & (1<<i))&(!(b & (1<<i)))) {pwm_ch[i]=255;}//1и0 if((!(a & (1<<i)))&(b & (1<<i))) {pwm_ch[i]=0;}//0и1 if((!(a & (1<<i)))&(!(b & (1<<i)))) {pwm_ch[i]=0;}//0и0 } Даже если уменьшить разрядность ШИМ втрое... уже и не знаю как и быть. имхо, у Вас попутаны ! и ~. Эта жуть приводится к Код for(unsigned char i=0, unsigned int tmp = 1; i<14; i++) { if(a & tmp) pwm_ch[i]=255; //1и1, 1и0 else pwm_ch[i]=0; //0и1, 0и0 tmp <<= 1; } Можете ещё пооптимизировать в сторону unsigned char tmp = 1; и (high) a, (low) a (или как оно там в винавре)
|
|
|
|
|
Jan 25 2011, 12:16
|

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

|
QUOTE (skyled @ Jan 25 2011, 12:11)  Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов. Мама! 1) Вы на каждой итерации делаете сдвиг единицы на i разрядов. Для процессора без аппаратного сдвигателя это очень накладная операция. 2) Вы используете двоичное "И" (&) вместо логического (&&). 3) заметьте, что у вас результат не зависит от значения b CODE uint8_t *ptr = &pwm_ch[13]; for(uint16_t mask = (1<<13); mask; mask >>= 1) { if(a & mask) *ptr-- = 255; else *ptr-- = 0; } P.S. Ой, xemul уже то же самое написал. Возможно, у него код даже лучше. P.P.S. ! и ~ у него не попутаны.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 25 2011, 21:07
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(kolobok0 @ Jan 25 2011, 13:15)  хотите оптимально - пишите на азм-е. оптимизатор может "оптимизнуть" готовые функции из библиотеки - на 5+, а вот логику - тут уж сильно зависит от опыта того кто писал оптимизатор и за сколько вы его купили. Поздно! Вот годика 4 назад, когда еще было много проблем с сями, тогда бы это звучало серьезно. Сейчас - увы. Цитата(Сергей Борщ @ Jan 25 2011, 15:16)  Мама!  Цитата(skyled @ Jan 25 2011, 13:11)  Тут выяснилось, что еще вот эта конструкция кушает невообразимое число тактов. Ара щто ти здэляль со мной? Йа плакаль, перед женщин стидно..
|
|
|
|
|
Jan 25 2011, 22:00
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

|
Цитата(_Pasha @ Jan 26 2011, 00:07)  ...Вот годика 4 назад... давайте оставим коней в вакууме - пускай отдыхают. если опираться то на факты (посему скорость написания, какчество и прочую чухню - оставим в покое). берём код который народ постит после компиляторов(в азм инструкциях) и от этого пляшем. вы утверждаете что оптимизатор справляется во всех случаях на 5? это хфантастика... как пример - код товарища выше. или Вы чиссо по животным в вакууме специализируетесь? удачи вам (круглый) ЗЫ всё конечно же зависит от задачи. в своё время приходилось писать и аля шарп технологию под 4051 кристал. но то так было задумано
|
|
|
|
|
Jan 26 2011, 14:06
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(Сергей Борщ @ Jan 25 2011, 15:16)  P.P.S. ! и ~ у него не попутаны. Замена ! на ~ без каких-либо ещё изменений даст лучший код на выходе. Замена посерёдке & на && добавит логичности сорцу и код тоже не ухудшит. А ненужный битово-логический замес, устроенный skyled'ом, не даёт ничего, кроме головняка оптимизатору.
|
|
|
|
|
Jan 26 2011, 18:39
|

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

|
QUOTE (xemul @ Jan 26 2011, 16:06)  Замена ! на ~ без каких-либо ещё изменений даст лучший код на выходе. Да, естественно. Он сведется к циклу pwm[i] = 255. Ибо X & (1<<i) дает либо 0, либо 1<<i, !(X & (1<<i)) имеет результат 1 или 0, а вот ~(X & (1<<i)) даст либо int из всех единиц, либо из всех единиц кроме i-го разряда, что в обоих случаях true.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 1 2011, 16:37
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(defunct @ Feb 1 2011, 15:51)  Ни один компилятор не даст такой эффективный код, какой может сделать __опытный__ асм программист. Проблема в интенсивном использовании компилятором(winavr) инструкций lds/sts - это раз. 192 такта при -О3(см. в начале темы) - целиком за счет разворачивания цикла. Это два. Там около 490 байт заняло оно, забыл тогда сказать. Там на регистровые переменные тоже не особо разбежишься - надо использовать ldd/std А по Вашему предложению - автор если собрался его реализовать, все-таки интересно, во сколько циклов оно встанет.  Извините за словесный понос.
|
|
|
|
|
Feb 2 2011, 02:24
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(_Pasha @ Feb 1 2011, 18:37)  А по Вашему предложению - автор если собрался его реализовать, все-таки интересно, во сколько циклов оно встанет. Ресурсоемкость кода сократиться в 18 раз только за счет того что прерываний стало в 18 раз меньше, плюс ресурсоемкость самих обработчиков сократится еще в 10 раз за счет того что обрабатываются не все 14, а только 1 канал. Итого на 2 порядка меньше от посчитанных Вами 190 тактов ) На асм писать не предлагаю - здесь нет в этом нужды. Цитата Там на регистровые переменные тоже не особо разбежишься - надо использовать ldd/std ldd/std определенно пользовать не надо. Массив 14-ти каналов разместить в регистрах, благо в AVR их аж 16 лишних.  обработчик прерывания банально пишем 5 команд и копипастим 14 раз: mov - 1 такт lpm - 3 cp - 1 brlo вместе с cbi/sbi - 2 такта. Итого на асм 1 + (1 + 3 + 1 + 2) * 14 = 99 тактов решением в лоб. ;>
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|