🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: pl.comp.lang.asm
Article #2595

Re: [1/3 NTG] C - Optymalizacje wstawkami

#2595
From: Bogdan (bogdro)
Date: Tue, 12 Feb 2019 20:23
176 lines
7626 bytes
W dniu 11.02.2019 o 16:56, mezzogm@gmail.com pisze:

[...]

>> Większość funkcji C działa na łańcuchach znaków kończących się bajtem
>> zerowym, bo po prostu tak są zdefiniowane łańcuchy znaków w C.
> 
> 
> long int strtol (const char* str, char** endptr, int base)
> double strtod (const char* str, char** endptr)
> 
> Funkcja zwraca przekonwertowaną wartość, zwraca również (przez referencję endptr) wskaźnik do pierwszego znaku ZA przekonwertowanym ciągiem cyfr.
> Jakiekolwiek gmeranie w bajtach dalej odbieram jako RAŻĄCY BŁĄD - chyba, że ktoś mnie przekona, że jest w tym jakiś głębszy sens


 Fakt, funkcja powinna się zatrzymać po ostatnim rozpoznanym znaku.
Masz jakiś minimalistyczny kod, którym można odtworzyć problem, wraz z
parametrami, które problem generują?


>> Można zawsze np. zmienić '\n' lub kropkę na bajt zerowy '\0' i
>> dopiero takim "stuningowanym" łańcuchem nakarmić strdo*().
> 
> 
> Można różne rzeczy, ale "ręczne" parsowanie ciągu bajtów w celu stworzenia złudzenia jakiejś użyteczności zrypanej funkcji standardowej budzi u mnie wewnętrzny sprzeciw.


 Funkcja nie jest zrypana z punktu widzenia jej użyteczności w
ogólnych zastosowaniach. Nie jest i nie ma być uniwersalną funkcją
umiejącą sparsować wszystko, co się da.
 Twoje dane nie pasują do tej akurat funkcji, więc trzeba coś zrobić -
albo pogmerać trochę w danych tak, aby działały funkcje standardowe,
albo zrobić swoje funkcje, lepiej pasujące do danych. Generalnie to
drugie rozwiązanie pewnie będzie lepsze i szybsze (chociażby przez to,
że przez ciąg bajtów przejdzie tylko raz). Nie mówiąc o "wartości
edukacyjnej" :).



>> Pewnie poziom optymalizacji większy od zera?
> 
> 
> Poziom optymalizacji, to takie trochę czary-mary-makagigi.
> Kod wynikowy - to jest konkret. :-)


 Tak, ale zwróciłem uwagę, że pewnie -O0 wygenerowałoby kod z
instrukcją (I)DIV. Skoro tu jej nie ma, to pewnie było co najmniej
-O1, co daje taki kod wymagający głębszej analizy.

[...]


> W ogóle taką "masówkę" powinno się załatwiać w wątku niezależnym od GUI, a już najlepiej temat zrównoleglić.
> Tylko jak zrównoleglić sekwencyjny odczyt z pliku?
> Można by stanąć gdzieś w środku bufora, złapać na szybko koniec linii i puścić drugi wątek parsujący.
> Jeszcze tylko trzeba upchać jakoś dane z dwóch wątków, wiedząc, że wyszukiwać w nich będzie funkcja hashująca...
> 
> Choroba, samo pisanie na tej grupie jest inspirujące! :-)


 :)
 Odczytu z pliku nie zrównoleglaj, bo cały zysk może zostać
przejedzony przez ciągłe uruchamianie fseek(). Załaduj cały plik do
pamięci, a dalej - jak piszesz: znaleźć "gdzieś w środku" separator, i
jeden wątek puszczasz na pierwszej części bufora, a drugi - na drugiej.


>> Jeśli kompilujesz C z optymalizacjami, to wygrać z kompilatorem w
>> tych czasach może być ciężko.
> 
> 
> Taki kod w C:
> 
> 
> QueryPerformanceCounter(&StartCounter);
> 
> *cptr = 0x0;
> while (iValue)
> {
>    *--cptr = char(iValue % 10) | '0';
>    iValue /= 10;
> }
> 
> QueryPerformanceCounter(&EndCounter);
> 
> 
> wypluty przez MinGW do kodu asemblera wygląda tak:
> 
> 
> 
> 	call	_QueryPerformanceCounter@4
> 	subl	$4, %esp
> 	movl	$2137483647, %ecx
> 	leal	143(%esp), %ebx
> 	leal	133(%esp), %edi
> 	movb	$0, 143(%esp)
> 	.p2align 4,,10
> L2:
> 	movl	%ecx, %eax
> 	subl	$1, %ebx
> 	imull	%esi
> 	movl	%ecx, %eax
> 	sarl	$31, %eax
> 	sarl	$2, %edx
> 	subl	%eax, %edx
> 	leal	(%edx,%edx,4), %eax
> 	addl	%eax, %eax
> 	subl	%eax, %ecx
> 	orl	$48, %ecx
> 	cmpl	%edi, %ebx
> 	movb	%cl, (%ebx)
> 	movl	%edx, %ecx
> 	jne	L2
> 	leal	72(%esp), %eax
> 	movl	%eax, (%esp)
> 	call	_QueryPerformanceCounter@4
> 	subl	$4, %esp
> 
> 
> Zakładam, że cała akcja dzieje się pomiędzy dwoma wywołaniami QueryPerformanceCounter.


Tak, poza "subl	$4, %esp", rzecz jasna (usuwanie argumentów ze stosu).


> Da się tu coś istotnego wywalić?
> Na moje oko (skłute składnią AT&T :D) kompilator wyłapał i uwzględnił sąsiadujące modulo i dzielenie przez 10.
> A wtedy - nic tu się nie urwie (ponad poziom szumu).


 No, można byłoby przestać używać pamięci, a wziąć jakiś nieużywany
rejestr, np. EBP. Kod w poprzednich linkach wyglądał na lepszy, więc
coś tam się poprawić da. Pierwszy SAR ustawia cały rejestr na 0 lub
FFFFFFFF, pewnie można byłoby to też jakoś przerobić. Ale to kwestia
doboru rozwiązania. Może to będzie szybsze w zadanych parametrach.
Jakie były parametry -O, -mtune i -march? Z innymi jest inny kod?
 A tak poza tym na oko to nie za wiele da się urwać. Jak pisałem, gdy
włączasz optymalizacje, wygrać z kompilatorem w tych czasach może być
ciężko.


> Czym się kurde różni SAR od SHR?


 SAR to dzielenie arytmetyczne, czyli takie "po ludzku" z zachowaniem
znaku (bit znaku zostaje na miejscu i to on jest kopiowany w prawo, a
nie zera są pompowane od lewej, jak w zwykłym SHR). SHR to proste
przesuwanie bitów.
 Weźmy sobie liczbę 80h (0x80). Bitowo jest to 1000 0000.
 Jeśli traktujesz ją jako liczbę bez znaku, to ta wartość odpowiada
liczbie +128. Jeśli jako liczbę ze znakiem, wynosi to -128.
 I teraz jedziemy:
	1000 0000 SAR 1 = 1100 0000 (-128 / 2 = -64)
	1100 0000 SAR 1 = 1110 0000 (-64 / 2 = -32)
...
	1111 1110 SAR 1 = 1111 1111 (-2 / 2 = -1)

 Wygląda logicznie. Z kolei, gdybyś użył zwykłego SHR, to -128 / 2 =
+64. Już trochę mniej sensownie.
 A jeśli traktujesz to jako liczbę bez znaku:
	1000 0000 SHR 1 = 0100 0000 (+128 / 2 = +64)
	0100 0000 SHR 1 = 0010 0000 (+64 / 2 = +32)
 Sensownie. A gdyby traktować to jako liczbę ze znakiem, to +128 / 2 =
192...
 Także, 80h to po prostu 80h, ale jak chcesz, aby działało z sensem,
musisz określić, co jest tym sensem - czy ta liczba ma być traktowana
jako ze znakiem (czyli od -2^(n-1) do +2^(n-1)-1, a najstarszy bit
mówi o znaku +/-), czy po prostu od 0 do +2^n-1.


-- 
Pozdrawiam/Regards - Bogdan                     (GNU/Linux & FreeDOS)
Kurs asemblera x86 (DOS, GNU/Linux):            http://bogdro.evai.pl
Grupy dyskusyjne o asm:  pl.comp.lang.asm alt.pl.asm alt.pl.asm.win32
www.Xiph.org www.TorProject.org  Soft(EN): http://bogdro.evai.pl/soft
Technical Details
Message-ID: <5c632b27$0$488$65785112@news.neostrada.pl>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!fu-berlin.de!goblin1!goblin.stu.neva.ru!newsfeed.neostrada.pl!unt-exc-01.news.neostrada.pl!unt-spo-a-02.news.neostrada.pl!news.neostrada.pl.POSTED!not-for-mail
References: <30292520-12bd-49f0-b5ce-39c9af378a4c@googlegroups.com> <5c5b41d7$0$501$65785112@news.neostrada.pl> <781a3ad8-10bb-42aa-939f-dc6c11efa783@googlegroups.com> <5c5df439$0$476$65785112@news.neostrada.pl> <0f221c6c-4754-475f-a906-373a1fba35db@googlegroups.com>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!fu-berlin.de!goblin1!goblin.stu.neva.ru!newsfeed.neostrada.pl!unt-exc-01.news.neostrada.pl!unt-spo-a-02.news.neostrada.pl!news.neostrada.pl.POSTED!not-for-mail
Subject: Re: [1/3 NTG] C - Optymalizacje wstawkami
Newsgroups: pl.comp.lang.asm
References: <30292520-12bd-49f0-b5ce-39c9af378a4c@googlegroups.com> <5c5b41d7$0$501$65785112@news.neostrada.pl> <781a3ad8-10bb-42aa-939f-dc6c11efa783@googlegroups.com> <5c5df439$0$476$65785112@news.neostrada.pl> <0f221c6c-4754-475f-a906-373a1fba35db@googlegroups.com>
From: "Bogdan (bogdro)" <bogdan@poczta.gazeta.pl>
Openpgp: preference=signencrypt
Date: Tue, 12 Feb 2019 21:23:02 +0100
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.5.0
MIME-Version: 1.0
In-Reply-To: <0f221c6c-4754-475f-a906-373a1fba35db@googlegroups.com>
Lines: 176
Message-ID: <5c632b27$0$488$65785112@news.neostrada.pl>
Organization: Telekomunikacja Polska
NNTP-Posting-Host: 89.64.39.243
X-Trace: 1550002983 unt-rea-a-02.news.neostrada.pl 488 89.64.39.243:61810
X-Complaints-To: abuse@news.neostrada.pl
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit