CISC vs. RISC + benchmarkok + tenyleg olyan szar-e az x86, mint sokan hiszik?

Fórumok

Minap a FreeBSD Alpha portjanak beszunteteserol szolo topicban felmerult, hogy az x86 egy szutyok proci az Alphahoz kepest. Most felreteve

http://hup.hu/node/24986#comment

Idezem a hozzaszolast (gsimon nevu nick kovette el):

Plusz az 500 MHz-es, EV56-os core-ral szerelt Miata-m lebegőpontos számításban abszolut skálán hármas szorzóval lehagyta a 2.4GHz-es P4-et.
Plusz a buszrendszere full 64-bit, és ha a belső cache-nél nagyobb adatmennyiségről van szó, akkor mire az egyező órajelen futó Intel meg AMD nekiindul, az Alpha már sétálva hozza visszafelé a célszalagot.

Harom dolgot furcsalltam a dologban:
- Egy 500MHz-es orajelenkent ket lebegopontos muvelettel hogyan hagy le egy 2.4GHz-es P4-est.
- Hogy jon ide a buszrendszer szelessege? Hatassal van a meresre, de messze nem olyan mertekben mint gondolnank...
- Ha adott orajelre vetitjuk a teljesitmenyt, akkor valoban gyorsabb az Alpha, mivel effektiven ket lebegopontos egysege van, mig az x86-osoknak egy. De az is tutibiztos, hogy nagysagrendekkel tobbet kell fizetni egy 1GHz-es Alpha prociert, mint egy 1Gigas Duronert.

Tovabb ragva a dolgot elkertem a benchmarkot, es megneztem alaposabban.


#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define BAILOUT		4096

int SIZE;
int	**pix;

int mandel(int i, int j)
{
	double		zre, zim;
	double		cre, cim;
	double		t;
	int			n;

	cre=2.0*(i-(SIZE/2))/SIZE;
	cim=2.0*(j-(SIZE/2))/SIZE;
	zre=zim=0;
	for (n=0; (n<BAILOUT) && ((zre*zre+zim*zim)<4); n++)
	{
		t=zre*zre-zim*zim+cre;
		zim=2*zre*zim+cim;
	}
	return n;
}

int main(int argc, char **argv)
{
	int		i, j;
	int		fd;

	if (argc<2) return printf("%s matrix_size\n", argv[0]);
	
	SIZE=atoi(argv[1]);
	pix=(int**)malloc(SIZE*sizeof(int*));
	
	for (i=0; i<SIZE; i++)
	{
		printf("Row %d/%d\n", i, SIZE);
		pix[i]=(int*)malloc(SIZE*sizeof(int));
		for (j=0; j<SIZE; j++)
		{
			pix[i][j]=mandel(i, j);
		}
	}
	
	fd=open("/dev/null", O_WRONLY);
	write(fd, pix, sizeof(pix));
	return 0;
}

+ a hozza tartozo text



                        Alpha, AMD, Pentium, Sparc, PPC
                               osszehasonlitas



Korulmenyek:
============
Platformok:
Alpha:   MiataGL/EV56, 500MHz, 1000 BogoMips, Cache: L1=8k, L2=96k, L3=2M 
AMD:     Duron, 1.3GHz, 2600 BogoMips, Cache: L1=64k, L2=64k, L3=???
Pentium: Pentium4, 2.53GHz, 4980 BogoMips, Cache: L1+L2=512k, L3=???
Sparc:   UltraSparc-III, 750MHz, Cache: L1+L2=64k, L3=8M
PPC:     PowerPC G3, 333MHz, Cache: ???
PPCg:	 PowerPC ???
         (Cache: L1, L2 a chipen, L3 az alaplapon)

Forditok:
Alpha:   Compaq C 6.5.9.001-6    ccc -O4 -o tgt src.c
		 GNU C 3.3.3			 gcc -O3 -o tgt src.c

AMD:     GNU C 3.0.4             gcc -O3 -o tgt src.c
Pentium: GNU C 3.0.4             gcc -O3 -o tgt src.c
Sparc:   GNU C 2.95.3            gcc -O3 -o tgt src.c
PPC:     GNU C 3.3               gcc -O3 -o tgt src.c
PPCg:    GNU C 2.9               gcc -O3 -o tgt src.c

Forgatokonyv:
Minden teszt haromszor futtatva, eredmenyek atlaga a tablazatban,
ervenyesseg feltele: szoras<5%, gepeken szamottevo egyeb terheles nincs.
!!! Alpha-n ellenoriztem a gcc-t is, csak 2..6-szor lassabb kodot generalt,
!!! valoszinuleg erosen WIntel-re optimalizal, igy egyeb platformokon az
!!! eredmenyek valoszinuleg szuboptimalisak!



Teszt #0: mandel.c
==================
         | N=128   | N=256  | N=512  | N=1024  | N=2048  |
---------+---------+--------+--------+---------+---------+
Alpha:   |  0.131  |  0.5   |  1.965 |   7.8   |  31.11  | valos
  *0.5   |  0.0655 |  0.25  |  0.983 |   3.9   |  15.56  | 1GHz-ekvivalens
 - - - - + - - - - + - - - - - - - - + - - - - + - - - - +
 gcc-vel |  3.664  | 14.628 | 58.48  |         |         | valos
  *0.5   |         |        |        |         |         | 1GHz-ekvivalens
---------+---------+--------+--------+---------+---------+
AMD:     |  0.587  |  2.336 |  9.324 |  37.263 | 149     | valos
  *1.3   |  0.763  |  3.037 | 12.121 |  48.442 | 193.7   | 1GHz-ekvivalens
---------+---------+--------+--------+---------+---------+
Pentium: |  0.410  |  1.628 |  6.494 |  25.945 | 103.7   | valos
  *2.53  |  1.037  |  4.119 | 16.43  |  65.641 | 262.36  | 1GHz-ekvivalens
---------+---------+--------+--------+---------+---------+
Sparc:   |  1.922  |  7.664 | 30.46  | 121.6   |         | valos
  *0.75  |  1.442  |  5.748 | 22.845 |  91.2   |         | 1GHz-ekvivalens
---------+---------+--------+--------+---------+---------+ 
PPC:     |  2.885  | 11.455 | 45.67  | 182.4   |         | valos
  *0.333 |  0.961  |  3.815 | 15.21  |  60.74  |         | 1GHz-ekvivalens
---------+---------+--------+--------+---------+---------+ 
PPCg:    |  0.377  |  1.481 |  5.985 |  23.61  |  94.22  | valos
  *      |         |        |        |         |         | 1GHz-ekvivalens
---------+---------+--------+--------+---------+---------+ 
Sebesseg-aranyok: Alpha > AMD > PPC >= Pentium > Sparc

Alpha/AMD     = 193.7 /15.56  = 1245% 
Alpha/PPC     =  60.74/ 3.9   = 1557%
Alpha/Pentium = 262.36/15.56  = 1686%
Alpha/Sparc   =  91.2 / 3.9   = 2338%

AMD/PPC       =  60.74/ 48.4  =  125%
AMD/Pentium   = 262.36/193.7  =  135%
AMD/Sparc     =  91.2 / 48.4  =  188%

PPC/Pentium   =  65.64/ 60.74 =  108%
PPC/Sparc     =  91.2 / 60.74 =  150%

Pentium/Sparc =  91.2 / 65.64 =  139%



Teszt #1: minsort.c
===================
         | N=4   | N=8   | N=16  | N=32  | N=64   | N=128 | N=256 |
---------+-------+-------+-------+-------+--------+---------------+
Alpha:   | 0.303 | 1.212 | 4.864 | 19.65 |  82.1  |               |
  *0.5   | 0.152 | 0.606 | 2.432 |  9.83 |  41.05 |               |
 - - - - + - - - + - - - + - - - + - - - + - - - -+- - - - - - - -+
 gcc-vel | 0.2   | 0.806 | 3.25  | 13.3  |  55.2  |               |
  *0.5   |       |       |       |       |        |               |
---------+-------+-------+-------+-------+--------+---------------+
AMD:     | 0.031 | 0.114 | 0.447 |  2.27 |  27.51 |               |
  *1.3   | 0.04  | 0.148 | 0.581 |  2.95 |  35.76 |               |
---------+-------+-------+-------+-------+--------+-------+-------+
Pentium: | 0.033 | 0.126 | 0.503 |  2.01 |   8.05 |  39.1 | 217.1 |
  *2.53  | 0.083 | 0.319 | 1.273 |  5.09 |  20.36 |  98.9 | 549.2 |
---------+-------+-------+-------+-------+--------+-------+-------+
Sparc:   | 0.163 | 0.607 | 2.35  |  9.86 |  41.1  |               |
  *0.75  | 0.122 | 0.455 | 1.763 |  7.4  |  30.83 |               |
---------+-------+-------+-------+-------+--------+---------------+
PPC:     | 0.535 | 2.068 | 8.72  | 35.5  | 149.8  |               |
  *0.33  | 0.178 | 0.689 | 2.9   | 11.82 |  49.88 |               |
---------+-------+-------+-------+-------+--------+-------+-------+
PPCg:    | 0.043 | 0.16  | 0.648 | 2.555 |  10.2  |  40.9 |       |
  *      |       |       |       |       |        |       |       |
---------+-------+-------+-------+-------+--------+-------+-------+
Sebesseg-aranyok: Pentium > Sparc > AMD > Alpha > PPC

Pentium/Sparc = 30.83/20.36 = 151%
Pentium/AMD   = 35.76/20.36 = 176%
Pentium/Alpha = 41.05/20.36 = 202%
Pentium/PPC   = 49.88/20.36 = 245%

Sparc/AMD   = 35.76/30.83 = 116%
Sparc/Alpha = 41.05/30.83 = 133%
Sparc/PPC   = 49.88/30.83 = 162%

AMD/Alpha   = 41.05/35.76 = 115%
AMD/PPC     = 49.88/35.76 = 139%

Alpha/PPC   = 49.88/41.05 = 122%

Megjegyzes:
Az algoritmus O(n^2)-es -> 2x akkora tombon 4x annyi a szamitasigeny. Ahol az
ido 4x-nel tobbet ugrik, ott a ram-eleresi idonek is ugrasa van -> cache
merethatar. Ez jol latszik Alpha-n vegig (L3 cache=2M), AMD-n 32k*4=128k-nal,
Pentium-en 64k*4=256k-nal.



Teszt #2: minsort_ll.c	// mint minsort.c, csak 'long long'-gal -> 64bit
======================
         | N=4   | N=8   | N=16   | N=32  |  N=64  |   
---------+-------+-------+--------+-------+--------+
Alpha:   | 0.319 | 1.274 |  5.223 | 21.93 |  92.28 |
  *0.5   | 0.16  | 0.637 |  2.612 | 10.97 |  46.14 |
 - - - - + - - - + - - - + - - - -+- - - -+- - - - +
 gcc-vel | 0.16  | 0.645 |  2.87  | 12.85 |  60.9  |
  *0.5   |       |       |        |       |        |
---------+-------+-------+--------+-------+--------+
AMD:     | 0.168 | 0.666 |  2.863 | 17.75 |  77.21 |
  *1.3   | 0.218 | 0.866 |  3.722 | 23.08 | 100.37 |
---------+-------+-------+--------+-------+--------+
Pentium: | 0.102 | 0.394 |  1.568 |  6.27 |  26.85 |
  *2.53  | 0.258 | 0.997 |  3.967 | 15.86 |  67.93 |
---------+-------+-------+--------+-------+--------+
Sparc:   | 0.494 | 1.954 |  7.97  | 32.77 | 132.45 |
  *0.75  | 0.371 | 1.466 |  5.978 | 24.58 |  99.34 |
---------+-------+-------+--------+-------+--------+
PPC:     | 0.837 | 3.635 | 14.88  | 63.7  |        |
  *0.33  | 0.279 | 1.21  |  4.96  | 21.21 |        |
---------+-------+-------+--------+-------+--------+
PPCg:    | 0.23  | 0.914 |  3.664 | 14.63 |  58.38 |
  *      |       |       |        |       |        |
---------+-------+-------+--------+-------+--------+
Sebesseg-aranyok: Alpha > Pentium > PPC >= Sparc >= AMD

Alpha/Pentium =  67.93/ 46.14 = 147%
Alpha/PPC     =  21.21/ 10.97 = 193%
Alpha/Sparc   =  99.34/ 46.14 = 215%
Alpha/AMD     = 100.37/ 46.14 = 218%

Pentium/PPC   =  21.21/ 15.86 = 134%
Pentium/Sparc =  99.34/ 67.93 = 146%
Pentium/AMD   = 100.37/ 67.93 = 148%

PPC/Sparc     =  24.58/ 21.21 = 116%
PPC/AMD       =  23.08/ 21.21 = 109%

AMD/Sparc     = 100.37/ 99.34 = 101%

Megjegyzes:
Cache-hatar-effektus AMD-n N=16=16k*8=128k-nal megintcsak elojon, egyebkent
jol latszik, hogy az Alpha memoriabusza 64-bit szeles.



Kiertekeles:
============
- Lebegopontos szamitasoknal az Alpha allva hagyja a jelen WIntel procikat
  12-17-_szeres_ szorzoval. Azokon belul az AMD 35%-kal gyorsabb a Pentiumnal.
  Az Pentium es a PPC kb. egyforma, a Sparc-nak ez a tema nem erossege.

- 32 bites muveleteknel viszont a Pentium a legjobb, 50-150%-kal ver mindent.
  Azon belul kicsit ellentmondasos a helyzet. Amig az adatok elfernek az AMD
  belso cache-eben, addik az AMD 60%-kal jobb a Pentiumnal, onnan viszont
  fordul a kocka, es a Pentium huz ra 75%-ot az AMD-re. Itt a Sparc belehuzott,
  maga moge tolva meg az AMD-t is. A szinten 64-bites Alpha es PPC itt nem
  igazan domboritott.
  
- 64 bites muveleteknel az Alpha nyer, 50%-kal gyorsabb a Pentiumnal, aki
  30%-kal gyorsabb a mezonynel. A PPC, Sparc es AMD nagyjabol ugyanazon
  teljesitmennyel allnak be a sor vegere.



Konkluzio:
==========
- Lebegopontos ill. 64bites muveletekre egyertelmuen hasznalj Alpha-t.
  Valos szamitasokra optimalizalt, full 64 bites gep.

- Altalanos esetben valaszd a Pentiumot. A valos szamitas nem erossege, 35%-ot
  veszit az AMD-vel szemben, de egyebkent megallja a helyet.

- AMD-t csak akkor, ha az adat elfer a cache-ben :), es 32 bites, esetleg ha
  muszaj PC-t hasznalnod, viszont valos szamokkal dolgozol.

- A PPC kicsit lassabb a Pentiumnal, viszont a 32 bites adatokat nagyon nem
  szereti.

- A Sparc, nos, ha olyan procit keresel, ami minden teren konstans 40-50%-kal
  lassabb a Pentiumnal, ez a te nagy lehetoseged :).

Nemigen szeretem a szarragast, de jelen esetben felmerult, hogy van itt tobb komoly tevedes, ami nem teszi eppen partatlanna az elemzest. Sot velemenyem szerint a konkluzio teljesen hibas. Azert nyitottam a forumot, hogy ezt a kerdest kicsit jobban meg lehessen vitatni. Remelem utana kicsit mindenki jobban a helyere tudja tenni a procicsaladokat egymashoz kepest.

Hozzászólások

No akkor a szerintem tamadhato reszek:

