View Full Version : Η αξία των development tools
DarthMoul
29-10-2004, 17:04
Μέχρι τώρα, σε πολλά threads, έχω αναφερθεί στα devtools και στην αξία τους. Γι αυτόν τον λόγο άνοιξα αυτό το thread. Με ένα απλό παράδειγμα και σύγκριση δύο μηχανών και δύο διαφορετικών compiler, θα δείξω πόσο σημαντικός είναι ο ρόλος τους. Πριν αρχίσω τις συγκρίσεις θα ήθελα να διευκρινήσω ότι devtool δεν είναι μόνο ο compiler αλλά επίσης και ο profiler και ο debuger. Ο compiler όμως είναι ο σημαντικότερος όλων και γι αυτόν τον λόγο θα σταθώ σε αυτόν.
DarthMoul
29-10-2004, 17:11
Θα πάμε λοιπόν να συγκρίνουμε δύο μηχανές. Η μία είναι ένας dual opteron στα 2.2 GHz και η άλλη ένας dual Itanium2 στα 1.4 GHz. Αυτά τα συστήματα, όπως ξέρετε οι περισσότεροι, δεν επιδέχονται παρεμβάσεις στο hardware όπως το overclocking. Οι μετρήσεις θα γίνουν με την ακριβή σύνθεση των κατασκευαστών τους (είναι επώνυμα μηχανήματα) και φορτίο στο 50%, ώστε να δούμε την συμπεριφορα τους κάτω από όσο το δύνατόν γίνεται πραγματικές συνθήκες.
Το πρόγραμμα που θα χρησιμοποιήσω είναι η multithreaded έκδοση του pitest που είχαμε δει εδώ: http://www.pctechnology.gr/vbull/vb/showthread.php?t=504
Και οι compilers θα είναι ο gcc από την GNU και ο icc από την Intel.
DarthMoul
29-10-2004, 17:16
Εδώ έχουμε τον gcc που θα χρησιμοποιήσουμε στον Itanium2:
~/pitest-ia64$ gcc -v
Reading specs from /usr/lib/gcc-lib/ia64-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=ia64-redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-42)
Διαβάζοντας το manual βλέπουμε πως μας ενδιαφέρουν 2 παράμετροι που αφορούν την ia64 αρχιτεκτονική.
-O3 Optimize yet more. -O3 turns on all optimizations specified by -O2
and also turns on the -finline-functions and -frename-registers
options.
-minline-divide-min-latency
Generate code for inline divides using the minimum latency algo-
rithm.
DarthMoul
29-10-2004, 17:31
Το -Ο3 είναι το υψηλότερο επίπεδο βελτιστοποίησης γενικής χρήσης που μπορεί να κάνει ο gcc. Με λίγα λόγια, κάνει εκτεταμένη χρήση της assembly αντικαθιστώντας function calls τα οποία δουλεύουν με long jumps και προκαλούν καθυστερήσεις. Επίσης κάνει register renaming στην x86 πλατφόρμα, αλλά εδώ δεν μας αφορά. Αφορά παρακάτω τον Opteron.
Για να εξηγήσουμε το -minline-divide-min-latency θα πρέπει να πούμε δύο λόγια για τον Itanium. Η FPU του itanium δεν έχει εντολή για διαίρεση πραγματικών αριθμών, όπως ο x86 και όλοι οι risc. Η δουλειά αυτή γίνεται από το software, δηλαδή από τον compiler. Η συνιστώμενη μέθοδος από την Intel είναι η μέθοδος Newton/Raphson σε βάθος τριών επιπέδων. Η μέθοδος αυτή μπορεί να υλοποιηθεί με δύο αλγοριθμους. Ο ένας είναι αλγόριθμος ελάχιστης καθυστέρησης (minimum latency), δηλαδή ελαχιστοποιεί τα stalls και αποφεύγει τα bottlenecks. Ο δεύτερος, έχει περισσότερα stalls αλλα αξιοποιεί καλύτερα το memory bandwidth. Επειδή το πρόγραμμα κάνει ελάχιστες προσπελάσεις στην μνήμη, και δουλεύει περισσότερο με registers, μας συμφέρει να διαλέξουμε τον αλγόριθμο με το minimum latency.
DarthMoul
29-10-2004, 17:38
~/pitest-ia64$ cat /proc/cpuinfo
processor : 0
vendor : GenuineIntel
arch : IA-64
family : Itanium 2
model : 1
revision : 5
archrev : 0
features : branchlong
cpu number : 0
cpu regs : 4
cpu MHz : 1396.227000
itc MHz : 1396.227000
BogoMIPS : 2088.76
processor : 1
vendor : GenuineIntel
arch : IA-64
family : Itanium 2
model : 1
revision : 5
archrev : 0
features : branchlong
cpu number : 0
cpu regs : 4
cpu MHz : 1396.227000
itc MHz : 1396.227000
BogoMIPS : 2088.76
~/pitest-ia64$ gcc -D_REENTRANT -O3 -minline-divide-min-latency pitest-mt.c -o pitest-mt -lpthread
~/pitest-ia64$ time ./pitest-mt 9 2
Thread #0 start from: 1 ends to: 1000000000
Thread #1 start from: 1000000001 ends to: 2000000000
9 digits precision Pi:3.141592653
18.312u 0.000s 0:09.17 199.6% 0+0k 0+0io 87pf+0w
9.17 seconds ο Itanium2 με gcc
circular
29-10-2004, 17:42
Πολύ ενδιαφέρον thread, DarthMoul. Φαντάζομαι πως θα κάνεις και κάποια σύγκριση με τον compiler της Intel?
[reason: μολις ειδα οτι ανέφερες τον icc... :083: :053:]
DarthMoul
29-10-2004, 17:50
Και έδώ είναι ο gcc που θα χρησιμοποιήσουμε στον Opteron:
lucast70/pitest-athlon> gcc -v
Reading specs from /usr/lib64/gcc-lib/x86_64-suse-linux/3.3.3/specs
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --enable-languages=c,c++,f77,objc,java,ada --disable-checking --libdir=/usr/lib64 --enable-libgcj --with-gxx-include-dir=/usr/include/g++ --with-slibdir=/lib64 --with-system-zlib --enable-shared --enable-__cxa_atexit x86_64-suse-linux
Thread model: posix
gcc version 3.3.3 (SuSE Linux)
Εδώ χρησιμοποιώ νεότερη έκδοση του gcc που περιλαμβάνει και opteron specific optimizations.
Διαβάζοντας το manual βλέπουμε πως υπάρχουν δύο παράμετροι που μας αφορούν:
-mcpu=<cpu type>
k8, opteron, athlon64, athlon-fx
AMD K8 core based CPUs with x86-64 instruction set
support. (This supersets MMX, SSE, SSE2, 3dNOW!,
enhanced 3dNOW! and 64-bit instruction set extensions.)
Και την γνωστή από πριν γενικής χρήσης -Ο3. Δεν νομίζω πως χρειάζεται να εξηγήσω κάτι παραπάνω εδώ.
DarthMoul
29-10-2004, 18:05
lucast70/pitest-athlon> cat /proc/cpuinfo
processor : 0
vendor_id : AuthenticAMD
cpu family : 15
model : 5
model name : AMD Opteron(tm) Processor 248
stepping : 8
cpu MHz : 2191.571
cache size : 1024 KB
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov
pat pse36 clflush mmx fxsr sse sse2 syscall nx mmxext lm 3dnowext 3dnow
bogomips : 4308.99
TLB size : 1088 4K pages
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management: ts ttp
processor : 1
vendor_id : AuthenticAMD
cpu family : 15
model : 5
model name : AMD Opteron(tm) Processor 248
stepping : 8
cpu MHz : 2191.571
cache size : 1024 KB
fpu : yes
fpu_exception : yes
cpuid level : 1
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov
pat pse36 clflush mmx fxsr sse sse2 syscall nx mmxext lm 3dnowext 3dnow
bogomips : 4374.52
TLB size : 1088 4K pages
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management: ts ttp
lucast70/pitest-athlon> gcc -D_REENTRANT -O3 -mcpu=k8 pitest-mt.c -o pitest-mt -lpthread
lucast70/pitest-athlon> time ./pitest-mt 9 2
Thread #0 start from: 1 ends to: 1000000000
Thread #1 start from: 1000000001 ends to: 2000000000
9 digits precision Pi:3.141592653
8.170u 0.000s 0:05.59 146.1% 0+0k 0+0io 151pf+0w
5.59 seconds o Opteron με τον gcc
DarthMoul
29-10-2004, 18:17
Για να δούμε κάποια πράγματα. Ο Itanium έχει συχνότητα 1.4 GHz και ο Opteron 2.2 GHz. Δηλαδή η συχνότητα του Itanium είναι 63% αυτής του Opteron. Στα αποτελέσματα τώρα βλέπουμε ότι τα 5.59'' του Opteron είναι το 60% του χρόνου που χρειάστηκε ο Itanium, ο οποίος είναι 9.17''. Ακόμα και με μία απλή μεθοδο των τριών θα δούμε ότι το 1:1 scaling θα μας έδινε τον Itanium στο 9.27''.
Συνεπώς ο gcc παράγει κώδικα με πάρα πολύ καλό frequency scaling και δεν αδικεί ούτε τον Opteron, ούτε τον Itanium. Αμφιβάλλω αν άλλος multiplatform compiler έχει τόσο καλή συμπεριφορά, ακόμα και σε τόσο απλά προγράμματα.
DarthMoul
29-10-2004, 18:37
H Intel για τους δικούς της επεξεργαστές έχει βγάλει μία σειρά από devtools μεταξύ των οποίων και o icc. Αυτα είναι και τα προτεινόμενα εργαλεία από τον κατασκευαστή και με αυτά υποστηρίζει τους επεξεργαστές του.
Εδώ είναι ο icc που θα χρησιμοποιήσουμε στον Itanium:
lucast70/pitest-ia64> icc -v
Version 8.1
Και διαβάζοντας το manual βλέπουμε πως χρειαζόμαστε τις παρακάτω παραμέτρους:
-O3 Enable -O2 optimizations and in addition,
enable more aggressive optimizations such as
loop and memory access transformation. The
-O3 optimizations may slow down code in some
cases compared to -O2 optimizations. Recommended
for applications that have loops with
heavy use of floating point calculations and
process large data sets.
-mcpu=<cpu>
itanium2 -- (i64 only) Optimize for Intel
Itanium 2 processor.
-IPF_fp_speculation<mode> (i64 only)
Enable floating point speculations with the
following <mode> conditions:
fast -- Speculate floating point operations
safe -- Speculate only when safe
strict -- Same as off
off -- Disables speculation of floating-point
operations
-IPF_fp_relaxed[-] (i64 only)
Enable [disable] use of faster but slightly
less accurate code sequences for math functions,
such as divide and square root.
DarthMoul
29-10-2004, 18:46
Τις παραμέτρους -O3 και -mcpu τις είδαμε και στον gcc. Την ίδια λειτουργία έχουν και στον icc.
To IPF_fp_speculation αλλάζει το instruction scheduling ώστε να επιταχύνει τις πράξεις πραγματικών αριθμών. Μας συμφέρει να την χρησιμοποιήσουμε αφού το πρόγραμμα μας δουλεύει σχεδόν αποκλειστικά με floats.
Το IPF_fp_relaxed μειώνει την ακρίβεια των πραγματικών αυξάνοντας την ταχύτητα.
Δεν χρησιμοποιήσαμε τέτοιες παραμέτρους στον gcc γιατί απλά δεν υπάρχουν. Ο Gcc είναι ένας πάρα πολύ καλός γενικής χρήσης multiplatform compiler που παράγει αξιόπιστο και γρήγορο κώδικα για 56 πλατφόρμες. Αλλά δεν είναι ο compiler του Itanium. Συνεπώς δεν έχει καμμία υποχρέωση να υποστηρίξει και τα πιο εξηζητημένα χαρακτηριστικά του.
DarthMoul
29-10-2004, 18:52
lucast70/pitest-ia64> cat /proc/cpuinfo
processor : 0
vendor : GenuineIntel
arch : IA-64
family : Itanium 2
model : 1
revision : 5
archrev : 0
features : branchlong
cpu number : 0
cpu regs : 4
cpu MHz : 1396.227000
itc MHz : 1396.227000
BogoMIPS : 2088.76
processor : 1
vendor : GenuineIntel
arch : IA-64
family : Itanium 2
model : 1
revision : 5
archrev : 0
features : branchlong
cpu number : 0
cpu regs : 4
cpu MHz : 1396.227000
itc MHz : 1396.227000
BogoMIPS : 2088.76
lucast70/pitest-ia64> icc -D_REENTRANT -O3 -IPF_fp_fast -IPF_fp_relaxed -mcpu=itanium2 pitest-mt.c -o pitest-mt -lpthread
lucast70/pitest-ia64> time ./pitest-mt 9 2
Thread #0 start from: 1 ends to: 1000000000
Thread #1 start from: 1000000001 ends to: 2000000000
9 digits precision Pi:3.141592653
3.586u 0.000s 0:01.80 198.8% 0+0k 0+0io 89pf+0w
1.80 seconds o Itanium με icc
Ο icc παράγει κώδικα που τρέχει στο 1/5 του χρόνου του gcc.
Περιμένω να το κουβεντιάσουμε
DarthMoul
31-10-2004, 19:28
Για να μην περιμένω άδικα τα σχόλια σας, θα κάνω εγώ τα δικά μου :D
Ο gcc δεν είναι optimized compiler για κανέναν από τους δύο επεξεργαστές. Πάραγει καλύτερο κώδικα για x86 απ'ότι για οποιαδήποτε άλλη πλατφόρμα, αλλά έχω δει και περιπτώσεις που η microsoft C παράγει ελαφρώς καλύτερο. Άλλωστε ο gcc ως δυνατό χαρακτηριστικό έχει την φορητότητα και όχι την ταχύτητα.
Όταν κάναμε την δοκιμή με τον gcc και οι δύο CPU συμπεριφέρθηκαν πολύ καλά, σύμφωνα πάντα με την αρχιτεκτονική και την συχνότητα τους. Και όπως δείξαμε πριν, ο gcc παρήγαγε ίδιας ποιότητας κώδικα και για τους δύο. Αν το πρόγραμμα ήταν πιο μεγάλο και περίπλοκο, όπως είναι συνήθως τα προγράμματα που χρησιμοποιούμε, ο Itanium θα ήταν λιγάκι αδικημένος.
Τελικά με την χρήση του icc, το αποτέλεσμα που έδωσε ο Itanium, παρόλη την υστέρηση σε ταχύτητα, ήταν σχεδόν τρεις φορές καλύτερο από αυτό του Opteron. Για όσους δεν το γνωρίζουν, ο Opteron έχει την καλύτερη FPU ανάμεσα στους x86.
Αφού στο πρόγραμμα δεν είχαμε κάνει καμμία μεταβολή, και το φορτίο του συστήματος δεν άλλαξε, ο μόνος παράγοντας που προκάλεσε την διαφόρά είναι ο compiler.
Στο ερώτημα, αν ο Opteron θα μπορούσε να πάει καλύτερα, η απάντηση μου είναι: Δεν ξέρω! Η αίσθηση μου είναι πως ναι, θα μπορούσε να πάει καλύτερα με κάποιον άλλο compiler. Τα 800 MHz που έχει παραπάνω δεν δικαιολογούν τόσο μεγάλες διαφορές. Το πρόβλημα είναι, ποιός είναι αυτός ο compiler και αν είναι προσβάσιμος σε εμάς, δηλαδή δωρεάν. Όταν έγραφα τον κώδικα, είχα στο μυαλό μου κάποιον Xeon. Συνεπώς έγραψα τον κώδικα μου cisc friendly, xωρίς χρήση loop unrolling και software pipelining που θα ευνοούσε χαρακτηριστικά τον Itanium. Αν είχα κάνει κάτι τέτοιο ο χρόνος του Opteron θα ήταν ακόμα χειρότερος.
Απ'ότι φαίνεται όμως, από μία ματιά στο assembly output και των δύο compilers, εφάρμοσε αυτές τις τεχνικές από μόνος του o icc για να βοηθήσει τον Itanium να πάει καλύτερα και μάλλον τα κατάφερε καλά.
Το δικό μου συμπέρασμα από όλα αυτά είναι ότι, αν έχουμε την δυνατότητα επιλογής ανάμεσα σε compilers, επιλέγουμε πολύ προσεκτικά. Οι διαφορές μεταξύ τους είναι τεράστιες καθώς και το ώφελος που θα έχουμε, χωρίς να χρειαστεί να αλλάξουμε ούτε μία γραμμή κώδικα.
Έχω βρει μία λίστα με safe flags για το gentoo εδώ (http://www.freehackers.org/gentoo/gccflags/flag_gcc3.html), την οποία και χρησιμοποιώ για τα δικά μου προγράμματα. Γνωρίζοντας την αρχιτεκτονική του target που θα τρέχει το software μπορώ να κάνω build σε ένα άλλης αρχιτεκτονικής μηχάνημα με τα flags που αντιστοιχούν στον target και να έχω τα ίδια αποτελέσματα? Υπάρχουν flags που θα πρέπει να φοβάμαι ανάλογα με το τι κάνω build (πχ standalone executable, shared library, static libray)?
DarthMoul
26-03-2006, 15:29
Εφόσον δεν κάνεις cross-compiling (Πχ x86 -> x86-64) δεν έχεις να φοβηθείς κάτι. Μπορείς κάλλιστα σε έναν Pentium3 να δημιουργήσεις binary optimized για έναν Athlon-XP. Στο cross-compiling αλλάζουν τα δεδομένα.
Τα safe flags μαζί με άλλες λεπτομέριες τα βρίσκεις και εδώ:
http://www.pctechnology.gr/vbull/vb/showthread.php?t=12792
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.