icc üti gcc-t

Végeztem egy apró tesztet gcc-4.1.2 és icc-10.0 (Build 20070809) között. A fordítókat saját sugárkövető programomon szoktam tesztelni, ami tekinthető CPU-intenzív alkalmazásnak. Mindkét fordítóval készítettem egy-egy futtathatót, és ezeket egymás után futtatva a következő eredményt kaptam:


sh-3.2$ time ./ray-g++-64 
15.21% Output has been written to tracement.tga
20.95% Output has been written to tracement.tga
25.98% Output has been written to tracement.tga
30.49% Output has been written to tracement.tga
41.46% Output has been written to tracement.tga
49.24% Output has been written to tracement.tga
53.96% Output has been written to tracement.tga
57.23% Output has been written to tracement.tga
61.35% Output has been written to tracement.tga
66.72% Output has been written to tracement.tga
80.49% Output has been written to tracement.tga
91.97% Output has been written to tracement.tga
98.14% Output has been written to tracement.tga
freeNode(0)

real	2m4.428s
user	8m12.798s
sys	0m0.803s
sh-3.2$ time ./ray-icpc-64 
21.14% Output has been written to tracement.tga
33.74% Output has been written to tracement.tga
52.56% Output has been written to tracement.tga
61.38% Output has been written to tracement.tga
80.88% Output has been written to tracement.tga
99.10% Output has been written to tracement.tga
freeNode(0)

real	0m55.223s
user	3m35.516s
sys	0m0.737s
sh-3.2$ 

Fordítási paraméterek:


g++ -O3 -march=nocona
icpc -fast

(64 bites kódról van szó, természetesen mindkét esetben.)

A C++ program négy szálon dolgozik, amit pthread-del old meg.
A futtató processzor egy Core 2 Quad (Q6600) 2,4GHz-en, 800MHz-es RAM-okkal.
Remélem nem hagytam ki semmi fontos információt.

Hozzászólások

gondolom van benne vektormuvelet rendesen, de kezzel irt asm kod meg nincs. a gcc defaultbol nem hasznal mmx/sse-t ehhez, az intel compiler igen. igy nem csoda az ekkora kulonbseg...

eleg sok kapcsoloja van mindket forditonak, celszeru lenne eloszor az adott forditot a sajat kapcsoloival "versenyeztetni" (megkeresni hogy pl.. a gcc cmilyen opciokkal forditja a leggyorsabb kodot). ezutan lehetne a 2 progit egymasnak engedni.

amugy gcc-bol van sokkal ujabb is. egy probat meger.

A'rpi

Van sok vektormuvelet, igen, viszont nincs asm egyaltalan.

Szerintem ebbol a 4.1.2-es gcc-bol mar nem lehet sokkal tobbet kihozni. Tudom, hogy nem egy mai verzio, de most azokat a forditokat teszteltem, amik reszei a Gentoo stabil aganak. Probaltam -msse{,2,3} kapcsolokat hozzadni, de pontosan ugyanazt a binarist forditotta mint azok nelkul. A manbol pedig kiderult, hogy a 64 bites gcc-ben ezek alapertelmezettek sok mas optimalizalo opcioval egyutt. Probaltam a -ftree-vectorize-ot is, de ettol sem lett gyorsabb. Meg fogom nezni az ujabb gcc-t is (4.3), mert abban van nehany igeretes dolog [ http://gcc.gnu.org/projects/tree-ssa/vectorization.html ].

Erdekes, hogy az inteles forditoval forditott valtozat majdnem annyival gyorsabb, mint amennyivel nagyobb meretu maga a futtathato :]

Az altalad megadott opciokkal gatlastalanul leteszteltem, bar hozza kell tenni par megjegyzest. Eloszor is az eredmenyek:


real	2m6.494s
user	8m17.208s
sys	0m1.207s

A megjegyzesek, melyek magyarazatul szolgalnak:
* -mfpmath=sse: benne van a manban, hogy x86-64 eseten sse a default erre az opciora, i386 eseten pedig 387, tehat mar az optimalisabb megoldas van kivalasztva esetunkben az opcio megadasa nelkul is.
* -ffast-math: implikalja a -funsafe-math-optimizations-t
* -funsafe-math-optimizations: ettol vartam volna, hogy valamit javul, de ugy latszik nem segitett sajnos ez sem. Raadasul a man azzal fenyeget hogy nem ajanlott, mert elronthatja az eredmenyt.

GCC oldalrol nagyon ugy fest, hogy csak az ujabb valtozatok szorongathatjak meg az intel compiler-t. Amugy az intel compiler is 2007 vegi, abbol nem tudom milyen lehet a legfrissebb... (majd megnezem igy a 10.0 utan a 10.1-et is)

Ha annyival nagyobb, akkor az ICC nem csinal alapbol loop unrollingot? (-funroll-loop gcc-ben)

Az ICC a manja szerint kifejezetten az -O1-nel irja, hogy nem csinal loop unrolling-ot, ebbol arra kovetkeztetek, hogy -O2-re mar csinal, en pedig a -fast kapcsolo megadasaval automatikusan -O3-at hasznalok. Tehat itt mar az ICC valoszinuleg csinal loop unrolling-ot. A GCC viszont alapbol nem, ezert kiprobaltam a -funroll-loops kapcsolot.
Mivel az inteles warningokat elkezdtem kozben kigyomlalni, kicsit megvaltozott a kod (gyorsabb lett), ezert most ujra kozlom az eredmenyeket roviden:


g++ -O3 -march=nocona
Forditas utan futtatva a progit:
real	1m56.431s
user	7m39.900s
sys	0m1.327s

g++ -O3 -march=nocona -funroll-loops
(Lathatoan nagyobb lett a futtathato binaris: 52955 -> 57051)
Forditas utan futtatva a progit:
real	1m57.429s
user	7m40.097s
sys	0m1.163s

icpc -fast
Forditas utan futtatva a progit:
real	0m48.189s
user	3m9.544s
sys	0m0.927s

-march mellett -mcpu -t is erdemes hasznalni, mert sokszor buta dolgokat tud kihozni nelkule.

Mindenesetre az impressziv, hogy az ICC mindenfele konfiguralas nelkul eleri ezt, de nem lehet, hogy cpuid alapjan tuningol az adott gepre? (ami termeszetesen cross compilingnal enyhen zavaro lenne)

De mindegy is, mert -march=nocone es -mtune=nocona utan is:


real	1m57.482s
user	7m39.607s
sys	0m1.273s

A man szerint amugy a -march implikalja az -mtune-t.

Egyebkent az nem teljesen igaz, hogy az intel forditonak nem adtam infot a processzorrol, mivel a -fast implikalja a -xT -O3 -ipo -no-prec-div -static opciokat, amik kozul az -xT kivalasztja a processzorok kozul azt, hogy "Intel(R) Core(TM)2 Duo processors, Intel(R) Core(TM)2 Quad processors, and Intel(R) Xeon(R) processors with SSSE3". Tehat a -fast egy rovid opcio, de elegge testre van szabva nekem :]

-static, akkor lehet a GCC alapbol PIC kodot fordit a gepedre, ami jelentosen csokkentheti a teljesitmenyt, felteve, ha hasznalsz libraryket.

Az -ipo szerintem a inliningon valtoztat, GCC-nel inline limit-et lehet valtoztatni. (-finline-functions -finline-limit=)

A -no-prec-div pedig FPU pontossagot csokkenti, erre is biztos van GCC-s alternativa. (-ffast-math)

Reference:
"
The -fast option enhances execution speed across the entire program by including the following options that can improve run-time performance:

-O3 (maximum speed and high-level optimizations)

-ipo (enables interprocedural optimizations across files)

-xT (generate code specialized for Intel(R) Core(TM)2 Duo processors, Intel(R) Core(TM)2 Quad processors and Intel(R) Xeon(R) processors with SSSE3)

-no-prec-div (disable -prec-div) where -prec-div improves precision of FP divides (some speed impact)

-static (statically link libraries during compilation)
"

Na megvan a lenyeg. Felbontottam a -fast opciot azokra, amiket helyettesit, es egyenkent elkezdtem leszedegetni. Arra jutottam, hogy az -ipo levetele utan 50 masodperccel megugrott a futas ido, ami ugye 2 perces teljes futasidonel eleg jelentos valtozas :] Szoval ennek az -ipo dolognak erdemes utana nezni.

Multi-file ip optimizations (-ipo) that includes:
- inline function expansion
- interprocedural constant propogation
- dead code elimination
- propagation of function characteristics
- passing arguments in registers
- loopinvariant code motion

Ebbol ket dolgot biztosan tud a GCC, az inline, amit fentebb irtam, es a pass-args-as-regs.

Utana neztem mindkettonek:
- inline: -finline-functions: az -O3 maga utan vonja. Azert probalkoztam explicit megadni, de nem segitett. Emellett megneztem a -finline-limit-et is, ami a man szerint default 600. Ezt felvittem 10000-re, de nem jott a varva vart javulas.
- pass-args-as-regs: ezt igy szo szerint nem talaltam meg. Talaltam helyette olyat, hogy -mregparm=n, es -msseregparm. Na ezt nem implikalta semmilyen eddigi mas opcio, viszont a man azt mondja, hogy az osszes hasznalt libnek ugyanigy kell leforditva lennie, ami azt jelenti, nem tud olyat a gcc-4.1.2, hogy csak hazon belul (modulon belul) hasznal regparmot, ami talan nem is lenne olyan rossz otlet... Azert kiprobaltam, de sajnos az -mregparm=n (n=0..3) segfaultos programot forditott. Az -msseregparm mar nem szallt el, viszont gyorsabb sem lett a program tole.

core2-re a gcc-4.3 tud optimalizálni. 4.1 csak PentiumD-re tud

gcc-4.3


[snip]
           i386 and x86-64 Options -mtune=cpu-type  -march=cpu-type
           -mfpmath=unit -masm=dialect  -mno-fancy-math-387 -mno-fp-ret-in-387
           -msoft-float -mno-wide-multiply  -mrtd  -malign-double
           -mpreferred-stack-boundary=num -mcld -mcx16 -msahf -mrecip -mmmx
 -->       -msse  -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -msse4a
           -m3dnow -mpopcnt -mabm -msse5 -mthreads  -mno-align-stringops
           -minline-all-stringops -mpush-args  -maccumulate-outgoing-args
           -m128bit-long-double -m96bit-long-double  -mregparm=num
           -msseregparm -mveclibabi=type -mpc32 -mpc64 -mpc80 -mstackrealign
           -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs
           -mcmodel=code-model -m32  -m64 -mlarge-data-threshold=num
           -mfused-madd -mno-fused-madd
[snip]

debian gnu/linux @ linux-2.6.26-rc8-git2 | patch
info