double vs. float

Fórumok

udvozlet! kerdes: van valami jo trukk arra, hogy c-ben amellett hogy egy adott valtozo-kupacot explicite float-kent deklaralunk, az alap-muveleteket a mindenfele egyeb (kvazi kikapcsolhatatlan) optimalizaciok mellett is float-szinten ve'gezze el? gcc-4.x alatt, mindezt. (tema: numerikus cuccok elokeszitese/elotesztelese gpu arch-ra, igy az alapmuvelet az lenyegeben +, -, *, / es esetleg sqrt()). thx, A.

Hozzászólások

Ha jól értem, valami ilyesmi kellene?

int a,b,c;

a=1; b=2;
(float)c = (float)a + (float)b

Ennek a kérdésnek fuss neki még egyszer, mert nem értem. :)

Egy példa biztos segítene...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Egy pelda: legyen a,b,c, e's d float, majd ki akarom szamolni a d=a+b*c; erteket. azt szeretnenk, hogy a b*c is float legyen, mint atmeneti ertek. a kod maga, amit tesztelni kene hasonloan egyszeru (+, - es * van csak benne), csak tobb egymasba agyazott ciklusban, fix meretu kicsi tombokben, tobb 100 soron keresztul... es elegge komplex ahhoz hogy belenyulni nem szeretne'k ha nem muszaj.

deviszont: me'g a 387-es idokben is meg lehetett csinalni, sot, gyk ott is az volt az alap, hogy egy ilyen "d=a+b*c" eseten a szorzas eredmenyet osszeadast gepi pontossaggal, es nem a valtozo sajat pontossagaval vegzi (gyk: fld b; fld c; fmulp st(1); fld a; faddp st(1); fstp d; vagy vmi hasonlo). nyilvan egy tobbszaz soros hasonlo jellegu kodot a fordito is, a cpu is ronggya' optimalizal, tehat a fene se tudja hogy mi tortenik (azaz nyilvan egy fstp x; .... fld x; garantalja hogy a masodik visszairasnal x az float pontossagu legyen, de a franc se tudja hogy mire fordul a kod, mert nyilvan nincs mindenhol szukseg erre, ma'r a 387-esben is 8 regiszter volt). egy gpu eseten is persze van optimalizacio de ott garantalt, hogy minden muvelet 32bites maradjon. ezt kellene emulalni valahogy cpu kodon is...

itten van maga a kod, amirol szo lenne. mindke't fv csont nelkul fordul nvcc-vel gpu-ra trivialis valtoztatasok utan (double -> float), es a lenyeg, a szamitasido 99%-a a masodik (_calc) fv-ben van. de ebben csak *, + e's - muveletek vannak. az eom, eln es aux tipusokban levo" tombok ill. matrixok fix meretuek ([8], [8][8], ezt forditasi idoben lehet tudni, es a gpu miatt is csak ilyen lehet, lenyegeben).

Igen, az x87-es utasításnak megvolt az az érdekessége, hogy minden számítás 80 biten történt, és kerekítés csak akkor volt, mikor kivetted a stack-ből az eredményt.
SSE2-nél ilyen már nincs, úgyhogy ha a programodat sse2-vel fordítod, akkor tudtommal biztos lehetsz benne, hogy a float-okon végzett számítás végig float pontossággal történik.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

na ezaz, hogy effele feltetelezesek persze vannak/lehetnek, de ez nagyon arch-fuggo". szoval kerdes, hogy mit kell tenni, hogy relative arch fuggetlenul (azaz mondjuk kvazi modern x86-os es x64-es linuxokon, pl) garantaltan float legyen... a gcc kapcsoloi kozott semmi erre egyertelmuen utalo dolgot nem lattam ;/

Én így tudom. Biztos csak a halál. Egyébként ha ennyire érdekel nézz utána. Vagy ellenőrizd magad. Most már tudod az irányt.

Egyébként Cuda-val lehet CPU-n emulálni a GPU-t, tehát ha csak ez a gond, akkor van megoldás.

Szerk:
Tekintve, hogy SSE kódnál az SSE regisztereket használod, amik 4x32 bitesek float esetben, ezért viszonylag biztos lehetsz benne, hogy már a regiszterekben is a float-ra kerekített érték tárolódik el.

Szerk2:
http://stackoverflow.com/questions/322797/problem-with-floating-point-p…

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Én sem vagyok biztos benne, hogy jól értem a kérdést.
Azt akarod, hogy 32 bites lebegőpontos számokkal történjen minden műveletvégzés?
Akkor nem trükközni kell, hanem ahogy te is írtad, float-ként kell deklarálni a változókat.
Azonban az sqrt()-vel így is gond lesz, mert a deklarációja:
double sqrt(double num);
C++-ban nincs vele gond, mert ott van float sqrt(float num); deklaráció is.
Egy megoldási lehetőség: http://www.dreamincode.net/code/snippet244.htm
Ez elvileg C++-ra van, de csak az i változó deklarációját kell áthelyeni, és már C-ben is jó.

-----
Innen most töltsünk tiszta vizet a nyílt kártyákba: ...

"Egy megoldási lehetőség: http://www.dreamincode.net/code/snippet244.htm"

Na ezt felejtsd el gyorsan... :)
Az első while ciklus teljes marhaság. A többi meg itt van jóval értelmesebben:
http://en.wikipedia.org/wiki/Babylonian_method#Babylonian_method

Amiből kiderül, hogy a második ciklus is túl hosszú, kb 6 iteráció elég double-nál is...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Az FPU-n nem tudod szimulálni a float számolást, hiszen a FPU regiszterek segítségével vagy 8byte-os, vagy 10 byte-os double-val történik a számolás (hogy melyikkel, az FPU flagektől, fordítóprogramtól, 32/64 bittől függ), és az eredmény valamilyen kerekítés után vissza lesz töltve egy float-ba.

Ha a fordito olyan kodot general(na), hogy minden muvelet utan kiveszi, majd visszateszi az erteket, akkor jo lenne. lasd a fenti pelda, 387-re:


a+b*c => fld a; fld b; fld c; fmulp st(1); faddp st(1); fstp result;

vs.


a+b*c => fld b; fld c; fmulp st(1); fstp tmp; fld a; fld tmp; faddp st(1); fstp result;

nyilvan ezutobbi megoldja a problemat, ha minden fst/fld dword-be (float) megy.

tehat a nkk az, hogy ilyen minden-csak-nem-opt asm kodot generaljon a fordito... vagy barmi ekvivalens. lasd fentebb belinkelt program: fix tombokkel, sok egymasba agyazott ciklus, stbstb, ezt ronggya' lehet optimalizalni ma'r feltucat regiszterrel is. de ~550 sornyi kodot csakugy az ember nem tud atirni...

c++ mennyire jatszik?
float helyett csinalsz sajat "myfloat" osztalyt, atdefinialod az operatorokat, hogy mindenkeppen minden szamitas utan 32 bites legyen, aztan jonapot.. max 20-30 sor, szellosen (utana productionben meg typedef-fel megmondod neki, hogy a myfloat az igazabol kozonseges float, es tessek GPU-ra forditani)

--
I can't believe Steve Jobs's liver is replaceable but the battery in my iPhone is not. - sickipedia