🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

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

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

#2592
From: DMR
Date: Fri, 08 Feb 2019 17:31
101 lines
6862 bytes
To była cisza przed burzą... :-)
Dzięki za odpowiedź!



> To jest tzw. context switch i ma on być niewidzialny dla każdego z
> procesów. I to procesor/system ma zadbać, aby tak było.
> Z tego, co na szybko znalazłem w podręczniku do AMD64 (tom 2, System
> Programming, rozdział 1.7.1 Hardware Multitasking), w trybach "legacy"
> (czyli innych niż 64-bitowy Long Mode - rzeczywisty, chroniony, ...)
> jest sobie tzw. Task State Segment i przy przełączaniu się na inne
> zadanie, procesor zapisuje stan bieżącego, po czym przywraca, gdy to
> zadanie/proces znów stanie się bieżącym/aktywnym.


No właśnie. Przypuszczałem, że między procesami jest to jakoś tak załatwione.



> __asm__ ("fsincos;" : "=t" (*c), "=u" (*s) : "0" (x) : "st(7)");


Ta składnia jest koszmarna, ale domyślam się, że stanowi ona pewnego rodzaju ochronę przed "wtargnięciem" w ciało programu.
Kompilator ma prawo przecież robić jakieś swoje założenia, a nie może być tak, że w połowie wchodzimy jak Ruski do baru i zaczynamy mu przestawiać rejestry.
Tyle, że jest problem - jak my nie chcemy słuchać kompilatora, to on też może się wypiąć i pomimo naszych prób optymalizacji całość wyjdzie gorzej niż przedtem...
Na szczęście koprocesor ze swoją stosową strukturą wydaje się pod tym względem raczej "bezpieczny", ale CPU to już inny level.

Okazuje się, że używanie "prostych" wstawek, to nie jest wcale trywialny problem.



> Wkrótce faktycznie ponoć ma już nie być x87 i wszystko ma być liczone
> za pomocą SSE/AVX itp.


Ale w sumie - co mnie właściwie obchodzi, który tranzystor liczy mi sinusa? :-)



> I też obstawiałbym, że instrukcja sprzętowa powinna być szybsza niż
> cokolwiek, co jest programowe.


Tego nawet nie zakładałem. Po prostu sugerowanie, że bezpośrednie odwołanie do FPU może działać wolniej, niż rozwiązanie pośrednio odwołujące się do tego samego FPU nie grało mi z powodów "cybernetycznych".
Mea culpa - nie przestudiowałem tych funkcji. Myślałem, że gość wie co robi... ;-)



> Na przykład, w moim glibc (2.27) kod
> sincos() jest dość złożony, bo sprawdza jeszcze błędy i normalizuje
> parametry, jeśli trzeba


Ta instrukcja jest zdaje się bardzo tolerancyjna, jeśli chodzi o parametry?
Zdaje się, że przyjmuje od -2^63 do 2^63
Kto by zresztą tyle tam wpisywał - ważne, że podanie mu -0.333 nie spowoduje wyświetlenia pozdrowień od Billa Gatesa... ;-)


A skoro już przy rozwiązaniach sprzętowych stanęliśmy...

Ostatnio musiałem napisać procedurę, która z pliku tekstowego wczytanego jako blok bajtów "wyparsuje" odpowiednie dane, ale okazało sie, że standardowe funkcje strtol() i strtod() zachowują się wyjątkowo dziwacznie w stosunku do deklarowanej logiki ich działania (z zagadkowych przyczyn nie kończyły działania na endptr, tylko wyłaziły dalej szukając zera, a przy okazji zawieszając program...).
Potrzeba matką wynalazków, więc szybko spłodziłem odpowiedniki, co doprowadziło mnie niemal do euforii, bo okazało się, że "moje" funkcje działają KILKADZIESIĄT razy szybciej od standardowych. A że pliczek miał 87 megabajtów... ;-)

Skoro tak, to - co było do przewidzenia - szybko zajawiłem, żeby sprawić sobie własny komplet jak najlepszych procedur konwertujących tekst <-> liczby.
Z tekstów na liczby poszło gładko, tym bardziej, że mnożenie przez 10 można zastąpić sumą iloczynów przez 8 i 2.
Za to w druga stronę... też poszło gładko. ;-)
Przynajmniej w tym sensie, że udało się uzyskać kilkukrotne przyśpieszenie względem funkcji standardowych.

W odpowiedniku itoa() znalazł się taki fragment (z dokładnością do zera):

*cptr = 0x0;
while (iValue)
{
    *--cptr = char(iValue % 10) | '0';
    iValue /= 10;
}

Niby wszystko gra, ale każdego szanującego się zboczeńca-perfekcjonistę w oczy kłuje to modulo, a za chwilę dzielenie przez 10.
Kombinowałem, żeby resztę uzyskać z ilorazu, z tymi shiftami, ale wyniki uzyskałem bardzo podobne, z tendencją lekko gorszą.

Coś mi się we łbie kolebało z tym modulo i przy okazji poszukiwań natrafiłem na stronę http://bogdro.evai.pl/ ;-)

Faktycznie, instrukcja DIV liczy iloraz i modulo za jednym zamachem, przerżnąłem więc ten kod i... d*pa! :-(
Wyszło dwa razy wolniej.

Tego już w ogóle nie rozumiałem, więc szybko nauczyłem się instrukcji -S, żeby GCC wypluł mi kod asemblera.
I, patrz Pan, nie było tam niczego choćby podobnego do DIV...

Jako, że nie byłem pewny, czy tu ktokolwiek zagląda, swojemu rozgoryczeniu dałem upust na pl.comp.programming, wklejając "publiczny" kod:
https://godbolt.org/z/Xs117J

Jakaś dobra dusza potwierdziła moje mgliste domysły, że chodzi o użycie dużego "quasi-współczynnika", który tam się potem odpowiednio "przekręcą", a potem shift i tak dalej.
Postudiuję ten temat, zwłaszcza że z daleka śmierdzi mi jakimś przepełnieniem, ale nie jestem przekonany, czy da się tu uzyskać jakieś przyśpieszenie względem kodu w C.
A sprawa jest kluczowa, bo jest to też fragment konwersji liczb zmiennoprzecinkowych na tekst.
Na razie rozdzielam część rzeczywistą i ułamkową konwersją na int i odejmowaniem/mnożeniem, ale może tu da się coś jeszcze ugryźć - zależy mi tylko na konwersji w "zafiksowanym" formacie RRRRRRRR.FFFFFFFF

Tu się kolega na ten temat mocno produkuje:
https://github.com/miloyip/dtoa-benchmark


No, to się wygadałem. :-)
Technical Details
Message-ID: <781a3ad8-10bb-42aa-939f-dc6c11efa783@googlegroups.com>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!goblin1!goblin.stu.neva.ru!k10no307258itk.0!news-out.google.com!v141ni270ita.0!nntp.google.com!q69no307789itb.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail
References: <30292520-12bd-49f0-b5ce-39c9af378a4c@googlegroups.com> <5c5b41d7$0$501$65785112@news.neostrada.pl>

Show Full Headers
Complete Article Headers
X-Received: by 2002:a24:1311:: with SMTP id 17mr5543363itz.20.1549647097619;        Fri, 08 Feb 2019 09:31:37 -0800 (PST)
X-Received: by 2002:aca:c703:: with SMTP id x3mr53530oif.5.1549647097144; Fri, 08 Feb 2019 09:31:37 -0800 (PST)
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!goblin1!goblin.stu.neva.ru!k10no307258itk.0!news-out.google.com!v141ni270ita.0!nntp.google.com!q69no307789itb.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail
Newsgroups: pl.comp.lang.asm
Date: Fri, 8 Feb 2019 09:31:36 -0800 (PST)
In-Reply-To: <5c5b41d7$0$501$65785112@news.neostrada.pl>
Complaints-To: groups-abuse@google.com
Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=80.238.104.22; posting-account=FE4hoAoAAADKg8EtnA4bEyQiJf7iqAgV
NNTP-Posting-Host: 80.238.104.22
References: <30292520-12bd-49f0-b5ce-39c9af378a4c@googlegroups.com> <5c5b41d7$0$501$65785112@news.neostrada.pl>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <781a3ad8-10bb-42aa-939f-dc6c11efa783@googlegroups.com>
Subject: Re: [1/3 NTG] C - Optymalizacje wstawkami
From: DMR <mezzogm@gmail.com>
Injection-Date: Fri, 08 Feb 2019 17:31:37 +0000
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit