🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: pl.comp.lang.asm
13 messages
13 total messages Started by tosamo Wed, 17 May 2006 12:42
optymalizacja
#250
Author: tosamo
Date: Wed, 17 May 2006 12:42
118 lines
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
#251
Author: Bogdan (bogdro)
Date: Wed, 17 May 2006 15:33
158 lines
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
#252
Author: tosamo
Date: Wed, 17 May 2006 16:15
105 lines
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
#253
Author: Bogdan (bogdro)
Date: Thu, 18 May 2006 08:33
140 lines
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
#254
Author: tosamo
Date: Thu, 18 May 2006 22:34
43 lines
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
#255
Author: tosamo
Date: Thu, 18 May 2006 22:41
49 lines
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
#256
Author: tosamo
Date: Thu, 18 May 2006 23:48
52 lines
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
#257
Author: Lopez
Date: Fri, 19 May 2006 05:41
33 lines
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
#258
Author: Bogdan (bogdro)
Date: Fri, 19 May 2006 11:20
68 lines
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
#259
Author: tosamo
Date: Fri, 19 May 2006 13:28
60 lines
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
#260
Author: Bogdan (bogdro)
Date: Fri, 19 May 2006 16:57
48 lines
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
#261
Author: tosamo
Date: Fri, 19 May 2006 19:49
32 lines
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
#262
Author: Lopez
Date: Sat, 20 May 2006 08:23
47 lines
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