LINUXSOFT.cz
Username: Password:     
    CZ UK PL

> GCC vs. CLANG 4

Vliv kompilačních voleb na rychlost kódu

4.8.2010 00:00 | Radim Kolář | read 5706×

DISCUSSION   

Jak kompilační volby ovlivňují rychlost kódu

Rozhodl jsem se prozkoumat jaký vliv mají jednotlivé volby kompilátoru na rychlost výsledného kódu obou překladačů.

Jako test jsem použil Linuxový port BYTE benchmarku verze 2. Jde o mixovaný benchmark, kde jsou testovány jak floating point operace tak integer operace a taky je zohledněna práce s pamětí. Jednotlivé testy odpovídají reálným úlohám, nejsou to tedy čistě syntetické benchmarky.

Testování probíhalo pod operačním systémem FreeBSD 8.1 s GCC 4.2.1 20070719 (poslední GCC verze co byla pod GPLv2, novější jsou pod GPLv3). Jako typ CPU pro GCC byl použit Intel prescott, protože core2 architektura v době napsání překladače ještě nebyla. Tento systém běžel virtualizován ve VMware. Přesto doby běhu testů byly konzistentní a lišily se v důsledku virtualizace a zátěží způsobované ostatními aplikacemi až v třetí platné číslici, tedy v jednotkách procent, což víceméně odpovídá přesnosti měření i v nevirtualizovaném prostředí.

V první tabulce se podíváme na GCC. Použijeme 3 sady kompilačních voleb. První a nejpomalejší jsou default kompilační volby používané ve FreeBSD. Druhá sada odpovídá volbám použitým při překladu většiny linux distribucí a třetí sada odpovídá agresivnější -O3 optimalizaci, která se ale moc často v praxi nepoužívá protože naneštěstí GCC často generuje s touto volbou chybný kód nebo kód co je pomalejší než při -O2.

GCC

TEST-O2 -march=prescott -fno-strict-aliasing-O2 -fstrict-aliasing -fomit-frame-pointer -march=prescott-march=prescott -O3 -fomit-frame-pointer -funroll-loops
NUMERIC SORT10901139.3982.44
STRING SORT95.3196.14696.948
BITFIELD4.8991e+084.838e+084.8311e+08
FP EMULATION118.45122.67212.62
FOURIER188451881419202
ASSIGNMENT31.61733.29640.036
IDEA44364586.35680.9
HUFFMAN2116.42148.82321.8
NEURAL NET30.58329.2590.76538
LU DECOMPOSITION1447.71465.71612.5
MEMORY INDEX15.34115.58816.614
INTEGER INDEX14.60215.07517.929
FLOATING-POINT INDEX23.79523.5307.260
Větší číslo v tabulce znamená lepší výsledek.

Zásadní rozdíl mezi první a druhou volbou je volba -fomit-frame-pointer. Touto volbou uvolníme jeden registr za cenu toho, že nám nebude správně fungovat backtrace při debugování. Z crashdump core souborů se pak nedá spolehlivě zjistit v které funkci to spadlo. Registr navíc způsobí zvýšení výkonu protože se nemusí tak často přistupovat do pomalé paměti, ačkoliv na dnešních 64-bitových procesorech již není tak výrazné jako bývalo na 32-bitových Pentium II. Tam uvolnění toho registru znamenalo i 15% nárůst výkonu. Optimalizační volba -O3 přináší oproti -O2 určité, ačkoliv ne výrazné zlepšení. Jak je vidět z výsledků tak -O3 způsobilo u některých testů propad výkonu.

Clang

Stejné testy jaké byly provedené s GCC jsou nyní zopakovány s překladačem Clang. Optimalizujeme pro CPU core2, protože ho Clang zná, neboť se jedná oproti starému GCC o současný překladač.

