Zdroják v c, a v pascalu
Pro testy jsem použil pentium/100 na 120, 512KB burst cache pod
dosem s himemem. Borlandí kompiler vlastním ve verzi 2.0 (já vím, že
verze x.y je nejméně pětkrát rychlejší) a proto jsem udělal také
test pod borland pascalem 7.0. Snažil jsem se všechny kompilery
donutit k co nejlepším výsledkům. U bc to bylo snadné. Ať jsem
měnil, co měnil pořád byl čas stejný. U paskalu jsem zapnul
koprocesor, 286 instrukce a vypnul kontroly. Zdroják jsem se snažil
napsat co nejoptimálněji. To pomáhá borlandům, protože všechny změny
(úprava výpočtů, obrácení smyčky..) nezměnily výsledný čas. Ve škole
jsem potom dodělal daší testy na ostatních kompilerech.
No abych nezdržoval tady je tabulka:
+----------+------------------------------------+------------------+
|kompiler |optiony | Smyček za sekundu|
+----------+------------------------------------+------------------+
|gcc2.6.3 |-O3 -ffast-math -m486 | 4 233 641 |
| |-fomit-frame_pointer -funroll-loops | |
|gcc2.7.2.1|-O3 -ffast-math -m486 | 4 149 377 |
| |-fomit-frame_pointer -funroll-loops | |
|pgcc2.7.2 |-O6 -ffast-math -m586 -frisc | 3 436 426 |
| |-fomit-frame_pointer -funroll-loops | |
|gpc2.0 |-O3 -ffast-math -m486 | 3 433 962 |
| |-fomit-frame_pointer -funroll-loops | |
|wc10.0 | -7 -5 -ol -ol+ -om -op -or -ot -fp5| 2 222 222 |
| | -fpi87 | |
|wc10.0 | -5 -7 | 2 217 249 |
|plan9 |<v IDE-586,speed+size optim.> | 1 623 376 |
|vc1.0 |<v IDE-586,speed+size optim.> | 1 531 393 |
|bc4.5 |<v IDE-486,fastest executable ...> | 1 455 604 |
|bc3.1 |<v IDE-386,fastest executable ...> | 1 433 070 |
|gcc2.7.2.1| (bez optimalizací) | 1 281 348 |
|gpc2.0 | (bez optimalizací) | 1 109 756 |
|bp7.0 | | 901 713 |
|tc2.0 |-1 -f87 -O -r -Z -G -a -mt | 846 511 |
|bc4.0 |<v IDE-486,speed optimizations...> | 755 857 |
|bc2.0 | | 716 535 |
|bc2.0 |-G -O -2 -Z -r | 716 535 |
|tc2.0 | | 546 546 |
|bc4.0 |<v IDE-486,speed+size optim.> | -3.6676456... |
+----------+------------------------------------+------------------+
Vc znamená visual C++ 1.0. Gcc 2.6.3 bylo použito v DJGPP 1.0.
Wc znamená watcom C 10.0. Pgcc je experimental gcc pro pentium od
Intelu. Plan9 je kompiler ve stejnojmeném OS (který je mimochodem
také free a velice zajímavý) Ještě zajímavější je, že tento kompiler
ma pouze cca 200KB a tak je suveréně nejjednodušší. Gpc je GNU
pascal compiler
Jak je vidět borlandí C je 5.77krát pomalejší. Pascal je na tom
o něco lépe tedy 4.58 krát. Asemblerový zdroják se mi podařilo
získat jenom z borlandího C a gcc. Napočítal jsem 20 instrukcí v
interní smyčce u GNU a 35 u borlandů. Novější Borlandi se celkem
slušně vylepšili. Ve verzi 4.5 je už "poze" 2.6krát pomalejší.
Naprosto mě ale překvapil test ve verzi 4.0. Tam se zpomalil a po
zapnutí optimizací na velikost se program natolik zrychlil, že
získal záporný čas. Nevím, jak někdo může tak zabugovaný compiler
pustit do světa. Další zajímavá věc ohledně Borlandů je to, že ve
verzi 3.1 byl .exe dlouhý 14KB, ve verzi 4.0 už 48KB a v 4.5 celých
61KB.V posledních borlandech jsem napočítal 34 instrukcí v interní
smyčce. FractalZoom, který má smyčku v assembleru se pyšní 22
instrukcema a jeho test říka 3.9 milionů smyček za sekundu. Zajímavé
je, že staré gcc vyšlo z testu o 2.2% lépe. Ale bude to spíš chyba
měření, protože interní smyčka je stejná. Naprosto mě zklamalo
watcom C. Měl jsem ho zafixované jako velmi dobrý kompiler ale přes
to, že narozdíl od gcc podporuje pentium, scheluding instrukcí pro
pentium, a fp optimalizace pro pentia bylo téměř dvakrát pomalejší.
Pro GNU pascal jsem musel zdroják poupravit tak, aby používal
céčkovou fci clock pro testování času a __long__ integer místo
integeru protože normální 16 bit integery jsou strašně pomalé.
Přesto ale je GNU pscal ze záhadných důvodů pomalejší než C.
Asm z gcc, a borlandu
Aby se neřeklo, že se starám pouze o MS-DOS provedl jsem ještě testy
na sunech a siliconech gcc versus kompiler dodávaný s OS. Tady jsou
výsledky:
SUN
+----------+------------------------------------+------------------+
|kompiler |optiony | Smyček za sekundu|
+----------+------------------------------------+------------------+
|gcc2.7.0 |-O3 -ffast-math -fomit-frame-pointer| 925 925 |
| | -funroll-loops | |
|cc |-O | 840 336 |
+----------+------------------------------------+------------------+
SGI
+----------+------------------------------------+------------------+
|kompiler |optiony | Smyček za sekundu|
+----------+------------------------------------+------------------+
|gcc2.7.0 |-O3 -ffast-math -fomit-frame-pointer| 2 688 172 |
| | -funroll-loops | |
|cc |-O | 2 096 436 |
+----------+------------------------------------+------------------+
Musím říct, že výsledek mě OPRAVDU překvapil. Výsledky jsou
mnohem vyrovnanější, než u dosových kompilerů. Napadly mě
následující vysvětlení:
1) GCC generuje horší kód na neintelových platformách
2) SUN a SGI odělali tak dobrý kompiler, že mu všechny komerční
DOSové nesahají ani po kotníky
3) Sparc a Mips mají jednodušší práci s floating point registry
a proto generování kodu pro ně je jednodušší.
Proto jsem udělal další test. Nahradil jsem long double za int.
Teď je už celá matematika jednoduchá i na intelu a udělal další
test:
+----------+------------------------------------+------------------+
|kompiler |optiony | Smyček za sekundu|
+----------+------------------------------------+------------------+
|pgcc2.7.2 |-O6 -ffast-math -frisc | 3 267 245 |
| |-fomit-frame_pointer -funroll-loops | |
|gcc2.7.2.1|-O3 -ffast-math -m486 | 3 250 000 |
| |-fomit-frame_pointer -funroll-loops | |
|wc10.0 |-fpi87 -fp5 -5 -7 -ol -ol+ -om -on | 3 246 753 |
| |-or -ot | |
|wc10.0 |-5 -7 | 3 194 888 |
|plan9 | | 2 973 176 |
|gpc2.0 |-O3 -ffast-math -fstrength_reduce | 2 888 888 |
| |-fomit-frame_pointer -funroll-loops | |
|gcc2.7.2.1| (bez optimalizace) | 2 394 736 |
|gpc2.0 | (bez optimalizace) | 2 219 512 |
|bc2.0 |-G -O -2 -Z -r | 2 166 666 |
|bp7.0 | | 1 956 947 |
|tc2.0 |-1 -O -r -G -Z -a -mt | 892 156 |
|tc2.0 | | 846 511 |
+----------+------------------------------------+------------------+
Výsledek mě opět překvapil. Zpomalení u gcc jsem nečekal. Po
prozkoukání assembleru jsem zjistil, že tam není nic, co bych byl
schopný nějak radikálně zoptimalizovat - všechno je v registrech a
smyčka se zkrátila na 14 instrukcí snad jenom ty dva skoky, ale když
jsou tu dvě podmínky a ve floatng point verzi byly taky.... Pentium
má mul pomalejší než fmul a tak se výsledek asi dal očekávat.
Samozdřejmě to neplatí o 486. Gcc s experimentálníma pentiovýma
patchema sice smyčku trochu přerovná ale pomůže to jen o cca 1%.
Pořád je ale Borland o hodně pomalejší. To, že gcc by generovalo
na mipsech horší kod se mi zdá nepravděpodobné, protože optimizery
jsou z velké části nezavislé na architektuře. a tak si myslím, že to
bude tak půl na půl mezi lepší architekturou a tím že lidi kolem
UNIXu lépe programují.
Myslím, že testy mluví samy za sebe a ukazují, že tady GNU
odvedlo opravdu dobrou práci. Psaní rutin v assembleru, aby byly
rychlejší už skoro nemá smysl. Je to důvod, proč programy v linuxu
bývají rychlejší (klasický příklad je doom). Má to bohužel i
nevýhodu. Přežhavené stroje často programy kompilované pomocí gcc
nevydrží (moje 486DX2 normálně pracující v pokojové teplotě se při
kompilaci jádra zahřeje tak, že na ní neudržím ruku). Lidi si
často myslí, že je to chyba programu. Taky proces kompilace je
docela složitý a tak to kompileru chvíli trvá.
Poslední dost důležitá věc je to, že oproti Borlandum je gcc
téměř bez bug. Za asi 6 let, co na něm dělám jsem narazil asi na tři
problémy. Jinak vždycky všechno fungovalo.
výheň