|
поменять местами биты в байте, простой вопрос |
|
|
|
 |
Ответов
(1 - 46)
|
Apr 25 2010, 20:04
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
я это вижу как цикл на 8 шагов где проверяется значение последнего бита в байте и это значение присваивается первому биту новому байту ну и затем сдвиг обоих на 1 вот только знаний не хватает как реализовать да в пересчете я наврал, ну думаю принцип Вы поняли что я пытался объяснить
Сообщение отредактировал Vny4ek - Apr 25 2010, 20:05
|
|
|
|
|
Apr 25 2010, 20:04
|
Частый гость
 
Группа: Участник
Сообщений: 92
Регистрация: 23-12-08
Из: Кишинёв
Пользователь №: 42 680

|
Сумбурное описание, но если правильно понял то типа того: Код uint8_t InverseByte(uint8_t b) { uint8_t ret = 0; for( int i = 0; i < 8; i++ ) { ret |= ( ( b & ( 1 << i ) ) ? 1 : 0 ) << ( 7 - i ); } return ret; } 0x72->0x4E
|
|
|
|
|
Apr 25 2010, 20:57
|
Частый гость
 
Группа: Участник
Сообщений: 92
Регистрация: 23-12-08
Из: Кишинёв
Пользователь №: 42 680

|
Цитата(KRS @ Apr 25 2010, 23:46)  Можно же стандартный способ использовать примерно так он пишется: Код a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1); a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2); a = (a >> 4) | (a << 4); Прикольно, наверное Кнут? Цикл всегда можно развернуть, правда там всё равно на два действия выходит больше...
|
|
|
|
|
Apr 25 2010, 21:12
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(baralgin @ Apr 25 2010, 22:57)  Цикл всегда можно развернуть, правда там всё равно на два действия выходит больше... То, что Вы написали весьма страшно  . И дело не в цикле (например стремимся к минимальному размеру, тогда прием KRS отдыхает) а в том, как он написан. Такое: Код uint8_t InverseByte(uint8_t b) { uint8_t ret = 0; for( uint8_t i = 0x80; i; i >>= 1 ) { if( b & 1 ) ret |= i; b >>= 1; } return ret; } будет в разы короче и быстрее. А такое, чуть увеличившись в размере, если повезет  , обгонит KRS и по скорости: Код uint8_t InverseByte(uint8_t b) { uint8_t ret = 0; for( uint8_t i = 0x80; b; b >>= 1 ) { if( b & 1 ) ret |= i; i >>= 1; } return ret; }
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 25 2010, 21:55
|
Частый гость
 
Группа: Участник
Сообщений: 92
Регистрация: 23-12-08
Из: Кишинёв
Пользователь №: 42 680