TEST-O2 -march=core2-O2 -fstrict-aliasing -fomit-frame-pointer -march=core2-O3 -fstrict-aliasing -fomit-frame-pointer -march=core2
NUMERIC SORT1320.11362.91359.3
STRING SORT90.12290.6295.615
BITFIELD4.4253e+084.4415e+084.3236e+08
FP EMULATION217.42224.03223.89
FOURIER131551385913933
ASSIGNMENT30.23231.26130.735
IDEA49245128.95017.2
HUFFMAN18881788.41832.2
NEURAL NET28.48628.86128.937
LU DECOMPOSITION1405.51423.61392.6
MEMORY INDEX14.34014.54514.593
INTEGER INDEX17.78618.00217.997
FLOATING-POINT INDEX20.41120.94920.852

Z tabulky je vidět že Clang generuje pomalejší kód než GCC, ale rozdíl je okolo 10 procent. Clang s -O3 negeneruje oproti -O2 rychlejší kód. Důležitější ale je, že negeneruje v některých případech s -O3 narozdíl od GCC kód pomalejší, takže je volba -O3 u Clang bezpečnější než u GCC. Integer operace umí Clang optimalizovat stejně dobře jako GCC, mírně zaostává při práci s pamětí a ve floating point operacích.

Stack protector

V GCC existuje od verze 4.1 modul ProPolice, který dělá ochranu před buffer overflow útoky. Ochrana není stoprocentní, protože již byly objeveny postupy jak exploitnout i program takto chráněný, ale ne vždy se dá tento postup použít. Pro více informací doporučuji shlédnout prezentaci z projektu OpenBSD.

ProPolice modul byl již dlouho použit v OpenBSD a to dávno v době kdy ještě nebyl oficiální součástí balíku GCC. Druhou distribucí která ho nasadila bylo Ubuntu a pak následovalo DragonFly BSD a NetBSD a FreeBSD-8.

Zajímalo mne jak se tato ochrana projeví na výkonu. ProPolice má dva režimy ochrany v standardním chrání jen fukce volající alloca a funkce s bufferem větším než 8 bajtů. V druhém režimu chrání všechny funkce. Podle materiálů projektu OpenBSD v druhém režimu způsobí ProPolice zhruba 2% zpomalení.

TEST-fno-stack-protector-fstack-protector-fstack-protector-all
NUMERIC SORT1125.91130.51063.5
STRING SORT95.44796.09595.53
BITFIELD4.8104e+084.8367e+084.8313e+08
FP EMULATION121.45122.38108.15
FOURIER186701888918859
ASSIGNMENT33.20833.37532.583
IDEA4535.24536.54133.7
HUFFMAN2133.32243.22167.5
NEURAL NET30.01130.35430.796
LU DECOMPOSITION1443.514411436.6
MEMORY INDEX15.50715.59615.436
INTEGER INDEX14.92415.15814.021
FLOATING-POINT INDEX23.54923.71623.794

Z tabulky vidíme, že rozdíl mezi volbami -fno-stack-protector a -fstack-protector je pod hranicí chyby měření. U -fstack-protector-all již zpomalení pozorujeme. Zde ale závisí na použitém testu kolik je v něm voláno funkcí. Pokud se funkcí volá hodně, tak pokles může být až 20 procent.

Vliv CPU typu na rychlost

Překladače jazyka C umí optimalizovat program pro daný procesor. Default volba je optimalizovat pro Intel 386. Používat ji není příliš šťastné řešení protože Intel 386 byl vyroben v roce 1986 a dneska se s ním setkáte jen v embedded zařízeních a to ještě velmi velmi zřídka, protože Intely 386 nebyly nikdy oblíbené - místo nich se používala 32-bitová Motorola 68000.

Novější Intel procesory umí nejen nové instrukce, které dokáží nahradit několik starších instrukcí - tedy provedou se rychleji, ale umí zpracovávat i více instrukcí současně za dodržení určitých podmínek - instrukce musí být na sobě nazávislé a požadovaná jednotka procesoru zpracovávající příslušnou operaci musí být volná. Optimalizace kompilátory pro procesor tedy spočívají ve vhodném výběru a řazení instrukcí.

