|
Никак не обмануть gcc 4.1.2 |
|
|
|
Aug 15 2008, 11:45
|

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

|
Пытаюсь оптимизировать процедуру очистки дисплея, но gcc не поддаётся дрессуре  Оптимизация: Os. Код #define LCD_WIDTH 128U #define LCD_HEIGHT 64U #define LCD_STR_HEIGHT 8U
unsigned char lcd_vram[LCD_WIDTH][LCD_HEIGHT/LCD_STR_HEIGHT]; // Буфер видеопамяти LCD.
//==================================== void lcd_clrscr(void) { unsigned char*p = &lcd_vram[0][0];
#if (((LCD_WIDTH*LCD_HEIGHT/LCD_STR_HEIGHT)/8)>255) # error "(sizeof(lcd_vram)/8)>255 !!!" #endif
register unsigned char i = sizeof(lcd_vram)/8; do { *p++ = 0; // 1 *p++ = 0; // 2 *p++ = 0; // 3 *p++ = 0; // 4 *p++ = 0; // 5 *p++ = 0; // 6 *p++ = 0; // 7 *p++ = 0; // 8 } while (--i); } Получаю листинг такого вида: Код lcd_clrscr: ldi r30,lo8(lcd_vram) ldi r31,hi8(lcd_vram) .L2: st Z,__zero_reg__ std Z+1,__zero_reg__ std Z+2,__zero_reg__ std Z+3,__zero_reg__ std Z+4,__zero_reg__ std Z+5,__zero_reg__ std Z+6,__zero_reg__ std Z+7,__zero_reg__ adiw r30,8 ldi r24,hi8(lcd_vram+1024) cpi r30,lo8(lcd_vram+1024) cpc r31,r24 brne .L2 ret Мне никак не удаётся заставить gcc использовать однобайтный счётчик цикла, отказаться от adiw и использовать st+,__zero_reg__. Так код стал бы и короче и быстрее... И попутно вопрос №2: Я считал, что static const является альтернативой define. Но, видимо, я заблуждался... Код static const unsigned char MY_ARRAY_SIZE = 2; //#define MY_ARRAY_SIZE 2
unsigned char my_array[MY_ARRAY_SIZE] = {0,0}; получаю сообщение: ../../../arclib/common/lcd128x64.c:10: error: variably modified 'my_array' at file scope ../../../arclib/common/lcd128x64.c:10: warning: excess elements in array initializer ../../../arclib/common/lcd128x64.c:10: warning: (near initialization for 'my_array') А если через #define MY_ARRAY_SIZE 2 - то всё ок. Знающие люди, объясните такое поведение. Спасибо!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
 |
Ответов
(1 - 14)
|
Aug 15 2008, 13:46
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(demiurg_spb @ Aug 15 2008, 17:45)  Пытаюсь оптимизировать процедуру очистки дисплея, но gcc не поддаётся дрессуре  Ну значит не умеет  Если так нужны эти такты, то проще не дрессировать гцц, а использовать инлайн - ассемблер: Код void lcd_clrscr(void) { unsigned char *p = &lcd_vram[0][0]; unsigned char i = 128; __asm__ __volatile__ ( "L_%=: " "st %a0+, __zero_reg__\n\t" "st %a0+, __zero_reg__\n\t" "st %a0+, __zero_reg__\n\t" "st %a0+, __zero_reg__\n\t" "st %a0+, __zero_reg__\n\t" "st %a0+, __zero_reg__\n\t" "st %a0+, __zero_reg__\n\t" "st %a0+, __zero_reg__\n\t" "subi %1, 1\n\t" "brne L_%= \n\t" : : "z" (p), "r" (i) ); } Как-то так.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Aug 15 2008, 15:10
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(demiurg_spb @ Aug 15 2008, 17:45)  И попутно вопрос №2: Я считал, что static const является альтернативой define. Но, видимо, я заблуждался... Конечно заблуждаетесь! #define это команда препроцессора, а не компилятора. По ней он всего лишь делает тупую подстановку и никаких проверок (соответствия типа, например) не происходит. static const на разных архитектурах может интерпретироватся по-разному. Где-то под переменную будет выделена отдельная ячейка в ОЗУ, где-то константа будет размещена во Flash. Но в любом случае static определяет класс переменных, констант и функций, "область видимости" которых ограничена текущим модулем или функцией. const указывает на то, что переменная в текущем модуле или функции явным образом не модифицируется. Значение переменной типа const (если она в ОЗУ была расположена) можно изменять либо явным приведением типа, либо неявно, через указатель. В вашем примере случай Код #define MY_ARRAY_SIZE 2 unsigned char my_array[MY_ARRAY_SIZE] = {0,0}; преобразуется препроцессором в Код unsigned char my_array[2] = {0,0}; А тот который дает ошибку Код static const unsigned char MY_ARRAY_SIZE = 2; unsigned char my_array[MY_ARRAY_SIZE] = {0,0}; означает попытку объявить переменную my_array типа unsigned char и одновременно присвоить одной переменной со смещением равным значению MY_ARRAY_SIZE сразу два значения. Естественно, что компилятор обалдевает от такой наглости и выдает вам ошибку.
|
|
|
|
|
Aug 15 2008, 16:22
|

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

|
Цитата(_Pasha @ Aug 15 2008, 20:06)  У Вас sizeof(lcd_vram) 16-битное. Избавьтесь от 16-ти битного представления - вот и вся дрессура  Только мне кажется, это компилер Вас дрессирует  Пытаеццо. Если я пишу Код unsigned char i=sizeof(lcd_vram)/8; то разрядность sizeof(lcd_vram) не имеет никакого значения, т.к. переменная i явно объявлена как байт. Спасибо за разъяснения про static const. На асме вставки делать не буду из религиозных соображений. Хочется чтоб gcc становился ещё умнее...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Aug 15 2008, 17:57
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(_Pasha @ Aug 15 2008, 23:27)  все попытки ввести "дрессурой" перем. цикла в явном виде, порождают менее эффективный код. А из моего асмового варианта получилось: Код 278c: 80 e8 ldi r24, 0x80; 128 278e: e7 e6 ldi r30, 0x67; 103 2790: f0 e0 ldi r31, 0x00; 0
00002792 <L_22>: 2792: 11 92 st Z+, r1 2794: 11 92 st Z+, r1 2796: 11 92 st Z+, r1 2798: 11 92 st Z+, r1 279a: 11 92 st Z+, r1 279c: 11 92 st Z+, r1 279e: 11 92 st Z+, r1 27a0: 11 92 st Z+, r1 27a2: 81 50 subi r24, 0x01; 1 27a4: b1 f7 brne .-20 ; 0x2792 <L_22> Это менее эффективно?
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Aug 15 2008, 19:39
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(AHTOXA @ Aug 15 2008, 21:57)  Это менее эффективно? А Вы посчитайте - если не ошибаюсь, Вы выиграли 2 такта и/или 3 слова программ.  Зачем полировать то, что может быть гораздо шершавее ? Другой вопрос, что на сях корявенько - через switch(lcd_state){...} состояния делаются, на асме через упрощенную кооперативную многопоточность куда проще и даже читабельнее, но это оффтоп.
|
|
|
|
|
Aug 16 2008, 06:39
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(_Pasha @ Aug 16 2008, 01:39)  А Вы посчитайте - если не ошибаюсь, Вы выиграли 2 такта и/или 3 слова программ.  Мелочь, но приятно:-) И потом, это же в цикле, выигрыш в тактах надо умножить на 128 :-) Цитата Зачем полировать то, что может быть гораздо шершавее ? Тут я полностью с вами согласен, я этим обычно не занимаюсь. Просто подумал, раз автор темы спрашивает, то может ему это действительно важно? (Оказалось - нет, ему религия важнее  ) Цитата Другой вопрос, что на сях корявенько - через switch(lcd_state){...} состояния делаются, на асме через упрощенную кооперативную многопоточность куда проще и даже читабельнее, но это оффтоп. Не, никакая красота не вернёт меня в лоно ассемблера:-)
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Aug 17 2008, 14:56
|

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