|
Не поленился, проверил (плохая привычка меряться.. на ночь глядя  ). CODE #include <cstdlib> #include <iostream> #include <windows.h> #include <stdint.h>
static uint8_t InverseByte_zltigo(int b ) { int ret = 0; for( int i = 0x80; i; i >>= 1 ) { if( b & 1 ) ret |= i; b >>= 1; } return ret; }
static uint8_t InverseByte_zltigo2(int b ) { int ret = 0; for( int i = 0x80; b; b >>= 1 ) { if( b & 1 ) ret |= i; i >>= 1; } return ret; }
static uint8_t InverseByte(int b ) { return ( (b & 0x01) << 7 | (b & 0x02) << 5 | (b & 0x04) << 3 | (b & 0x08) << 1 | (b & 0x10) >> 1 | (b & 0x20) >> 3 | (b & 0x40) >> 5 | (b & 0x80) >> 7 ); }
static void Benchmark( uint8_t (*test_func)(int)) { LARGE_INTEGER start, end; QueryPerformanceCounter(&start); int seed = 0x72; for(int i = 0; i < 100000000; i++ ) seed = test_func(seed); QueryPerformanceCounter(&end); std::cout << "time=" << end.QuadPart - start.QuadPart << std::endl; }
int _tmain(int argc, _TCHAR* argv[]) { Benchmark( &InverseByte_zltigo ); Benchmark( &InverseByte_zltigo2 ); Benchmark( &InverseByte );
return 0; }
Результат на моём процессоре (A64, Brisbane, L2=512kb): time=11045076 time=6801262 time=3793456 Видимо сравнения мешают. Я внёс немного самодеятельности и обозвал все внутренние переменные int'ом - так быстрее(для всего что выше avr). ps: но по скорости всё равно таблица рулит, как предложили выше. ps2: мой развёрнутый цикл идёт из немного модифицированного первого варианта: ret |= ( ( b & ( 1 << i ) ) >>i ) << ( 7 - i ); ps3: от порядка следования тестов результат конечно же зависит, но кардинально ничего не меняет.
Сообщение отредактировал baralgin - Apr 25 2010, 22:02
|
|
|
|
|
Apr 25 2010, 22:04
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(baralgin @ Apr 25 2010, 23:55)  Не поленился Сильно поленились - у Автора всего лишь AVR а не Atlon . А во вторых и для AVR8 это фатально, переврали мои примеры и вписали int вместо insigned char. В третьих, а почему свой вариант не протестировали  ? Вот как он выглядит на AVR8: Код 15 BYTE InverseByte(BYTE b) \ InverseByte: 16 { \ 00000000 2F59 MOV R21, R25 \ 00000002 2F68 MOV R22, R24 \ 00000004 2F30 MOV R19, R16 17 BYTE ret = 0; \ 00000006 E020 LDI R18, 0 18 for( int i = 0; i < 8; i++ ) \ 00000008 E080 LDI R24, 0 \ 0000000A E090 LDI R25, 0 19 { 20 ret |= ( ( b & ( 1 << i ) ) ? 1 : 0 ) << ( 7 - i ); \ ??InverseByte_0: \ 0000000C 2F48 MOV R20, R24 \ 0000000E E001 LDI R16, 1 \ 00000010 E010 LDI R17, 0 \ 00000012 .... RCALL ?S_SHL_L02 \ 00000014 2F13 MOV R17, R19 \ 00000016 2310 AND R17, R16 \ 00000018 F011 BREQ ??InverseByte_1 \ 0000001A E001 LDI R16, 1 \ 0000001C C001 RJMP ??InverseByte_2 \ ??InverseByte_1: \ 0000001E E000 LDI R16, 0 \ ??InverseByte_2: \ 00000020 E010 LDI R17, 0 \ 00000022 E047 LDI R20, 7 \ 00000024 1B48 SUB R20, R24 \ 00000026 .... RCALL ?S_SHL_L02 \ 00000028 2B20 OR R18, R16 21 } \ 0000002A 9601 ADIW R25:R24, 1 \ 0000002C 3088 CPI R24, 8 \ 0000002E E000 LDI R16, 0 \ 00000030 0790 CPC R25, R16 \ 00000032 F364 BRLT ??InverseByte_0 22 return ret; \ 00000034 2F02 MOV R16, R18 \ 00000036 2F86 MOV R24, R22 \ 00000038 2F95 MOV R25, R21 \ 0000003A 9508 RET 23 } А так нормально написанный цикл Код 15 BYTE InverseByte(BYTE b) \ InverseByte: 16 { 17 BYTE ret = 0; \ 00000000 E020 LDI R18, 0 18 for( BYTE i = 0x80; i; i >>= 1 ) \ 00000002 E810 LDI R17, 128 19 { 20 if( b & 1 ) \ ??InverseByte_0: \ 00000004 FB00 BST R16, 0 \ 00000006 F40E BRTC ??InverseByte_1 21 ret |= i; \ 00000008 2B21 OR R18, R17 22 b >>= 1; \ ??InverseByte_1: \ 0000000A 9506 LSR R16 23 } \ 0000000C 9516 LSR R17 \ 0000000E F7D1 BRNE ??InverseByte_0 24 return( ret ); \ 00000010 2F02 MOV R16, R18 \ 00000012 9508 RET 25 } А в четвертых попробуйте этот Ваш сравнительный тест, например, на 0x01 и узнаете немного о везении.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 25 2010, 22:31
|
Частый гость
 
Группа: Участник
Сообщений: 92
Регистрация: 23-12-08
Из: Кишинёв
Пользователь №: 42 680

|
Цитата(zltigo @ Apr 26 2010, 01:04)  Сильно поленились - у Автора всего лишь AVR а не Atlon . А во вторых и для AVR8 это фатально, переврали мои примеры и вписали int вместо insigned char. В третьих, а почему свой вариант не протестировали  ? А в четвертых попробуйте этот сравнительный тест, например, на 0x01 и узнаете немного о везении. Во первых под рукой нет avr и именно по этому uint8_t превратился в int. Для avr конечно нужно просто uint8_t. Далее свой(первый) вариант протестировал... и он оказался быстрее всех  - смотрел несколько раз, менял местами тесты. Быстрее он. Видимо архитектура процессора+ компилятор(VS2008Express, оптимизация на скорость). Насчёт 0x01: не корректно. Потому что компилятор умудряется считать результат до исполнения  . Зато есть более корректный способ: подать в функцию случайную последовательность. Тогда влияние кэша и предсказателя(и возможно других фишек процессора) будет меньше. Вот новый вариант(с первой функцией) и случайным входом: CODE #include <cstdlib> #include <iostream> #include <windows.h> #include <stdint.h>
static uint32_t x, y, z, w; static void reset_xor128() { x = 123456789; y = 362436069; z = 521288629; w = 88675123; }
static uint32_t xor128() { uint32_t t; t=(x^(x<<11));x=y;y=z;z=w; return(w=(w^(w>>19))^(t^(t>>8))); }
static uint8_t InverseByte_zltigo(int b ) { int ret = 0; for( int i = 0x80; i; i >>= 1 ) { if( b & 1 ) ret |= i; b >>= 1; } return ret; }
static uint8_t InverseByte_zltigo2(int b ) { int ret = 0; for( int i = 0x80; b; b >>= 1 ) { if( b & 1 ) ret |= i; i >>= 1; } return ret; }
static uint8_t InverseByte_unroll(int b ) { return ( (b & 0x01) << 7 | (b & 0x02) << 5 | (b & 0x04) << 3 | (b & 0x08) << 1 | (b & 0x10) >> 1 | (b & 0x20) >> 3 | (b & 0x40) >> 5 | (b & 0x80) >> 7 ); }
static uint8_t InverseByte_first(int b ) { int ret = 0; for( int i = 0; i < 8; i++ ) { ret |= ( ( b & ( 1 << i ) ) ? 1 : 0 ) << ( 7 - i ); } return ret; }
static void Benchmark( uint8_t (*test_func)(int)) { LARGE_INTEGER start, end; reset_xor128(); QueryPerformanceCounter(&start); for(int i = 0; i < 100000000; i++ ) test_func( xor128() & 0xFF ); QueryPerformanceCounter(&end); std::cout << "time=" << end.QuadPart - start.QuadPart << std::endl; }
int _tmain(int argc, _TCHAR* argv[]) { Benchmark( &InverseByte_unroll ); Benchmark( &InverseByte_first ); Benchmark( &InverseByte_zltigo ); Benchmark( &InverseByte_zltigo2 );
return 0; } И результат: time=4589919 time=4583382 time=18303765 time=16308624 ps: После нескольких испытаний пришёл всёже выводу что InverseByte_unroll и InverseByte_first примерно равны по скорости. Но в любом случае это всё архитектурнозависимо и тестировать нужно на том железе, где будет работать(оказывается что даже инструкции специальные для этого бывают  ).
|
|
|
|
|
Apr 26 2010, 06:58
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Vny4ek @ Apr 26 2010, 07:33)  я проще себе это представлял, не знаю только как на языке реализовать: Все плохо, Вы, как оказалось, не только написать не можете, но и прочитать уже написанное  . Ибо все варианты с циклом в таком стиле и делают. Надо учить язык. Цитата(baralgin @ Apr 26 2010, 00:31)  Насчёт 0x01: не корректно. Потому что компилятор умудряется считать результат до исполнения  . Вообще-то причина не в этом, а том, что цикл будет прерван как только закончатся единичные биты в старшей части байта. Цитата оказывается что даже инструкции специальные для этого бывают  ). А когда не бывают, можно сопроцессор  поставить. Много лет назад, когда по ошибке разработчиков периферийного оборудования (несколько стативов) на CPU на шустром (аж целых 12MHz) 80286 сыпались 32 последовательных потока из развернутых байт, поставил в помощь к процессору 8bit регистр с выходами перекрестно запаралеленными на входы. Записал в него байт и считал развернутым.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 26 2010, 07:56
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Для AVR все равно быстрее так Код uint8_t rsb(uint8_t a) { a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1); a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2); return __swap_nibbles(a); } 15 тактов. Даже если на асм написать развернутый цикл со сдвигом через перенос получится 16 тактов. Код 5 a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1); \ 00000000 2F10 MOV R17,R16 \ 00000002 7515 ANDI R17,0x55 \ 00000004 0F11 LSL R17 \ 00000006 7A0A ANDI R16,0xAA \ 00000008 9506 LSR R16 \ 0000000A 2B01 OR R16,R17 6 a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2); 7 return __swap_nibbles(a); \ 0000000C 2F10 MOV R17,R16 \ 0000000E 7C1C ANDI R17,0xCC \ 00000010 9516 LSR R17 \ 00000012 9516 LSR R17 \ 00000014 7303 ANDI R16,0x33 \ 00000016 0F00 LSL R16 \ 00000018 0F00 LSL R16 \ 0000001A 2B01 OR R16,R17 \ 0000001C 9502 SWAP R16 \ 0000001E 9508 RET
|
|
|
|
|
Apr 26 2010, 17:12
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
Цитата Все плохо, Вы, как оказалось, не только написать не можете, но и прочитать уже написанное sad.gif. Ибо все варианты с циклом в таком стиле и делают. Надо учить язык. да я с этим полностью согласен, вроде принцип реализации правильно изложил, а на практике написать не могу, если бы на русском ткнули в учебник где можно было понять, как извлечь бит из байта, как установить 0 или 1 в нужном месте байта был бы признателен. Инфы много, но то что читаю либо не содержит такие вещи либо уже идет слишком сложно и не могу просто понять.
|
|
|
|
|
Apr 26 2010, 19:45
|
Частый гость
 