Trochu odlišná situace panuje ve světě RISC procesorů jako jsou UltraSPARC a POWER. Tam se stává že novější verze CPU již neumí z důvodů zjednodušení designu zpracovávat některé málo využívané staré instrukce. Tyto instrukce se pak softwarově emulují, stejně jako se v dobách Intelu 386 a 486SX emuloval matematický koprocesor. Emulace se buďto zabudovaná přímo v operačním systému, nebo se emuluje v userland knihovně, která se při spuštění starých programů načítá mechanizmem LD_PRELOAD.

TESTGCC i386GCC i686GCC prescott
NUMERIC SORT1062.21077.31139.3
STRING SORT95.86894.496.146
BITFIELD4.8498e+084.4164e+084.838e+08
FP EMULATION71.07122.31122.67
FOURIER184361885918814
ASSIGNMENT32.05533.18833.296
IDEA4077.84497.34586.3
HUFFMAN2073.72205.32148.8
NEURAL NET28.74331.35429.259
LU DECOMPOSITION1427.71438.31465.7
MEMORY INDEX15.39015.01315.588
INTEGER INDEX12.43914.87815.075
FLOATING-POINT INDEX23.03123.94723.530

U GCC platí že pokud vytváříme binární balíčky a nekompilujeme si program pro sebe tak máme kompilovat pro CPU i686 neboli Pentium II CPU. Nárůst výkonu s použitím optimalizace pro vyšší CPU již není tak významný a u zákazníků se mohou čas od času ještě najít starší počítače. Pentium II to sice nebude, ale Celerony kompatibilní s Pentiem III se zřídka zahlédnout dají.

TESTClang i386Clang i686Clang core2
NUMERIC SORT1365.11357.21354.1
STRING SORT89.64889.72289.786
BITFIELD4.4283e+084.4203e+084.4164e+08
FP EMULATION223.15222.61215.48
FOURIER145711456513620
ASSIGNMENT30.58430.331.004
IDEA5114.95108.35074.1
HUFFMAN1822.51815.31779.1
NEURAL NET10.710.66328.844
LU DECOMPOSITION345.92344.411420.3
MEMORY INDEX14.37314.32414.433
INTEGER INDEX18.06518.00417.728
FLOATING-POINT INDEX9.5499.52320.808

U Clangu je situace odlišná. Narozdíl od GCC zde prakticky žádný rozdíl v rychlosti není s vyjímkou floating point operací, které jsou při použití core2 výrazně rychlejší. Pravděpodobně je překladač realizuje pomoci rozšíření SSE.

Závěr

Překvapil mne všeobecně malý vliv optimalizace větší než -O2 na rychlost výsledného kódu. U Clangu je tento vliv ještě menší. S vyjímkou floating point operací bych řekl že je stěží měřitelný.

 

DISCUSSION

For this item is no comments.

Add comment is possible for logged registered users.
> Search Software
> Search Google
1. Pacman linux
Download: 4875x
2. FreeBSD
Download: 9063x
3. PCLinuxOS-2010
Download: 8561x
4. alcolix
Download: 10943x
5. Onebase Linux
Download: 9659x
6. Novell Linux Desktop
Download: 0x
7. KateOS
Download: 6240x

1. xinetd
Download: 2411x
2. RDGS
Download: 937x
3. spkg
Download: 4755x
4. LinPacker
Download: 9961x
5. VFU File Manager
Download: 3196x
6. LeftHand Mała Księgowość
Download: 7201x
7. MISU pyFotoResize
Download: 2806x
8. Lefthand CRM
Download: 3561x
9. MetadataExtractor
Download: 0x
10. RCP100
Download: 3117x
11. Predaj softveru
Download: 0x
12. MSH Free Autoresponder
Download: 0x
©Pavel Kysilka - 2003-2024 | mailatlinuxsoft.cz | Design: www.megadesign.cz