- A benchmark eredmenyet torzitja, hogy meri az egesz futast, ahelyett, hogy a lebegopontos kernelre koncentralna. Igy beleszol a kernel, a c konyvtar, a loader, a konzol es meg mas is.

- Az Alpha-s teszt agresszivebb optimalizaciot hasznal, hianyzik a -fast-math -march=p4 es a -msse2 opcio. gcc varazslo kollegak bizonyara tudnanak javasolni egy-ket egyeb kapcsolot, amivel gyorsabb lenne, de maradjunk ezeknel.

- Miert meregetjuk az x86-osokat 3.0-as gcc-vel, ami koztudottan lomha kodot general? Ott a 2.95 vagy a 3.4.

- Miert foglalunk folyamatosan memoriat a futas alatt? Megint a c konyvtarat meregetjuk, nem pedig a lenyegre koncentralunk. Ugyanigy torzit a kiirato rutin is.

- Hibas az az elgondolas, hogy a cache barmilyen komoly hatassal lenne az eredmenyekre, a cache akkor segit, ha sok hivatkozas tortenik a memoria egy kis szeletere. Jelen esetben unit-stride bejarasa van a tomboknek. A cache nem szamit, olyan esetekben van jelentosege, mint pl. a matrix szorzasnak, ahol ugyanazt a memoriatartalmat a szamitas tobb kulonbozo pontjan felhasznaljuk. Akkor mar sokat szamit, hogy bent van-e a cache-ben, vagy ujra a memoriabol kell becincalni.

Sajnos nalam most csak vmware-ben van linux, de kiprobalom a kodot a VisualStudio forditojaval, aztan kiderul mennyit jelent ezek a turpissagok.

- A p4 optimalizálási opciókkal tényleg ludas vagyok, az lemaradt
- Azért foglaltam memóriát, használtam a c lib-et, stb., mert arra voltam kíváncsi, hogy egy átlagos aritmetika-intenzív progival mit teljesít, mert ahogy a ténylegesen használt programok forrását elnézegetem, elég sűrűn szerepel ez is benne.
- Azért a 3.0-s gcc-t használtam, mert akkor az volt a latest&greatest stabilnak mondott.
- Teljes idő mérése, kiíratás, konzol, stb., igen, ezek is vesznek el időt, de (bár egy profile-olással ezt igazolni kéne), a betöltődés kivételével elenyésző a másodperc-nagyságrendű futási eredményekben. A betöltődés kb. konstans, azt le lehetett volna vonni, ez igaz.
- A cache hatásaira a rendezgetős példákat szántam, azoknál inkább jellemző, hogy az idő nagy részét a memória-elérés teszi ki, (legalábbis ezért írtam O(n^2)-esre :)...), és nem az aritmetika

Viszont mivel ez így tényleg csak házi saccolásra alkalmas, én is szívesen látnék tippeket, hozzászólásokat, hogy mit kéne másképp csinálni benne, és végül kihozni egy korrektebb eredményt.

Jelenleg a köv. gépeken tudom tesztelni:
- Alpha 21164 500MHz, gcc 3.3.3 (a ccc-t még reszelnem kell, mert azóta netbsd van fenn, fene tudja, sikerül-e)
- AMD AthlonXP 2600+
- AMD Duron 1.3GHz
- Intel Pentium MMX 233 :)

Nagyon szivesen benne lennek egy tesztben.

En a kovetkezo gepeket tudom "felajanlani":

- Intel Centrino 1.8GHz "Dothan" Notebook (ezen windows van jelenleg)
- AMD Athlon XP 1800+ "Palomino" (windows es linux)
- AMD Athlon64 X2 3800+ "Manchester" (windows es linux)

Otletek:

- Szerintem csinaljuk meg hordozhatora a kodot es akkor windows alatt is tud menni. Nem nagy erofeszites.

- Probaljuk ki a leheto legjobb elerheto forditoprogramokkal is (pl. icc), es kiserletezzunk a flagekkel.