Thread View: pl.comp.lang.asm
13 messages
13 total messages
Started by tosamo
Wed, 17 May 2006 12:42
optymalizacja
Author: tosamo
Date: Wed, 17 May 2006 12:42
Date: Wed, 17 May 2006 12:42
118 lines
3618 bytes
3618 bytes
Witam
Pisze sobie porgramik w masm32 (wersja 6.11 chyba). Do tej pory pisalem
glownie w c i pascalu wiec na poczatku
program w asm wygladal jak dokladna kalka z jezykow wyzszego rzedu i dzialal
jakies 3 razy wolniej niz
pascal i delphi. Potem zaczalem optymalizowac i wyszlo na to, ze kazda
optymalizacja zwalnia dzialanie programu
o kilka(dziesiat) %.
Na przyklad:
Czemu takie cos :
mov edi,offset TABLICA
mov ecx,16
sha1_processmessageblock4:
mov eax,dword ptr [edi-12]
xor eax,dword ptr [edi-32]
xor eax,dword ptr [edi-56]
xor eax,dword ptr [edi-64]
rol eax,1
stosd
;
inc ecx
cmp ecx,80
jne sha1_processmessageblock4
Jest kilkukrotnie wolniejsze niz :
mov edi,offset TABLICA
mov ecx,16
sha1_processmessageblock4:
mov eax,ecx
shl eax,2
sub eax,12 ; 3 * 4
mov ebx,dword ptr [edi+eax]
sub eax,20 ; 5 * 4
xor ebx,dword ptr [edi+eax]
sub eax,24 ; 6 * 4
xor ebx,dword ptr [edi+eax]
sub eax,8 ; 2 * 4
xor ebx,dword ptr [edi+eax]
rol ebx,1
mov eax,ecx
shl eax,2
mov dword ptr [edi+eax],ebx
;
inc ecx
cmp ecx,80
jne sha1_processmessageblock4
Albo czemu takie cos :
mov esi,offset Buffers_ ; D
mov edi,offset Buffers__ ; E
std
movsd
movsd
ror DWORD PTR [esi],2
movsd
movsd
mov DWORD PTR [edi],eax
cld
Jest duzo wolniejsze niz :
mov ebx,DWORD PTR [Buffers+12] ; E = D
mov DWORD PTR [Buffers+16],ebx
;;
mov ebx,DWORD PTR [Buffers+8] ; D = C
mov DWORD PTR [Buffers+12],ebx
;
mov ebx,DWORD PTR [Buffers+4] ; C = SHA1CircularShift(30,B)
ror ebx,2
mov DWORD PTR [Buffers+8],ebx
;
mov ebx,DWORD PTR [Buffers] ; B = A
mov DWORD PTR [Buffers+4],ebx
;
mov ebx,eax
mov DWORD PTR [Buffers],eax ; A = temp
Albo na przyklad mam cos takiego :
mov al,byte ptr [esi+ecx]
mov byte ptr [edi+ebx],al
inc ecx
inc ebx
inc [Message_Block_Index] << TO JEST WAZNE
;
add [Length_Low],8
jnz sha1_input8 ;
inc [Length_High] ;
jnz sha1_input8
mov [Corrupted],1
Zmienna Message_Block_Index to zwykla zmienna DD w sekcji .data. Nie jest do
niczego juz potrzebna bo zamiast niej
zapisuje dane w rejestrach. Usuwam ta linie i program zwalnia o 5% !
Oczywiscie dziala bez zmiena tylko wolniej.
Oprocz tego na przyklad wielokrotne
mov eax,edx
shl eax,2
mov eax,DWORD PTR [Word_+eax] ;
Dziala oczywiscie duzo szybciej niz proste
mov esi,offset Word_
i potem juz tylko kilkadziesiat razy
lodsd
Czy ktos mi to wyjasni albo chociaz powie gdzie mozna jakies konkrety na ten
temat przeczytac ?
Re: optymalizacja
Author: Bogdan (bogdro)
Date: Wed, 17 May 2006 15:33
Date: Wed, 17 May 2006 15:33
158 lines
5625 bytes
5625 bytes
tosamo napisał(a): > Witam > > Pisze sobie porgramik w masm32 (wersja 6.11 chyba). Do tej pory pisalem > glownie w c i pascalu wiec na poczatku > program w asm wygladal jak dokladna kalka z jezykow wyzszego rzedu i dzialal > jakies 3 razy wolniej niz > pascal i delphi. Potem zaczalem optymalizowac i wyszlo na to, ze kazda > optymalizacja zwalnia dzialanie programu > o kilka(dziesiat) %. Optymalizacja numer 1: używaj najlepszych algorytmów/instrukcji, funkcji in-line/makr, odwijaj pętle itp. Optymalizacja numer 2: w kompilatorze HLL włącz optymalizacje na szybkość. Optymalizacja numer 3: jeśli obie powyższe dają niewystarczające wyniki, sięgaj po assemblera. > Na przyklad: > > Czemu takie cos : > > mov edi,offset TABLICA > mov ecx,16 > sha1_processmessageblock4: > mov eax,dword ptr [edi-12] > xor eax,dword ptr [edi-32] > xor eax,dword ptr [edi-56] > xor eax,dword ptr [edi-64] > rol eax,1 > stosd > ; > inc ecx > cmp ecx,80 > jne sha1_processmessageblock4 > > Jest kilkukrotnie wolniejsze niz : > > mov edi,offset TABLICA > mov ecx,16 > sha1_processmessageblock4: > mov eax,ecx > shl eax,2 > sub eax,12 ; 3 * 4 > mov ebx,dword ptr [edi+eax] > sub eax,20 ; 5 * 4 > xor ebx,dword ptr [edi+eax] > sub eax,24 ; 6 * 4 > xor ebx,dword ptr [edi+eax] > sub eax,8 ; 2 * 4 > xor ebx,dword ptr [edi+eax] > rol ebx,1 > mov eax,ecx > shl eax,2 > mov dword ptr [edi+eax],ebx > ; > inc ecx > cmp ecx,80 > jne sha1_processmessageblock4 Trudno powiedzieć. Możliwe, że przez stosd. Ja bym strzelał, że wersja pierwsza powinna być szybsza. Może przebijasz cacheline. Może operacje na EBX lubią tą przerwę, która tu mają a nie jak poprzednio: co instrukcja o EAX, każda RMW. > Albo czemu takie cos : > > mov esi,offset Buffers_ ; D > mov edi,offset Buffers__ ; E > std > movsd > movsd > ror DWORD PTR [esi],2 > movsd > movsd > mov DWORD PTR [edi],eax > cld > > Jest duzo wolniejsze niz : > > mov ebx,DWORD PTR [Buffers+12] ; E = D > mov DWORD PTR [Buffers+16],ebx > ;; > mov ebx,DWORD PTR [Buffers+8] ; D = C > mov DWORD PTR [Buffers+12],ebx > ; > mov ebx,DWORD PTR [Buffers+4] ; C = SHA1CircularShift(30,B) > ror ebx,2 > mov DWORD PTR [Buffers+8],ebx > ; > mov ebx,DWORD PTR [Buffers] ; B = A > mov DWORD PTR [Buffers+4],ebx > ; > mov ebx,eax > mov DWORD PTR [Buffers],eax ; A = temp Też możliwe, że przez movsd. Ror na pamięci też nie wymiata, ale przynajmniej jest Direct Path. Tą drugą wersję można jeszcze przyspieszyć moim zdaniem, używając różnych rejestrów. > Albo na przyklad mam cos takiego : > > mov al,byte ptr [esi+ecx] > mov byte ptr [edi+ebx],al > inc ecx > inc ebx > inc [Message_Block_Index] << TO JEST WAZNE > ; > add [Length_Low],8 > jnz sha1_input8 ; > inc [Length_High] ; > jnz sha1_input8 > mov [Corrupted],1 > > Zmienna Message_Block_Index to zwykla zmienna DD w sekcji .data. Nie jest do > niczego juz potrzebna bo zamiast niej > zapisuje dane w rejestrach. Usuwam ta linie i program zwalnia o 5% ! > Oczywiscie dziala bez zmiena tylko wolniej. Wstaw ze 5-10 NOPów, może pomoże. Chodzi o to, że poprzednie instrukcje się muszą wykonać, nowe - zostać zdekodowane. Tak *mi* się wydaje. Poza tym, należy unikać używania rejestrów cząstkowych o ile się da. Należy rozdzielać instrukcje zależne. > Oprocz tego na przyklad wielokrotne > > mov eax,edx > shl eax,2 > mov eax,DWORD PTR [Word_+eax] ; > > Dziala oczywiscie duzo szybciej niz proste > > mov esi,offset Word_ > > i potem juz tylko kilkadziesiat razy > > lodsd Instrukcje łańcuchowe są powolne. > Czy ktos mi to wyjasni albo chociaz powie gdzie mozna jakies konkrety na ten > temat przeczytac ? Ja swoje informacje biorę z podręczników optymalizacyjnych AMD: http://www.amd.com/us-en/Processors/DevelopWithAMD/0,,30_2252_739_7044,00.html Niedawno jeden kolega na alt.pl.asm próbował łamać MD5. Może połączycie siły? To, że w SHA1 i MD5 odkryto jakieś dziurki nie oznacza od razu, że w jakimś rozsądnym czasie znajdziecie kolizje. -- Pozdrawiam, Bogdan (Linux i FreeDOS) Kurs assemblera x86 (DOS i Linuks): http://rudy.mif.pg.gda.pl/~bogdro Grupy dyskusyjne o asm: pl.comp.lang.asm alt.pl.asm alt.pl.asm.win32 Prawdziwy, bezpieczny komunikator: www.JabberPL.org
Re: optymalizacja
Author: tosamo
Date: Wed, 17 May 2006 16:15
Date: Wed, 17 May 2006 16:15
105 lines
4194 bytes
4194 bytes
Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomości
news:e4ffrk$he5$1@nemesis.news.tpi.pl...
> tosamo napisał(a):
>> Witam
>>
>> Pisze sobie porgramik w masm32 (wersja 6.11 chyba). Do tej pory pisalem
>> glownie w c i pascalu wiec na poczatku
>> program w asm wygladal jak dokladna kalka z jezykow wyzszego rzedu i
>> dzialal
>> jakies 3 razy wolniej niz
>> pascal i delphi. Potem zaczalem optymalizowac i wyszlo na to, ze kazda
>> optymalizacja zwalnia dzialanie programu
>> o kilka(dziesiat) %.
>
> Optymalizacja numer 3: jeśli obie powyższe dają niewystarczające
> wyniki, sięgaj po assemblera.
To ma byc na zaliczenie z jezykow asemblerowych wiec musi byc w asm.
Ciekawe co powie wykladowca jak zobaczy ze w asm wyszlo 5 razy wolniej niz w
c
i 4 razy wolniej niz w delphi.
>> Na przyklad:
>>
>> {..}
>> ;
>> mov ebx,eax
>> mov DWORD PTR [Buffers],eax ; A = temp
>
> Też możliwe, że przez movsd. Ror na pamięci też nie wymiata, ale
> przynajmniej jest Direct Path.
> Tą drugą wersję można jeszcze przyspieszyć moim zdaniem, używając
> różnych rejestrów.
Moze i mozna. I tak postanowilem pojsc inna droga i zupelnie wywalilem
te kopiowanie.
>> Albo na przyklad mam cos takiego :
>>
>> mov al,byte ptr [esi+ecx]
>> mov byte ptr [edi+ebx],al
>> inc ecx
>> inc ebx
>> inc [Message_Block_Index] << TO JEST WAZNE
>> ;
>> add [Length_Low],8
>> jnz sha1_input8 ;
>> inc [Length_High] ;
>> jnz sha1_input8
>> mov [Corrupted],1
>>
>> Zmienna Message_Block_Index to zwykla zmienna DD w sekcji .data. Nie jest
>> do
>> niczego juz potrzebna bo zamiast niej
>> zapisuje dane w rejestrach. Usuwam ta linie i program zwalnia o 5% !
>> Oczywiscie dziala bez zmiena tylko wolniej.
>
> Wstaw ze 5-10 NOPów, może pomoże. Chodzi o to, że poprzednie
> instrukcje się muszą wykonać, nowe - zostać zdekodowane. Tak *mi* się
> wydaje. Poza tym, należy unikać używania rejestrów cząstkowych o ile
> się da.
Ten fragment to akurat dokladna kopia z c. Postaram sie to jeszcze
zoptymalizowac.
Zrobie kopiowanie calych blokow po 4 bajty i znowu bede mial o 50% wolniej.
> Należy rozdzielać instrukcje zależne.
Ale o co chodzi ?
>> {..}
>> lodsd
>
> Instrukcje łańcuchowe są powolne.
A ja caly czas zylem w przeswiadczeniu, ze to najszybszy sposob na
kopiowanie
pamieci. W takim razie co bedzie szybsze ?
Takie cos ?
mov eax,dword ptr [esi]
inc esi
>> Czy ktos mi to wyjasni albo chociaz powie gdzie mozna jakies konkrety na
>> ten
>> temat przeczytac ?
>
> Ja swoje informacje biorę z podręczników optymalizacyjnych AMD:
> http://www.amd.com/us-en/Processors/DevelopWithAMD/0,,30_2252_739_7044,00.html
Zobacze.
> Niedawno jeden kolega na alt.pl.asm próbował łamać MD5. Może
> połączycie siły? To, że w SHA1 i MD5 odkryto jakieś dziurki nie
> oznacza od razu, że w jakimś rozsądnym czasie znajdziecie kolizje.
Ja nie probuje lamac sha. Musze tylko zrobic zeby bylo chociaz o kilka %
szybsze niz
przyklad w c i bedzie ok. Juz mi wyszlo, ze dla duzych blokow danych jest
szybszy tylko
z malymi sobie nie radzi.
Dzieki za odpowiedz.
Re: optymalizacja
Author: Bogdan (bogdro)
Date: Thu, 18 May 2006 08:33
Date: Thu, 18 May 2006 08:33
140 lines
5927 bytes
5927 bytes
tosamo napisał(a):
> Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomości
> news:e4ffrk$he5$1@nemesis.news.tpi.pl...
>> tosamo napisał(a):
>>> Witam
>>>
>>> Pisze sobie porgramik w masm32 (wersja 6.11 chyba). Do tej pory pisalem
>>> glownie w c i pascalu wiec na poczatku
>>> program w asm wygladal jak dokladna kalka z jezykow wyzszego rzedu i
>>> dzialal
>>> jakies 3 razy wolniej niz
>>> pascal i delphi. Potem zaczalem optymalizowac i wyszlo na to, ze kazda
>>> optymalizacja zwalnia dzialanie programu
>>> o kilka(dziesiat) %.
>> Optymalizacja numer 3: jeśli obie powyższe dają niewystarczające
>> wyniki, sięgaj po assemblera.
>
> To ma byc na zaliczenie z jezykow asemblerowych wiec musi byc w asm.
> Ciekawe co powie wykladowca jak zobaczy ze w asm wyszlo 5 razy wolniej niz w
> c
> i 4 razy wolniej niz w delphi.
A, z tym zaliczeniem to inna mowa teraz. Czasem może być ciężko pobić
kompilator. Popatrz na moje wskazówki pod koniec, może coś się uda.
>> Należy rozdzielać instrukcje zależne.
>
> Ale o co chodzi ?
Jak masz takie coś:
mov eax, [zmienna]
add eax, 2
mov ebx, [zmienna2]
add ebx, 10
mov ecx, [zmienna3]
sub ecx, 20
to lepiej powinno wyjść:
mov eax, [zmienna]
mov ebx, [zmienna2]
mov ecx, [zmienna3]
add eax, 2
add ebx, 10
sub ecx, 20
Chodzi o to, że jeśli instrukcje operujące na tym samym rejestrze nie
muszą być obok siebie, to niech nie będą.
>
>>> {..}
>>> lodsd
>> Instrukcje łańcuchowe są powolne.
>
> A ja caly czas zylem w przeswiadczeniu, ze to najszybszy sposob na
> kopiowanie
> pamieci. W takim razie co bedzie szybsze ?
>
> Takie cos ?
>
> mov eax,dword ptr [esi]
> inc esi
Czasem tak, choć nie mierzyłem. Jakby się jeszcze udało oddzielić te
dwie instrukcjami niezależnymi od ESI, to powinno być jeszcze lepiej.
Najnowsze procesory nawet bardziej lubią "add esi, 1" niż "inc esi".
Najlepiej moim zdaniem używać złożonych sposobów adresowania (np.
takich, jakie podałeś w pierwszym fragmencie kodu: [edi-xxx]), a potem
podbijać rejestr wskazujący (tu: ESI) o większą liczbę na raz, jeśli
możliwe.
> Ja nie probuje lamac sha. Musze tylko zrobic zeby bylo chociaz o kilka %
> szybsze niz
> przyklad w c i bedzie ok. Juz mi wyszlo, ze dla duzych blokow danych jest
> szybszy tylko
> z malymi sobie nie radzi.
Bo to tak jest z instrukcjami łańcuchowymi: lods*, movs*, ...
Zaczynają one sobie radzić dopiero przy większych porcjach danych.
Kiedyś widziałem testy, że dla małych porcji danych najszybciej
wychodzi "ręczne" kopiowanie (mov itp), dla średnich (powiedzmy,
64-512 bajtów) - rep movs*, dla dużych - MMX i SSE. Mimo iż to było z
REP, to same instrukcje też nie są genialnie szybkie (4 cykle, w
porównaniu do 0.5 czy 1 niektórych MOV). Po prostu są one dość złożone.
Jeszcze kilka rad dorzucę:
- często używane zmienne załaduj do rejestrów. Czasem tych cząstkowych
trzeba będzie używać, ale może jednak coś przyspieszy.
- stosując CMOVcc, SETcc wyeliminuj tyle skoków warunkowych, ile się
tylko da.
- po każdym JMP daj UD2, co zahamuje niepotrzebne dekodowanie dalszych
instrukcji
- istotne etykiety (może nawet wszystkie) ułóż dyrektywą "align 16" na
adresach podzielnych przez 16. W ten sposób małe fragmenty kodu między
dwoma etykietami (lub czasem całe procedury) nie będą przełamane na
zbyt dużo linii pamięci podręcznej cache procesora. Przykład:
align 16
funkcja:
...
Jeśli funkcja na pewno już się nie zmieni, to rozważ, czy nie lepiej
wkleić ją w miejsce CALL, bo uruchamianie funkcji i powrót też swoje
trwają.
- dane układaj według malejących rozmiarów, przed pierwszą z nich daj
"align 16", głównie z tych samych powodów co wyżej.
- jeśli jakieś instrukcje zależne muszą być blisko siebie, spróbuj
rozdzielić kilkoma NOPami. Czasem pomaga.
- unikaj mnożenia MUL przez małą stałą liczbę (ostatnio mul
przyspieszył, więc mnożenie już tak nie boli jak dawniej).
- jeśli procesor to Pentium IV lub okolice, unikaj SHL i stosuj ADD
zamiast niego
- zamiast "or rej1, rej1", używaj "test rej1, rej1" (na tym samym
rejestrze)
- w ostatecznej wersji programu nie może być żadnego wyświetlania w
pętlach (chyba że absolutnie naprawdę konieczne). Wyświetlanie nieźle
zamula.
- zamiast kilku PUSHów na rejestrach, daj "sub esp, xxx" i sekwencję
"mov [esp+xxx], yyy". Jeśli możliwe, przekazuj parametry (o ile są
potrzebne) w rejestrach. Dla twardzieli: nie używaj EBP w funkcjach i
operuj na ESP.
--
Pozdrawiam, Bogdan (Linux i FreeDOS)
Kurs assemblera x86 (DOS i Linuks): http://rudy.mif.pg.gda.pl/~bogdro
Grupy dyskusyjne o asm: pl.comp.lang.asm alt.pl.asm alt.pl.asm.win32
Prawdziwy, bezpieczny komunikator: www.JabberPL.org
Re: optymalizacja
Author: tosamo
Date: Thu, 18 May 2006 22:34
Date: Thu, 18 May 2006 22:34
43 lines
2463 bytes
2463 bytes
Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomości
news:e4hbi4$fpm$1@atlantis.news.tpi.pl...
> tosamo napisał(a):
>> Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomości
>> news:e4ffrk$he5$1@nemesis.news.tpi.pl...
>>> tosamo napisał(a):
>>>> Witam
>>>>
>>>> Pisze sobie porgramik w masm32 (wersja 6.11 chyba). Do tej pory pisalem
>>>> glownie w c i pascalu wiec na poczatku
>>>> program w asm wygladal jak dokladna kalka z jezykow wyzszego rzedu i
>
> - zamiast kilku PUSHów na rejestrach, daj "sub esp, xxx" i sekwencję
> "mov [esp+xxx], yyy". Jeśli możliwe, przekazuj parametry (o ile są
> potrzebne) w rejestrach. Dla twardzieli: nie używaj EBP w funkcjach i
> operuj na ESP.
> {..}
No dobra. Wiekszosc z rozwiazan o ktorych piszesz probowalem stosowac.
Niektore
rzeczywiscie mocno przyspieszyly prorgam (np rezygnacja z push i pop).
Jedna rzecz mnie totalnie zalamala :
mov eax,offset Intermediate_Hash
mov DWORD PTR [eax+20],067452301h
Zmienna zadeklarowana jest tak
To fragment procedurki ktory powinein wystarczyc do przedstawienai problemu
To sie wykonuje 40us (dla porownania caly hash z wyjatkiem tego kawalka
liczy sie tylko 12us !!)
Disassemblowalem podobna procedure z c. Jest praktycznie identyczna do tego
co sam napisalem
i wykonuje sie w czasie ponizej 1us.
Robilem wszystko co sie dalo (lacznie z mov ecx,067452301h i mov mov DWORD
PTR [eax+20],ecx) i nic.
Ta
Re: optymalizacja
Author: tosamo
Date: Thu, 18 May 2006 22:41
Date: Thu, 18 May 2006 22:41
49 lines
2697 bytes
2697 bytes
Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomo?ci
news:e4hbi4$fpm$1@atlantis.news.tpi.pl...
> tosamo napisał(a):
>> Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomo?ci
>> news:e4ffrk$he5$1@nemesis.news.tpi.pl...
>>> tosamo napisał(a):
>>>> Witam
>>>>
>>>> Pisze sobie porgramik w masm32 (wersja 6.11 chyba). Do tej pory pisalem
>>>> glownie w c i pascalu wiec na poczatku
>>>> program w asm wygladal jak dokladna kalka z jezykow wyzszego rzedu i
>
> - zamiast kilku PUSHów na rejestrach, daj "sub esp, xxx" i sekwencję
> "mov [esp+xxx], yyy". Je?li możliwe, przekazuj parametry (o ile s?
> potrzebne) w rejestrach. Dla twardzieli: nie używaj EBP w funkcjach i
> operuj na ESP.
> {..}
No dobra. Wiekszosc z rozwiazan o ktorych piszesz probowalem stosowac.
Niektore rzeczywiscie mocno przyspieszyly prorgam (np rezygnacja z push i
pop).
Jedna rzecz mnie totalnie zalamala :
mov eax,offset Intermediate_Hash
mov DWORD PTR [eax+20],067452301h
Zmienna zadeklarowana jest tak
align 16
Intermediate_Hash DD 5 DUP(0)
To fragment procedurki ktory powinein wystarczyc do przedstawienai problemu
To sie wykonuje 40us (dla porownania caly hash z wyjatkiem tego kawalka
liczy sie tylko 12us !!)
Disassemblowalem procedure ktora robi to samo z c. Jest praktycznie
identyczna do tego
co sam napisalem i wykonuje sie w czasie ponizej 1us.
Robilem wszystko co sie dalo (lacznie z mov ecx,067452301h i mov mov DWORD
PTR [eax+20],ecx) i nic. Probowalem zamiast eax korzystac z innych rejestrow
(chociaz to w c
korzysta z eax i jest ok).
Wiesz co z tym zrobic ? W zasadzie do pelni szczescia brakuje mi juz tylko
tego fragmentu.
Re: optymalizacja
Author: tosamo
Date: Thu, 18 May 2006 23:48
Date: Thu, 18 May 2006 23:48
52 lines
2740 bytes
2740 bytes
Użytkownik "tosamo" <tosamo@o2.pl> napisał w wiadomości news:e4it6m$c00$1@inews.gazeta.pl... > > Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomo?ci > news:e4hbi4$fpm$1@atlantis.news.tpi.pl... >> tosamo napisał(a): >>> Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomo?ci >>> news:e4ffrk$he5$1@nemesis.news.tpi.pl... >>>> tosamo napisał(a): >>>>> Witam >>>>> >>>>> Pisze sobie porgramik w masm32 (wersja 6.11 chyba). Do tej pory >>>>> pisalem >>>>> glownie w c i pascalu wiec na poczatku >>>>> program w asm wygladal jak dokladna kalka z jezykow wyzszego rzedu i >> > > mov eax,offset Intermediate_Hash > mov DWORD PTR [eax+20],067452301h > > Zmienna zadeklarowana jest tak > > align 16 > Intermediate_Hash DD 5 DUP(0) > > To fragment procedurki ktory powinein wystarczyc do przedstawienai > problemu > > To sie wykonuje 40us (dla porownania caly hash z wyjatkiem tego kawalka > liczy sie tylko 12us !!) > > Wiesz co z tym zrobic ? W zasadzie do pelni szczescia brakuje mi juz tylko > tego fragmentu. No i sie troche wyjasnilo. Problemem jest to, ze laduje plik dll (mam 3 dll z identycznymi funkcjami hashujacymi w c, delphi i asm) i ten fragment napisany wyzej to pierwsza operacja na sekcji danych. Jesli zrobie inicjacje hashowania a potem wlacze timer i powtorze ta inicjacje to juz wykonuje sie okolo 1us zamiast 50us. Wersje c i delphi oczywiscie nie maja tego problemu bo przy ladowaniu dll cos tam na pewno mieszaja juz z danymi. Problem rozwiazalo zapisanie czegos w LibMain (DllMain) do pamieci. Wiesz moze czemu tak jest ? Musze w dokumentacji projektu opisac ten projekt a nie za bardzo wiem gdzie tego szukac.
Re: optymalizacja
Author: Lopez
Date: Fri, 19 May 2006 05:41
Date: Fri, 19 May 2006 05:41
33 lines
1877 bytes
1877 bytes
Użytkownik "tosamo" napisał... > > No i sie troche wyjasnilo. Problemem jest to, ze laduje plik dll (mam 3 dll > z identycznymi > funkcjami hashujacymi w c, delphi i asm) i ten fragment napisany wyzej to > pierwsza > operacja na sekcji danych. Jesli zrobie inicjacje hashowania a potem wlacze > timer i powtorze > ta inicjacje to juz wykonuje sie okolo 1us zamiast 50us. > > Wersje c i delphi oczywiscie nie maja tego problemu bo przy ladowaniu dll > cos tam na pewno > mieszaja juz z danymi. > > Problem rozwiazalo zapisanie czegos w LibMain (DllMain) do pamieci. > > Wiesz moze czemu tak jest ? Musze w dokumentacji projektu opisac ten projekt > a nie za bardzo > wiem gdzie tego szukac. wyglada na to, ze strona, w ktorej znajduje sie hash, jeszcze nie jest zaladowana do pamieci i jest allokowana przy pierwszym dostepie. -- Pozdrawiam Lopez
Re: optymalizacja
Author: Bogdan (bogdro)
Date: Fri, 19 May 2006 11:20
Date: Fri, 19 May 2006 11:20
68 lines
3954 bytes
3954 bytes
tosamo napisał(a): >> mov eax,offset Intermediate_Hash >> mov DWORD PTR [eax+20],067452301h >> >> Zmienna zadeklarowana jest tak >> >> align 16 >> Intermediate_Hash DD 5 DUP(0) >> >> To fragment procedurki ktory powinein wystarczyc do przedstawienai >> problemu >> >> To sie wykonuje 40us (dla porownania caly hash z wyjatkiem tego kawalka >> liczy sie tylko 12us !!) >> >> Wiesz co z tym zrobic ? W zasadzie do pelni szczescia brakuje mi juz tylko >> tego fragmentu. > > No i sie troche wyjasnilo. Problemem jest to, ze laduje plik dll (mam 3 dll > z identycznymi > funkcjami hashujacymi w c, delphi i asm) i ten fragment napisany wyzej to > pierwsza > operacja na sekcji danych. Jesli zrobie inicjacje hashowania a potem wlacze > timer i powtorze > ta inicjacje to juz wykonuje sie okolo 1us zamiast 50us. > > Wersje c i delphi oczywiscie nie maja tego problemu bo przy ladowaniu dll > cos tam na pewno > mieszaja juz z danymi. > > Problem rozwiazalo zapisanie czegos w LibMain (DllMain) do pamieci. > > Wiesz moze czemu tak jest ? Musze w dokumentacji projektu opisac ten projekt > a nie za bardzo > wiem gdzie tego szukac. Prawdopodobnie (bo nie znam Win) jest dokładnie tak, jak mówi Lopez. Nie wszystkie części kodu/danych są od razu ładowane do pamięci przez system. Jak po raz pierwszy odwołujesz się do niezaładowanej sekcji, występuje wyjątek Page Fault, bo tej strony nie ma w pamięci. System obsługuje ten wyjątek i ładuje odpowiednie sekcje (strony pamięci) z dysku do RAM. Zarówno obsługa wyjątków, jak i operacje na dysku trwają długo. Rozwiązaniem tego problemu jest właśnie dowolny dostęp do niezaładowanej sekcji. Nawiasem mówiąc, proponuję kod: mov DWORD PTR [Intermediate_Hash+20],067452301h Długaśna z tego instrukcja wyjdzie, ale lepsza niż dwie. Wiesz, że ta instrukcja zapisuje dane poza tablicą Intermediate_Hash (która ma 20 bajtów)? Swoją drogą, można byłoby zrobić pożytek z pamięci podręcznej procesora: użycie instrukcji PREFETCH* mówi procesorowi, że "jakiś tam adres wkrótce będzie używany i dobrze byłoby go załadować do cache". To jest tylko wskazówka dla procesora, nie musi tego robić. Jeśli te instrukcje nie są dostępne (lub chcemy mieć pewność), to na początku programu jawnie załaduj gdziekolwiek zawartość kilku zmiennych (takich odległych o 16 czy 32 bajty od siebie). To załadowanie na początku chwilkę zaboli, ale potem dzięki temu wszystko powinno być w cache i operacje na danych powinny być wykonywane szybciej. -- Pozdrawiam, Bogdan (Linux i FreeDOS) Kurs assemblera x86 (DOS i Linuks): http://rudy.mif.pg.gda.pl/~bogdro Grupy dyskusyjne o asm: pl.comp.lang.asm alt.pl.asm alt.pl.asm.win32 Prawdziwy, bezpieczny komunikator: www.JabberPL.org
Re: optymalizacja
Author: tosamo
Date: Fri, 19 May 2006 13:28
Date: Fri, 19 May 2006 13:28
60 lines
3227 bytes
3227 bytes
Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomości news:e4k9m6$ogh$1@atlantis.news.tpi.pl... >> >> Wersje c i delphi oczywiscie nie maja tego problemu bo przy ladowaniu dll >> cos tam na pewno >> mieszaja juz z danymi. >> >> Problem rozwiazalo zapisanie czegos w LibMain (DllMain) do pamieci. >> >> Wiesz moze czemu tak jest ? Musze w dokumentacji projektu opisac ten >> projekt >> a nie za bardzo >> wiem gdzie tego szukac. > > Prawdopodobnie (bo nie znam Win) jest dokładnie tak, jak mówi Lopez. > Nie wszystkie części kodu/danych są od razu ładowane do pamięci przez > system. Jak po raz pierwszy odwołujesz się do niezaładowanej sekcji, > występuje wyjątek Page Fault, bo tej strony nie ma w pamięci. System > obsługuje ten wyjątek i ładuje odpowiednie sekcje (strony pamięci) z > dysku do RAM. Zarówno obsługa wyjątków, jak i operacje na dysku trwają > długo. Rozwiązaniem tego problemu jest właśnie dowolny dostęp do > niezaładowanej sekcji. OK. Dzieki. > Nawiasem mówiąc, proponuję kod: > > mov DWORD PTR [Intermediate_Hash+20],067452301h Ale takie cos : mov DWORD PTR [Intermediate_Hash],067452301h mov DWORD PTR [Intermediate_Hash+4],0EFCDAB89h mov DWORD PTR [Intermediate_Hash+8],098BADCFEh mov DWORD PTR [Intermediate_Hash+12],010325476h mov DWORD PTR [Intermediate_Hash+16],0C3D2E1F0h bedzie lepsze niz mov eax,offset Intermediate_Hash mov DWORD PTR [eax],067452301h mov DWORD PTR [eax+4],0EFCDAB89h mov DWORD PTR [eax+8],098BADCFEh mov DWORD PTR [eax+12],010325476h mov DWORD PTR [eax+16],0C3D2E1F0h ? Wersja z rejestrem nie jest szybsza ? > Długaśna z tego instrukcja wyjdzie, ale lepsza niż dwie. Wiesz, że ta > instrukcja zapisuje dane poza tablicą Intermediate_Hash (która ma 20 > bajtów)? Nie wiem skad tam sie wzielo te 20. W programie tego nie ma. > Swoją drogą, można byłoby zrobić pożytek z pamięci podręcznej > procesora: użycie instrukcji PREFETCH* mówi procesorowi, Nie wiem w ktorym dokladnie procesorze sie to pojawilo ale watpie zeby na tej uczelni mieli takie nowoczesne komputery ;)
Re: optymalizacja
Author: Bogdan (bogdro)
Date: Fri, 19 May 2006 16:57
Date: Fri, 19 May 2006 16:57
48 lines
2950 bytes
2950 bytes
tosamo napisał(a): > Ale takie cos : > > mov DWORD PTR [Intermediate_Hash],067452301h > mov DWORD PTR [Intermediate_Hash+4],0EFCDAB89h > mov DWORD PTR [Intermediate_Hash+8],098BADCFEh > mov DWORD PTR [Intermediate_Hash+12],010325476h > mov DWORD PTR [Intermediate_Hash+16],0C3D2E1F0h > > bedzie lepsze niz > > mov eax,offset Intermediate_Hash > mov DWORD PTR [eax],067452301h > mov DWORD PTR [eax+4],0EFCDAB89h > mov DWORD PTR [eax+8],098BADCFEh > mov DWORD PTR [eax+12],010325476h > mov DWORD PTR [eax+16],0C3D2E1F0h > > ? Wersja z rejestrem nie jest szybsza ? Wersja z rejestrem na pewno będzie wygodniejsza w pisaniu i w utrzymaniu. Czy szybsza, to nie wiem. Jak miałbym zgadywać, to powiedziałbym, że nie, bo podałeś grupy instrukcji typu: mov [zmienna], liczba i mov [eax], liczba Ten adres musi jednak kiedyś być obliczany, bo nie jest stały. A pierwsza grupa instrukcji operuje na stałych adresach obliczonych i wstawionych na sztywno przez kompilator czy linker (niemniej, są one zakodowane na sztywno w programie). Poza tym, nie ukrywajmy, że jest to o 1 instrukcję (mov eax,) mniej. Jeśli drugi fragment kodu wygląda w programie tak, jak tutaj, to dodatkowo na korzyść *pierwszego* przemawia zwolnienie rejestru EAX do obliczeń lub przechowywania jakiejś zmiennej oraz przede wszystkim likwidacja zależności między co najmniej 2 instrukcjami, którą to zależność gołym okiem widać w 2 pierwszych instrukcjach drugiej grupy: mov eax, ... / mov [eax..], ... -- Pozdrawiam, Bogdan (Linux i FreeDOS) Kurs assemblera x86 (DOS i Linuks): http://rudy.mif.pg.gda.pl/~bogdro Grupy dyskusyjne o asm: pl.comp.lang.asm alt.pl.asm alt.pl.asm.win32 Prawdziwy, bezpieczny komunikator: www.JabberPL.org
Re: optymalizacja
Author: tosamo
Date: Fri, 19 May 2006 19:49
Date: Fri, 19 May 2006 19:49
32 lines
2061 bytes
2061 bytes
Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomości
news:e4kthl$25d$1@nemesis.news.tpi.pl...
> tosamo napisał(a):
>> Ale takie cos :
>>
>> mov DWORD PTR [Intermediate_Hash],067452301h
>> mov DWORD PTR [Intermediate_Hash+4],0EFCDAB89h
>>
>> bedzie lepsze niz
>>
>> mov eax,offset Intermediate_Hash
>> mov DWORD PTR [eax],067452301h
>>
>> ? Wersja z rejestrem nie jest szybsza ?
>
> Wersja z rejestrem na pewno będzie wygodniejsza w pisaniu i w
> utrzymaniu. Czy szybsza, to nie wiem. Jak miałbym zgadywać, to
> powiedziałbym, że nie, bo podałeś grupy instrukcji typu:
Nie wiem jak to cos ale takie zapamietywanie rejestrow
mov DWORD PTR [REGISTERS],EAX
mov DWORD PTR [REGISTERS+4],EBX
mov DWORD PTR [REGISTERS+4*2],ECX
jest wolniejsze niz to
sub esp,12
mov DWORD PTR [esp+4*2],EBP
mov DWORD PTR [esp+4],ESI
mov DWORD PTR [esp],EDI
Re: optymalizacja
Author: Lopez
Date: Sat, 20 May 2006 08:23
Date: Sat, 20 May 2006 08:23
47 lines
2514 bytes
2514 bytes
Użytkownik "tosamo" napisał... > > Użytkownik "Bogdan (bogdro)" <bogdan@bogdan.pl> napisał w wiadomości > news:e4kthl$25d$1@nemesis.news.tpi.pl... > > tosamo napisał(a): > >> Ale takie cos : > >> > >> mov DWORD PTR [Intermediate_Hash],067452301h > >> mov DWORD PTR [Intermediate_Hash+4],0EFCDAB89h > >> > >> bedzie lepsze niz > >> > >> mov eax,offset Intermediate_Hash > >> mov DWORD PTR [eax],067452301h > >> > >> ? Wersja z rejestrem nie jest szybsza ? > > > > Wersja z rejestrem na pewno będzie wygodniejsza w pisaniu i w > > utrzymaniu. Czy szybsza, to nie wiem. Jak miałbym zgadywać, to > > powiedziałbym, że nie, bo podałeś grupy instrukcji typu: > > Nie wiem jak to cos ale takie zapamietywanie rejestrow > > mov DWORD PTR [REGISTERS],EAX > mov DWORD PTR [REGISTERS+4],EBX > mov DWORD PTR [REGISTERS+4*2],ECX > > jest wolniejsze niz to > > sub esp,12 > mov DWORD PTR [esp+4*2],EBP > mov DWORD PTR [esp+4],ESI > mov DWORD PTR [esp],EDI > ZTCW to zapisywanie na stosie o wiele szybsze, poniewaz 1. adres aktualnej strony stosu jest juz od dawna w TLB i wyznaczenie efektywnego adresu zwykle nic nie kosztuje. 2. strona ta juz prawdopodobnie znajduje sie w L2, albo moze nawet czesciowo w L1 ale wszystko zalezy od tego, co sie dzialo wczesniej i jak bardzo uzywales stosu. -- Pozdrawiam Lopez
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads