Article View: pl.comp.lang.asm
Article #2595Re: [1/3 NTG] C - Optymalizacje wstawkami
From: Bogdan (bogdro)
Date: Tue, 12 Feb 2019 20:23
Date: Tue, 12 Feb 2019 20:23
176 lines
7626 bytes
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-mailReferences:
<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