|
Цитата(_Pasha @ Aug 15 2008, 23:39)  А Вы посчитайте - если не ошибаюсь, Вы выиграли 2 такта и/или 3 слова программ.  Выигрыш 3 такта и 3 слова, т.к. adiw выполняется за 2 такта. Итог для этого случая 128*3=384 такта, а если циклов 256, то 768 тактов.... Цитата(_Pasha @ Aug 15 2008, 23:39)  Зачем полировать то, что может быть гораздо шершавее ? А действительно, зачем вообще что-либо делать? Ведь можно продолжать смотреть диафильмы на проекторе с ручным приводом, а DVD и HDTV - это не для нас, потому что мы не в состоянии поднять FPS...  Когда компилятор считает себя умнее программиста - это немного раздражает...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Aug 17 2008, 22:45
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(demiurg_spb @ Aug 17 2008, 18:56)  Выигрыш 3 такта и 3 слова, т.к. adiw выполняется за 2 такта. Итог для этого случая 128*3=384 такта, Допустим что фрейм буфер очищается 25 раз в секунду, это значит что выигрыш 25 * 384 = 9600 тактов в секунду, или примерно 0.1% при тактовой частоте 10МГц. Цитата а если циклов 256, то 768 тактов.... 0.2% Цитата А действительно, зачем вообще что-либо делать? Ведь можно продолжать смотреть диафильмы на проекторе с ручным приводом, Код генерируемый GCC 15 инструкций, Ваш 13 - выигрыш по размеру примерно 20%. Цикл генерируемый GCC выполняется за 23 такта, Ваш за 20, выигрыш 15%. Конечно компилятор сработал не идеально, но по диафильмы - это уже литературное преувеличение. Как часто Вам надо очищать буфер в этой программе? Анатолий.
Сообщение отредактировал aesok - Aug 17 2008, 23:40
|
|
|
|
|
Aug 17 2008, 22:53
|

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