Группа: Участник
Сообщений: 149
Регистрация: 2-06-08
Из: Москва
Пользователь №: 38 003

|
Цитата(Vny4ek @ Apr 26 2010, 21:12)  Инфы много, но то что читаю либо не содержит такие вещи либо уже идет слишком сложно и не могу просто понять. Да фиг с ними с учебниками, Вы тему-то свою с начала до конца внимательно перечитайте. Как перечитаете выберите один из предложенных вариантов, перечитайте его еще раз, попытайтесь понять, затем задайте вопросы, если что-то останется непонятным.
Сообщение отредактировал smac - Apr 26 2010, 19:46
|
|
|
|
|
Apr 26 2010, 19:55
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Vny4ek вот как-то так: установить бит в байте Код b |= 1 << bit_number; сбросить бит в ноль Код b &= ~(1 << bit_number); bit_number, естественно от 0 до 7, 15 или 31 или даже 63 в зависимости от типа переменных  *Для типов подлиннее(длиннее int) придётся указать явное приведение к нужному типу, иначе то, что в скобках - будет приводиться к int(в общем случае).
--------------------
The truth is out there...
|
|
|
|
|
Apr 26 2010, 20:59
|

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

|
Цитата(KRS @ Apr 26 2010, 11:56)  Даже если на асм написать развернутый цикл со сдвигом через перенос получится 16 тактов. Можно и так, но не менее 16 тактов... Код BLD R16,0 BST R17,7
BLD R16,1 BST R17,6
BLD R16,2 BST R17,5
BLD R16,3 BST R17,4
BLD R16,4 BST R17,3
BLD R16,5 BST R17,2
BLD R16,6 BST R17,1
BLD R16,7 BST R17,0 А ещё кто-то предлагал соединить два 8-ми битных порта перемычками крест-накрест и инвертировать за 2-3 такта: Код out PORTB, R16 nop in R17,PORTD
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Apr 27 2010, 01:53
|
Профессионал
    
Группа: Участник
Сообщений: 1 273
Регистрация: 3-03-06
Пользователь №: 14 942

