Page 1 of 8

Эффективное программирование в KOLIBRI OS

Posted: Mon Apr 10, 2006 6:31 am
by <Lrz>
Я попоробовал напистасть небольшую статью на данную тему. Надеюсь что с вашей помощью я ее улучшу, и напишу остальные.
Тама очень актуальна и злободневна т.к. часто можно встретить ошибки в логике программы. Данный пример иллюстирует возможность постороения рамок методом прямоугольников, с последующим их корректным отображением на канве окна программы при перекрытии.
В архиве присутствует документация в виде HTML + бинарник + исходник. http://www.test-kolibri.narod.ru/d/less1.7z

Попрошу все ваши замечания и предложения высказать, т.к. это необходимо для развития меня в данном направлении. Если у вас получиться оптимизировать, улушчить или сократить код, пожалуйста поделитесь со мной, я внесу необходимые изменения.

Выскажу предположение, что может быть в будующем это возможно станет темой рассылки.

Posted: Mon Apr 10, 2006 11:15 am
by Serge
Маленькое замечание
mov eax,8
...
...
...
;mov eax,4
shr eax,1 ;то же но сдвиги быстрее т.е. получается 8 разделить на 2
Это не факт. На всех суперскалярных процессорах (Р2 - Р4, Атлоны) mov eax,4 будет выполнено раньше чем shr eax,1 потому, что нет ложных взаимозависимостей по регистру еах. И загрузка непосредственного значения в регистр выполняется быстрее ( с опережениеми и параллельно), чем операция с регистром.

Р4 (Вилламет и Нортвуд)выполняют простые арифметический операции быстрее чем сдвиги
add reg, reg
add reg, reg ; умножение на 4

быстрее чем
shl reg, 2

простое сложение
add reg, 1
sub reg, 1

быстрее чем
inc reg
dec reg

в Прескоттах ситуацию с inc reg и dec reg поправили.

Posted: Mon Apr 10, 2006 12:14 pm
by <Lrz>
Что ж... чень интересно получаеется ... http://www.wasm.ru/article.php?article=1010001, я частично руководствовался данной статьёй. Инструкция типа
mov reg, 0x0 ;5 байт занимает
sub reg,0x1 ;2 байта
inc reg ;занимает 1 байт
...
В общем то получается что можно почти любой код переработать под конкретную архитектуру дабы получить наибольшее быстродейстивие. В целом же хочется получить маленький и быстрый код. И опять же мы говорим о байтах выйгрыша или пройгрыша - в данной задаче это не актуально т.к. это не критичный участок кода.
Serge, если у тебя есть желание то можешь переписать код, с учетом вышесказанного. Я думаю это поможет не одному начинающиму прогаммисту. Я в коментариях подправлю что быстрее на 80х386 процессорах. Если ты перепишешь мою программу я обязательно включу ее как оптимизированный вариант для суперскалярных процессоров.

Posted: Mon Apr 10, 2006 5:15 pm
by Serge
Я не думаю что так уж необходимо переписывать код. Просто со времен 8086 многое изменилось и самый маленький код не всегда самый быстрый, скорее наоборот. Я решил подготовить полезные советы для оптимизаторов и скоро пришлю их.

Главная цель оптимизации - экономить время людей, а не машин.

Posted: Mon Apr 10, 2006 8:29 pm
by <Lrz>
Serge - давай проверим на реальных процессорах ? У меня есть программа для тестирования скорости выполнения кода
http://test-kolibri.narod.ru/test_cod/test.7z. Я завтра проверю, что быстрее inc,dec или же add, sub и shl, shr.
У меня есть под рукой Celeron 600 МГц/128 ОЗУ и IBM Think Pad 380 XD - PII/233МГц/64 ОЗУ. Со своей стороны ты тоже проверь, если есть желание.
Могу попробовать найти у себя Р1- 133 МГц. Но я думаю что через год - два данные процессоры вообще исчезнут, в принципе стоит ориентироваться на машины класса PIII - PIV и выше.

Posted: Mon Apr 10, 2006 8:44 pm
by Mario79
<Lrz>
Ты, конечно, взялся за хорошее дело, такие статьи, несомненно, нужны. Но стоит хотя бы натравить ворд или другую прогу для проверки орфографии. Я понимаю каждый из нас человек, и допускает ошибки, но все же проверять орфографию необходимо, иначе у читателя сразу возникает вопрос "А че этот неграмотный других учит?".
Я надеюсь, не обидел тебя своим замечанием, но нужно поправить текст.
В частности я заметил:
1)ЭФФЕКТИНОЕ ПРОГРАМИМИРОВАНИЕ В KOLIBRI OS - 2 слова в заголовке написаны неправильно, нужно - эффективное программирование
2)Написать сборник статей на тему Эффективное прогаммирование в КОЛИБРИ - опять несчастное программирование
3)рассмотреных - нужно рассмотренных
4)без условно - нужно писать вместе
5)не верны - нужно писать вместе, это прилагательное
Про знаки препинания я ничего не скажу, так как сам с ними плохо разбираюсь. Вот так вот в принципе татарин научил тебя русскому языку. :-)
Можешь возмущаться на мое маленькое замечание, я не буду в обиде.
Удачи.

Posted: Mon Apr 10, 2006 9:12 pm
by Mario79
<Lrz>
У меня есть Cyrix233MX, так что если надо могу подсобить в тестировании.

Posted: Mon Apr 10, 2006 9:25 pm
by Serge
По поводу скорости исполнения inc и dec я ошибся, но у них есть свои заморочки на P4. В остальном все правильно

Разницу в быстродействии можно будет заметить только на очень большом числе команд.
Надо хорошо продумать порядок тестирования.

Mario79
Я отправил тебе письмо с правилами оптимизаторов. Если можешь - размести.

Posted: Mon Apr 10, 2006 9:48 pm
by <Lrz>
Mario79 - спасибо что указал на ошибки. Я загрузил в ворд и исправил остальные недочеты. Просто мне нужно более внимательнее читать то что я написал :). А ошибки не делает только тот кто ничего не делает :) . И вовсе я на тебя не обижась - есть косяк - ошибка. Значит нужно исправлять. Как можно увидить документация еще не дописана, описан просто метод. В ближайшее время постораюсь доделать.
Мне вот интересно все ли я в коде правильно сделал ? Может у кого есть замечания по логике программы?

Posted: Tue Apr 11, 2006 2:07 pm
by <Lrz>
Протестировал на машине Celeron 600 команда add ecx,1 оказалась быстрее inc ecx.

Posted: Tue Apr 11, 2006 3:58 pm
by Serge
А исходный код теста можно посмотреть? И сколько было прогонов ?

Posted: Tue Apr 11, 2006 7:43 pm
by <Lrz>
Тестирование производилось с помощью программы Func testing v0.91_betta.
Инструкции загонялись в цикл 2^32-1 с выводом результата и подсчетом среднего значения(красное ниженее значение).
1) произвел прогон пустого цикла т.е. только пустой цикл.
2) составил пары для тестирования т.е. inc + add; dec + sub; mov reg,reg + shl reg,1 + пустые циклы
3) произвел прогон цикла с 10 однотипными инструкциями для каждого варианта.
4) произвел запись и вычисления "времени" выполнения кода.
Программа считает тики системного процессора - оценить время на очень коротких промежутках не представляется возможным.

Скачать программы + исходник программы для тестирования кода т.е. уже собранные варианты прогаммы со встроенным участком кода для тестирования. http://www.test-kolibri.narod.ru/d/testing.7z
Пример кода цикла

Code: Select all

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
testing:	   ;собственно сюда можно вставить кусок своего кода 
	 xor eax,eax
loop_s:  xor ecx,ecx
	 dec ecx
	 shl ecx,1
	 shl ecx,1
	 shl ecx,1
	 shl ecx,1
	 shl ecx,1
	 shl ecx,1
	 shl ecx,1
	 shl ecx,1
	 shl ecx,1
	 shl ecx,1
	 
	inc eax
	cmp eax,0xfffffff
	 jb loop_s	        

testsize=$-testing ;размер кода 
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
testing:	   ;собственно сюда можно вставить кусок своего кода 
	 xor eax,eax
loop_s:  xor ecx,ecx
;	 dec ecx
	 add ecx,1
	 add ecx,1
	 add ecx,1
	 add ecx,1
	 add ecx,1
	 add ecx,1
	 add ecx,1
	 add ecx,1
	 add ecx,1
	 add ecx,1
	 
	inc eax
	cmp eax,0xfffffff
	 jb loop_s	        

testsize=$-testing ;размер кода 
Результаты приведу завтра

Posted: Wed Apr 12, 2006 6:44 am
by <Lrz>
Приведу результаты которые у меня получились: Машина Celeron 600/128МБ ОЗУ
Пустой цикл для add, sub, inc, dec - 808358560
код получился

Code: Select all

testing:      ;собственно сюда можно вставить кусок своего кода 
    xor eax,eax 
loop_s:  xor ecx,ecx 
   inc eax 
   cmp eax,0xfffffff 
    jb loop_s           
testsize=$-testing ;размер кода 
Пустой цикл для shr, shl - 808366510

Code: Select all

testing:      ;собственно сюда можно вставить кусок своего кода 
    xor eax,eax 
loop_s:  xor ecx,ecx 
    inc ecx
    inc eax 
   cmp eax,0xfffffff 
    jb loop_s           
testsize=$-testing ;размер кода 
ADD ecx,1 - 3138366050
INC ecx - 3138333120
++++++++++++++++ Примерно разницы никакой т.к. разброс результата состовляет около 10 % и варируется от эксперимента к эксперимента
SUB ecx,1 - 3138286591
DEC ecx - 3138327211
++++++++++++++++ Аналогично можно сделать вывод что команды равноценны и выйгрыш явно не будет получен от применения той или иной команды
ADD ecx,ecx 3463860130
SHR ecx,1 - 3286396591
SHL ecx,1 - 3362494447
+++++++++++++++++ А все таки сдвиги лучше
>>>>>>>>
Обновил архивы на сайте т.к. ранее не включил в архив 2 файла *.inc
ссылки на архивы прежние

Posted: Wed Apr 12, 2006 9:53 am
by Serge
Лучше немного изменить код

Code: Select all

testing:      ;собственно сюда можно вставить кусок своего кода
    xor eax,eax
loop_s:  xor ecx,ecx   ; зачем обнулять есх в цикле,
    inc ecx                 ; а потом увеличивать
    inc eax
   cmp eax,0xfffffff     ; занимает много времени 
    jb loop_s           
вариант add reg, 1 / inc reg

Code: Select all

     xor eax, eax
.l: 
     add eax, 1    ; или inc eax     
     add eax, 1     
; чем больше здесь будет проверяемых команд
; тем меньше будет влияние от команды условного перехода
; число команд должно быть степенью двойки - 16, 32
; а лучше 64
     add eax, 1     
     add eax, 1     
     jnz .l     ; если число команд не степень двойки то код не сработает
вариант shl reg, 1 / add reg, reg

Code: Select all

    xor ecx, ecx 
    xor eax, eax
    add eax, 1

.l: 
     shl eax, 1
     shl eax, 1
; используем 31 команду shl eax, 1
; им должны соответствовать
; 31 пара команд  
;   add eax, eax
;   add eax, eax
   
     add ecx, 1  ; или sub ecx, 1
     jnz .l          ; лучше использовать команды add и sub
                     ;так как они изменяют все арифметические флажки 

Posted: Wed Apr 12, 2006 2:01 pm
by <Lrz>
Протестил на машине CELERON 633 /64 ОЗУ с изменениями в коде тестирования ADD eax,1 - 18927539
inc eax 18993466 - ADD быстрее