|
Цитата(aesok @ Aug 18 2008, 00:45)  Как часто Вам надо очищать буфер в этой программе? Самое смешное, что буфер обычно очищать не нужно, нужно очищать хвосты оставшиеся от старой информации. Очитить все и занести заново это лобовой алгоритм, который не то, что не нужно вылизывать, но и использовать не следует.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Aug 18 2008, 06:59
|

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

|
Цитата(aesok @ Aug 18 2008, 02:45)  Конечно компилятор сработал не идеально, но про диафильмы - это уже литературное преувеличение. Ну куда же без этого  Но сути не меняет. Цитата(aesok @ Aug 18 2008, 02:45)  Как часто Вам надо очищать буфер в этой программе? Всегда 2 раза в секунду, иногда до 10 раз в секунду + на каждое действие пользователя. Этот же алгоритм выводит подготовленную страницу из SRAM в ОЗУ контроллера дисплея... Да и вообще циклов в программе просто немеряно... Но что это меняет? Я просто обратил внимание на узкое место в циклах и на мой взгляд на это стоит обратить внимание уважаемым разработчикам ГЦЦ и ничего более... Я сам иногда имею сильное желание приобщится к этому процессу, но в силу разных причин не получается... Цитата(zltigo @ Aug 18 2008, 02:53)  Самое смешное, что буфер обычно очищать не нужно, нужно очищать хвосты оставшиеся от старой информации. Очитить все и занести заново это лобовой алгоритм, который не то, что не нужно вылизывать, но и использовать не следует. В моём случае именно этот алгоритм меня полностью удовлетворяет.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|