|
Цитата(KRS @ Apr 26 2010, 11:56)  Для AVR все равно быстрее так Код uint8_t rsb(uint8_t a) { a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1); a = ((a & 0xCC) >> 2) | ((a & 0x33) << 2); return __swap_nibbles(a); } 15 тактов. Даже если на асм написать развернутый цикл со сдвигом через перенос получится 16 тактов. Код ... С первой половиной согласен — 6 тактов, вторая половина могла бы уложиться в 5 без лишних сдвигов. Итого 11 тактов против 15. Код uint8_t rsb(uint8_t a) { a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1); return __swap_nibbles(a); a = ((a & 0x66) | (a & 0x99)); }
mov r17,r16 lsr r17 andi r17,0x55 lsr r16 andi r16,0xAA or r16,r17 mov r17,r16 swap r17 andi r17,0x66 andi r16,0x99 or r16,r17 (ret)
|
|
|
|
|
Apr 27 2010, 07:35
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Vny4ek @ Apr 27 2010, 07:02)  sigmaN, спасибо большое. То что написали после вас вообще не понятно мне т.к. я на Си учусь писать. И уже не первый год http://electronix.ru/forum/index.php?showt...=57082&st=0 все о битах спрашиваете. Ну очень "эффективно" идет процесс  . Может, наконец-то возьмете в руки букварь? А то просто ничего кроме сказанного здесь http://electronix.ru/forum/index.php?showt...=55513&st=0 SasaVitebsk по поводу очередного Вашего "вопроса": Цитата Блин. Во что лень делает.... сказать уже не могу  .
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 27 2010, 09:06
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(demiurg_spb @ Apr 27 2010, 00:59)  А ещё кто-то предлагал соединить два 8-ми битных порта перемычками крест-накрест и инвертировать за 2-3 такта: Код out PORTB, R16 nop in R17,PORTD Я вот не помню, AVR умеет свопить полубайты? Тогда можно одним портом обойтись с чуть большим количеством тактов
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Apr 27 2010, 20:58
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(x736C @ Apr 27 2010, 05:53)  С первой половиной согласен — 6 тактов, вторая половина могла бы уложиться в 5 без лишних сдвигов. Итого 11 тактов против 15. Код uint8_t rsb(uint8_t a) { a = ((a & 0x55) << 1) | ((a & 0xAA) >> 1); return __swap_nibbles(a); a = ((a & 0x66) | (a & 0x99)); }
mov r17,r16 lsr r17 andi r17,0x55 lsr r16 andi r16,0xAA or r16,r17 mov r17,r16 swap r17 andi r17,0x66 andi r16,0x99 or r16,r17 (ret) у Вас какая-то полная фигня в асм тексте(и в С тоже) после lsr r17 и lsr r16 и неиспользования в дальнейшем флага С Вы младший бит ужо потеряли короче, меньше 13 тактов и не надейтесь получить  эта я Вам как "крупный специалист по перекладыванию битиков" гарантирую...
|
|
|
|
|
Apr 28 2010, 00:36
|
Профессионал
    
Группа: Участник
Сообщений: 1 273
Регистрация: 3-03-06
Пользователь №: 14 942

|
Цитата(singlskv @ Apr 28 2010, 00:58)  у Вас какая-то полная фигня в асм тексте(и в С тоже) после lsr r17 и lsr r16 и неиспользования в дальнейшем флага С Вы младший бит ужо потеряли короче, меньше 13 тактов и не надейтесь получить  эта я Вам как "крупный специалист по перекладыванию битиков" гарантирую...  Вы правы, действительно ошибся. lsl надо заменить на rol, lsr на ror. 11 тактов и получится. Перепроверьте. Соответственно код на Си тоже надо подправить. Поправленный код Код mov r17,r16 rol r17 andi r17,0x55 ror r16 andi r16,0xAA or r16,r17 mov r17,r16 swap r17 andi r17,0x66 andi r16,0x99 or r16,r17
|
|
|
|
|
Apr 28 2010, 02:55
|

I WANT TO BELIEVE
     
Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751

|
Цитата А во вторых человек настолько хреново разбирается в том, что вы ему пытаетесь объяснить, что помоему тут разговор не об экономии 256 байтах RAM'a Вот приучится в тупую делать простые вещи и так и будет по табличке всю жизнь. Не на столько сложная задача. Понятно, что оптимизация просто ради оптимизации - никому не нужна. Но тут другой разговор идет. AVR - это всё таки не PC и разбрасываться ресурсами(а в конечном итоге и деньгами) ИМХО не стОит. И что плохого, если люди вступили в дискуссию и пытаются создать максимально оптимальный код под задачу? Лично я ничего плохого не вижу в этом. Вон с 13 тактов уже на 11 переползли. Может быть некоторые бы и до конца жизни не знали, что это возможно ))))))) И флаг Вам в руки, когда вы с такой привычкой реализуете что-нибудь на меге 128, а другой разработчик сделает тоже самое на тиньке какой-нибудь вшивой
--------------------
The truth is out there...
|
|
|
|
|
Apr 28 2010, 08:03
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(x736C @ Apr 28 2010, 04:36)  Перепроверьте. Нет, все равно ошибка. Смотрите: Код mov r17,r16; r16 = abcdefgh r17=abcdefgh C=x rol r17; r17=bcdefghx C=a andi r17,0x55; r17=0c0e0g0x ror r16; r16=aabcdefg C=h andi r16,0xAA; r16=a0b0d0f0 or r16,r17; r16=acbedgfx mov r17,r16; r17=acbedgfx swap r17; r17=dgfxacbe andi r17,0x66; r17=0gf00cb0 andi r16,0x99; r16=a00ed00x or r16,r17; r16=agfedcbx получили agfedcbx а нужно hgfedcba
|
|
|
|
|
Apr 28 2010, 13:56
|

Знающий
   
Группа: Свой
Сообщений: 568
Регистрация: 8-07-07
Из: Занзибар
Пользователь №: 28 964

|
Такое впечатление, что все ваши начальники понимают, о чем здесь речь и оценивают вашу работу по количеству использованной памяти в мк, а не по результату (работает / не работает). Тоже самое относится ко времени, которое дается на разработку... Я например не могу объяснить своему начальнику, что такого прекрасного в экономии 256 бит памяти на начальном этапе разработке. А уж тем более почему я потратил на это половину своего рабочего дня.  Цитата(sigmaN @ Apr 28 2010, 06:55)  Вот приучится в тупую делать простые вещи и так и будет по табличке всю жизнь. А Вы думаете, что большинство делает иначе? Цитата(sigmaN @ Apr 28 2010, 06:55)  Понятно, что оптимизация просто ради оптимизации - никому не нужна. Но тут другой разговор идет. AVR - это всё таки не PC и разбрасываться ресурсами(а в конечном итоге и деньгами) ИМХО не стОит. И что плохого, если люди вступили в дискуссию и пытаются создать максимально оптимальный код под задачу? Лично я ничего плохого не вижу в этом. Вон с 13 тактов уже на 11 переползли. Может быть некоторые бы и до конца жизни не знали, что это возможно ))))))) И флаг Вам в руки, когда вы с такой привычкой реализуете что-нибудь на меге 128, а другой разработчик сделает тоже самое на тиньке какой-нибудь вшивой  Ничего плохого в этом нет. Просто я бы это все в отдельную тему выделил. Новичек в этой куче сообщений не найдет простого решения (которое будет работать с любым мк). Сколько времени у Вас уйдет, чтобы переписать этот код на ассемблере для другого Вам неизвестного ранее мк? А при этом Вы профессионал своего дела, а новичек скорее пойдет в соседний форум и найдет там как раз самое просто решение и использует его.
--------------------
"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино". А. и Б. Стругацкие
|
|
|
|
|
Apr 28 2010, 14:11
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(sergeeff Jr. @ Apr 28 2010, 15:56)  Я например не могу объяснить своему начальнику, что такого прекрасного в экономии 256 бит памяти 256 Байт. Цитата А уж тем более почему я потратил на это половину своего рабочего дня.  А этот уже страшно  . На эту задачу на 'C' надо тратить 10 минут, даже если ночью разбудить. Набивать таблицу на 256 байт дольше и ошибиться легче. При этом на 'C', если чуть чуть думать, это будет достаточно портируемый вариант. Цитата Сколько времени у Вас уйдет, чтобы переписать этот код на ассемблере для другого Вам неизвестного ранее мк? Спокойнее, как выяснилось, писать на ассемблере практически бесполезно.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Apr 28 2010, 15:21
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 15-07-04
Из: g.Penza
Пользователь №: 326

|
sergeeff JrТут речь не оптимизации ради оптимизации. Проинвертировать биты в байте таблицей не факт, что проще. Причин несколько: - размер кода; - время на кодирование (или тупое набивание таблицы); - количество вызовов функции в общем времени работы программы. Предложенный алгоритм с xor работает быстро. Более того, в некоторых случаях он вообще будет работать быстрее, чем таблица (если таблицу хранить во внешней медленной памяти). Отлаженный и качественный алгоритм с одного МК на другой на ассемблере (свежий пример - с 8051 на ARM9) переноситься за 1 день. И даёт выигрыш в производительности 3-8 раз по сравнению с кодом, написанным на C. Для устройств, где важен каждый милливатт, это зачастую важно. Если Ваше устройство работает от аккумулятора 10 дней (с "вылизанным" ПО на ассемблере), а у конкурентов только 2 дня (на "copypaste'ном" С), то тендер Вы, очень вероятно, проиграете. Зато потом будет масса времени объяснить своему начальнику, что такого прекрасного в экономии.
|
|
|
|
|
Apr 28 2010, 16:49
|

Знающий
   
Группа: Свой
Сообщений: 568
Регистрация: 8-07-07
Из: Занзибар
Пользователь №: 28 964

|
Байт конечно, очепятался я. Я не говорил, что я не буду искать более красивого решения (что проигнорирую вариант с XOR), но сделаю я это может через месяц, может через два. Потому что как раз каждый милливатт нужен.  А тот, кто создал эту тему вообще скорее всего вникать не будет. А урезателям бонусов еще раз скажу: когда вас поставят в положение - сделай плату, сделай прошивку, подготовь макет с прогой на компе, летим за тридевять земель к клиенту через неделю, тогда я посмотрю что вы будет в коде вылизывать, а главное когда.  А "тупое набивание таблицы" кто-то сделал до меня.
--------------------
"Познание бесконечности требует бесконечного времени, а потому работай не работай - все едино". А. и Б. Стругацкие
|
|
|
|
|
Apr 28 2010, 17:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Если обратите внимание, в последних книгах по программированию, серьезные авторы предупреждают о вреде преждевременной оптимизации. Сначала получи работоспособную программу (устройство), а затем, при необходимости, займись оптимизацией узких мест. Очевидно, что у каждого программиста со стажем накоплено оптимизированных функций и модулей на 95 % случаев. Автор топика, судя по задаваемому вопросу, программист молодой. Если он над каждым простым вопросом будет сидеть по две недели, конечное устройство не будет разработано в обозримом будущем никогда.
|
|
|
|
|
Apr 28 2010, 18:05
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(sergeeff Jr. @ Apr 28 2010, 20:49)  А урезателям бонусов еще раз скажу: когда вас поставят в положение - сделай плату, сделай прошивку, подготовь макет с прогой на компе, летим за тридевять земель к клиенту через неделю, тогда я посмотрю что вы будет в коде вылизывать, а главное когда.  Думаете, "урезатели бонусов" не умеют работать быстро и качественно?  Цитата(sergeeff @ Apr 28 2010, 21:35)  Если обратите внимание, в последних книгах по программированию, серьезные авторы предупреждают о вреде преждевременной оптимизации. Сначала получи работоспособную программу (устройство), а затем, при необходимости, займись оптимизацией узких мест. Да, а применение таблицы "из интернета" - это как раз отличный пример преждевременной оптимизации. С соответствующими побочными эффектами
|
|
|
|
|
Apr 28 2010, 22:11
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(sergeeff Jr. @ Apr 28 2010, 20:49)  А урезателям бонусов еще раз скажу: когда вас поставят в положение - сделай плату, сделай прошивку, подготовь макет с прогой на компе, летим за тридевять земель к клиенту через неделю, тогда я посмотрю что вы будет в коде вылизывать, а главное когда.  Ага и работать не будет - потому что в таблице была ошибка  Посмотрите например, исходники CRC, там обычно таблицы генерируются на лету, а потом используются. Если надо разместить во флеше - все равно нужна прграмма которая эту таблицу сгенерирует. А для такой простой операции как обмен бит - таблица это черезмерная оптимизация. К тому же, если так обмен происходит за 15 тактов - то по таблице будет за 6 тактов ( mov ZL, r16 mov ZH, 0 subi ZL, LOW(-PTR) sbci ZH, HIGH(-PTR) LD R16, Z)
|
|
|
|
|
Apr 30 2010, 06:27
|
Частый гость
 
Группа: Участник
Сообщений: 145
Регистрация: 11-01-08
Пользователь №: 34 001

|
Всем большое спасибо за помощь. Сам понимаю что тупо не хватает знаний языка. Сейчас стараюсь это устранить. to zltigo, я разве сказал что в программировании гуру, просто раздел называется для новичков, а то что появляется желание что либо сделать не коммерческое на МК делаю, появляются моменты где не могу разобраться спрашиваю тут. С той поры когда я задавал вопросы по приведенным ссылкам, я (на мой взгляд) подвинулся вперед. Тогда вообще мало понимал. То что интервалы большие между вопросами, так у каждого есть работа, семья, проблемы, дела. Еще раз повторю что я не сидел все это время за МК к сожалению, просто бывает время выпадает и хочется что нибудь свое попробовать сделать. Как то так.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|