» »

Digitalna evolucija

Digitalna evolucija

««
16 / 29
»»

OwcA ::

Priznam, da sem v prejšnem odgovoru napisal nekaj bedarij in sicer:
1) namesto QueryPerformanceFrequency bi moralo pisati QueryPerformanceCounter
2) QueryPerformanceCounter() nima enake resolucje na vseh sistemih, zato je bila ocenitev resolucije GetTickCount() napačna, še vedno pa velja isti pomislek (čeprav verjetno manj ozek in je napaka velikostnega reda 1).
Otroška radovednost - gonilo napredka.

Thomas ::

Če bi optimiziral Critticall (na $retvar variable, tako kot vedno dela), bi tole 100 milijonsko zanko skrajšal na vsega 10, 20 inštrukcij. Rezultat bi bil enak. Za faktor cca milijon torej.

Compiler pa to naredi za faktor okoli 10.

Dovolj, da benchmark ni vreden nič.

:D
Man muss immer generalisieren - Carl Jacobi

noraguta ::

zakaj 0-le? kompajler pomeče ven kar nima prihodnosti.
ce printneš k po merjenju casa bi morale nule izginit. uni zadnji game devovc pa se mi zdi da je testiral rand funkcijo nisem šel preverjar. sicer pa tisti bench programček , ki je tam uporabljen pri bsr-ih ne zgleda napačen.
Pust' ot pobyedy k pobyedye vyedyot!

OwcA ::

Sem se še malo igral in spremenil kodo tako, da zgenerira polje naklučnih integerjev in te uporablja za argumente. To bi naj sedaj bila realna situacija, upam da se strinjaš.
int main()
{
	int max = 0;
	std::cin >> max;
	srand( (unsigned)time( NULL ) );
	int *in = new int[max];
	for (int i = 0; i < max; i++)
	{
		in[i]=rand();
	}
	int mode=1;mode<<=BITS;
	int n=0;
        LARGE_INTEGER c1;
        LARGE_INTEGER c2;
	int k=0;
	int t=0;

        k=0;
        t=GetTickCount();
	QueryPerformanceCounter(&c1);
	for (n=0; n<max; n++) {
 	   k += NextPow2_DD3(in[n]%mode);
	}
	QueryPerformanceCounter(&c2);
	printf("\n           Time NextPow2_DD3: %d miliseconds. ",GetTickCount()-t);
	printf("%d precise counter. ", c2.QuadPart-c1.QuadPart);

        k=0;
	t=GetTickCount();
	QueryPerformanceCounter(&c1);
	for (n=0; n<max; n++) {
 	    k+=NextPow2_Critticall(in[n]%mode);
	}
	QueryPerformanceCounter(&c2);
	printf("\n Time NextPow2_Critticall: %d miliseconds. ",GetTickCount()-t);
	printf("%d precise counter. ", c2.QuadPart-c1.QuadPart);

	printf("\n\n");

	delete [] in;
	return 0;
}


Rezultati za 100000000 (enaka vrednost uporabljena tudi v vseh nadaljnih testih) števil so:
Time NextPow2_DD3: 62 miliseconds. 203787084 precise counter.
Time NextPow2_Critticall: 62 miliseconds. 201894428 precise counter.

Torej sem se motil glede agresivnosti optimizacij, hkrati pa drži kar sem pisal prej o izkoriščanju arhitekture.

Zanimivo postane, če vklopimo avtomatično paralelizacijo (/Qparallel), pri čemer nas prevajalnik prijazno obvesti, da je ustrezno obdelal obe zanki v funkciji main:
Time NextPow2_DD3: 63 miliseconds. 233771260 precise counter.
Time NextPow2_Critticall: 0 miliseconds. 60652 precise counter.

Fantastičen dosežek za Critticall kaj?

Kaj pa če za hec zamenjamo vrstni red testov, tako da je najprej NextPow2_Critticall?
Time NextPow2_Critticall: 125 miliseconds. 413988124 precise counter.
Time NextPow2_DD3: 0 miliseconds. 60448 precise counter.

Mislim, da komentar ni potreben, oziroma glej mojo razlago zgoraj.

Volk sit in koza cela? :)
Otroška radovednost - gonilo napredka.

snow ::

OwcA lep za mene najbolj objektiven test s to tabelo naključno generiranih števil.

Ok meni ni jasno tole z vrstnimi redi... optimizacija mal glede kaj dela en in kaj drug algoritem, pa se odloči pol da brezveze da drugega laufa? Ali laufa druga vzporedno in se ubistvu že izvede?
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Thomas ::

mode=2<<(BITS+1)
Man muss immer generalisieren - Carl Jacobi

Zgodovina sprememb…

  • spremenil: Thomas ()

Thomas ::

Ne ne. Je že OK. 2<<BITS ... gledam dalje.
Man muss immer generalisieren - Carl Jacobi

Thomas ::

Compiler je, potem ko mu že zabremzamo optimizacije, relativno slab.

Slabo on prevaja iz C v asm.

Jest to naredim bistveno bolje, še popravim, pa še ni optimum.

Iz vsega tega sem se naučil to, da se mi bistveno izplača delat ASM output iz Critticalla.
Man muss immer generalisieren - Carl Jacobi

Thomas ::

> Ok meni ni jasno tole z vrstnimi redi... optimizacija mal glede kaj dela en in kaj drug algoritem, pa se odloči pol da brezveze da drugega laufa? Ali laufa druga vzporedno in se ubistvu že izvede?

Pravzaprav ne vem. Oboje je slabo za benchmarking.
Man muss immer generalisieren - Carl Jacobi

OwcA ::

@snow: zelo poenostavljeno povedano se koda tako problikuje, da lahko hkrati uporabljamo več cevovodov. Tako se obe zanki izvedeta "istočasno" (vsaj iz gledišča naših casomercev), kjer je bila druga zanka ostane le malo kode, ki iz raširitvenih registrov prestavi podatke.

@Thomas:
Oboje je slabo za benchmarking.

Se strinjam. Lepo pa pokaže neiskoriščenost ciklov.

Compiler je, potem ko mu že zabremzamo optimizacije, relativno slab.

Meni se ne zdi. Še vedno zna, če vse ostalo (kot je prevajanje kakšnih bolj naprednih jezikovnih konstruktov) odmislimo, iskoriščati arhitekturo, ti pa verjetno ne, ali vsaj ne več kot ene.
Bom spremenil še tvojo asm kodo (ali pa jo daj sam), da bo skladna s testno metodologijo in poskusil.
Otroška radovednost - gonilo napredka.

Thomas ::

Moj assembler spremeni tako, da bo bral iz tabele, namesto da bi računal iz tekoče zanke.

Vendar ni treba. V assemblerju ne zna goljufati.
Man muss immer generalisieren - Carl Jacobi

Thomas ::

V assemblerju, kot sem rekel, optimizacije ne znajo goljufati.

V Cju pa lahko uporabljajo tud MMX, SSD in še vse druge možne optimizacije.

Koda ki pride ven je lahko bolj slaba, vendar se zaradi 64 in več bitne podpore in nekaterih drugih hardwareskih trikov zelo hitro izvaja.
Man muss immer generalisieren - Carl Jacobi

snow ::

Aha v mojem stdlib je #define RAND_MAX 0x7FFF

Tak se ne smemo it :)
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Thomas ::

Če se gremo tak, Critticall's suffers very much. :D
Man muss immer generalisieren - Carl Jacobi

OwcA ::

Spremeniti sem mislil zato, da je povsod enako funkcijskih klicov in da je zanka enako implementirana. Potem imamo relano primerjavo med tvojim asmjem in ICC-jevim.

Koda ki pride ven je lahko bolj slaba, vendar se zaradi 64 in več bitne podpore in nekaterih drugih hardwareskih trikov zelo hitro izvaja.

Ampak ali ni v končni fazi to tisto kar šteje? Čim več computinga za čim manj CPU-ja.

Glede na to, da prihajajo dodatne razširitve (SSE, x86-64 ...) z vsako generacijo procesorjev in da se pojavlja vse več namenskih procesorjev (GPU, DSP ...) se mi zdi nujno računati s tovrstnim "goljufanjem". Učinkovitost le-tega smo ravnokar empirično preverili. ;)
Otroška radovednost - gonilo napredka.

Thomas ::

> Glede na to, da prihajajo dodatne razširitve (SSE, x86-64 ...) z vsako generacijo procesorjev in da se pojavlja vse več namenskih procesorjev (GPU, DSP ...) se mi zdi nujno računati s tovrstnim "goljufanjem". Učinkovitost le-tega smo ravnokar empirično preverili.

NE. Še vedno velja, da imej matematično optimalen algoritem in le takega bodo vsi gizmoti končno prevedli še bolje. Suboptimalnost se splača le po kakšnem naklučju, ki pa ni trpno.

Be the best at every stage! First stage specially!

Ker po predaji izvorne kode je pa že vse določeno.

:)
Man muss immer generalisieren - Carl Jacobi

OwcA ::

Aha v mojem stdlib je #define RAND_MAX 0x7FFF

Sem popravil in spremenil kodo toliko, da se polje že napolni z "normiranimi" vrednostmi:
int main()
{
	int max = 0;
	std::cin >> max;
	srand( (unsigned)time( NULL ) );
	int *in = new int[max];
	int mode=1;mode<<=BITS;
	for (int i = 0; i < max; i++)
	{
		in[i]=static_cast<int>(static_cast<float>(rand())/RAND_MAX*max)%mode;
	}
	int n=0;
        LARGE_INTEGER c1;
        LARGE_INTEGER c2;
	int k=0;
	int t=0;

        k=0;
	t=GetTickCount();
	QueryPerformanceCounter(&c1);
	for (n=0; n<max; n++) {
		k+=NextPow2_Critticall(in[i]);
	}
	QueryPerformanceCounter(&c2);
	printf("\n Time NextPow2_Critticall: %d miliseconds. ",GetTickCount()-t);
	printf("%d precise counter. ", c2.QuadPart-c1.QuadPart);

        k=0;
        t=GetTickCount();
	QueryPerformanceCounter(&c1);
	for (n=0; n<max; n++) {
 	   k += NextPow2_DD3(in[i]);
	}
	QueryPerformanceCounter(&c2);
	printf("\n           Time NextPow2_DD3: %d miliseconds. ",GetTickCount()-t);
	printf("%d precise counter. ", c2.QuadPart-c1.QuadPart);

	printf("\n\n");

	delete [] in;
	return 0;
}

Rezultat ostaja bolj ali manj nespremenjen:
Time NextPow2_Critticall: 62 miliseconds. 223672188 precise counter.
Time NextPow2_DD3: 62 miliseconds. 201822716 precise counter.
Otroška radovednost - gonilo napredka.

Thomas ::

Pojdi na več bitov, pa bo Critticall zmagal.

Matematika je na strani njegovega algoritma. :)
Man muss immer generalisieren - Carl Jacobi

snow ::

Ok moj gcc compiler je čuden :)
(Jaz bi tudi mel intel compiler ja...:\)

No kak je bilo. Testiram kodo, ki jo je dal Owca.

Brez optimizacij pod 50 miljonov cifr zgubi critticall za eno malenkost. (oba časa okol 250ms)

Nad 60 miljonov pa čas zelo zelo naraste.. dd3 23 sekund, critticall 13sekund.


Z optimizacijami je podobno razmerje samo časi so nižji.

procesor: amd 1900+

owca bi lahko dobil tvoj exe.. z optimizacijami brez qpararel?
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

snow ::

Za več bitov:
Do 24 moraš dodati critticalu 2 al tri vrstice..

Do 32 bitov pa še v lut(dd3) verziji.. plus v critticallu ene 12 :\
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

OwcA ::

NE. Še vedno velja, da imej matematično optimalen algoritem in le takega bodo vsi gizmoti končno prevedli še bolje.

Se ne strinjam, vsaj ne, dokler matematične optimalnosti ne definiraš glede na ceno v ciklih na dani arhitekturi (pa še potem nastane vprašanje prenosljivosti).

Poglej že ta primer. V kolikor ne bi imeli linearne porazdelitve ampak nekaj padajočega, jo Critticallova verzija odnese slabše.

Jest to naredim bistveno bolje, še popravim, pa še ni optimum.

Kaj res? No daj za hec zoptimiziraj Critticallovo rešitev, da dobiš rezultat primerljiv z
Time NextPow2_Critticall: 0 miliseconds. 25098704 precise counter.
Time NextPow2_DD3: 63 miliseconds. 200534916 precise counter.

Deli, paraleziraj, vladaj. ;)
Otroška radovednost - gonilo napredka.

snow ::

> V kolikor ne bi imeli linearne porazdelitve ampak nekaj padajočega, jo Critticallova verzija odnese slabše.

Za tisto bi Critticall pogruntal drug algoritem se ve. :D

To sem razlagal na gamedev.. moraš vedet na kaj gledaš ti neko optimalnost, za kakšno porazdelitev števil.

Ja, možno da bi bila tale DD3 verzija tista optimalna.. ampak bi moral povedat za kakšno razporeditev se gre in bi potem testirali.
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Thomas ::

> Se ne strinjam, vsaj ne, dokler matematične optimalnosti ne definiraš glede na ceno v ciklih na dani arhitekturi

Vedno gre za neka zaporedja osnovnih operacij z biti.

Te operacije izvajajo neki (preprosti) fizikalni procesi.

Vse kar želimo je otimizacija njihovih zaporedij.
Man muss immer generalisieren - Carl Jacobi

OwcA ::

@snow: Matematično gledano se mi zdi, da je v skoraj vseh primerih Critticallova rešitev najboljša, v praksi pa je cmp dražji od premikanja bitov (še posebaj recimo na Athlonih, kjer je praktično "zastonj").
Kot sem že rekel, da bi v celoti tole zdržalo, bi bilo potrebno nekoliko drugače definirati matematično optimalnost.

owca bi lahko dobil tvoj exe.. z optimizacijami brez qpararel?

Lahko (brez qpararel, optimizacije za P3, ker K7 ni povesm združljiv z P4).
Otroška radovednost - gonilo napredka.

Zgodovina sprememb…

  • spremenilo: OwcA ()

Thomas ::

> Kaj res? No daj za hec zoptimiziraj Critticallovo rešitev

No, take reči sem že počel. MMX optimizacije, naprimer. Ampak ne bom več. To naj odslej dela Critticall. Bom napisal kakšen Critticall C template, ki to počne. Ko se premaknemo naprej.

Na Rubika recimo najprej, res.
Man muss immer generalisieren - Carl Jacobi

OwcA ::

Malo prepozno sem dopolnil svoj odgovor, zato ga bom raje napsisal kot nov odgovor:

@Thomas:
Vedno gre za neka zaporedja osnovnih operacij z biti.

Kaj so zate "osnovne operacije"? Če tiste za katere imaš neposredno strojno podporo, potem se te razlikujejo od arhitekture do arhitekture. Ne trdim, da je kaj takega nemogoče implementirati v Critticall, ampak bi pa za to verjetno potreboval kar obsežno ekipo. Druga rešitev je odprta koda. GCC-ju precej dobro uspeva konkurirati Intelu tudi kar se tiče podpore različnih novih razširitev.
Vse druge delitve pa so nesmiselne, saj ni nobenega argumenta vprid razlikovanju med časovno enako zahtevnimi operacijami.
Otroška radovednost - gonilo napredka.

snow ::

Aha problem je v ramu :)
Sam tale program se temu nekak izogne pa potem ko napolni array izmeri normalne čase, za razliko od onega ki sem ga jaz naredil z gcc.

Mal meril od 50 do 150 miljonov.
Včasih en včasih drug včasih skoraj enak :)
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

snow ::

Rubik sem slišal? Yes please!
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Thomas ::

> Kaj so zate "osnovne operacije"?

Približno nekaj takega.

> Ne trdim, da je kaj takega nemogoče implementirati v Critticall, ampak bi pa za to verjetno potreboval kar obsežno ekipo.

Ne v program, kar v nek C template.
Man muss immer generalisieren - Carl Jacobi

Vesoljc ::

what have i done :)

mar bi bil tiho :D
Abnormal behavior of abnormal brain makes me normal...

noraguta ::

@snow: Ok meni ni jasno tole z vrstnimi redi... optimizacija mal glede kaj dela en in kaj drug algoritem, pa se odloči pol da brezveze da drugega laufa? Ali laufa druga vzporedno in se ubistvu že izvede?


testa se izvedeta zaporedno napaka je v bench programu. to je bilo napisano ze najmanj 3kratkrat in na to so tomasa opozorili na zacetku ko je vstopil v temo na game dev.

v zadnji zanki kompiler ugotovi ,da se int k (k+=NextPow2_Critticall(in[n]%mode);=
ne uporablja več in ga compiler flikne ven .

če za
QueryPerformanceCounter(&c2);
printf("\n Time NextPow2_Critticall: %d miliseconds. ",GetTickCount()-t);
printf("%d precise counter. ", c2.QuadPart-c1.QuadPart);
dodaš
printf("%d",k);
bi moralo benchat kakor se zagre.
Pust' ot pobyedy k pobyedye vyedyot!

DixieFlatline ::

Da mal prekinem vročo debato, en link ki spada v tole temo.

Povezava
The sky above the port was the color of television, tuned to a dead channel.

Thomas ::

Jah vroče bo tole še!

Ampak tvoj link je super. Ja, vsako stvar je možno zevoluirati, tako je!
Man muss immer generalisieren - Carl Jacobi

snow ::

Recimo fitness funkcijo za rubikovo kocko :\
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Thomas ::

Ma, vse. Tole se mi pogovarjamo na chatu ob sobotah in sploh na forumu že kar nekaj časa. Pisec tega članka, kot da bi nas bral! :D

Dejansko bomo zevoluirali vse možno, to je zdaj že kristalno jasno. Računalniki so pa tudi že zelo hudi. Supercomputri pa sploh!

Google for "top 500"!
Man muss immer generalisieren - Carl Jacobi

ciki57 ::

Zgodovina sprememb…

  • spremenil: ciki57 ()

snow ::

Saj saj... vedno več bo tega. :))
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Thomas ::

Return to HOT.

Trenutna ugotovitev na Gamedev.net je taka, da pravilno delujeta le dva algoritma. BSR4 in Critticallov. Razen seveda taful tapočasnih.

Tko da ... spremljajmo naprej!

P.S.

Vae victis!
Man muss immer generalisieren - Carl Jacobi

Zgodovina sprememb…

  • spremenil: Thomas ()

Vesoljc ::

kot kaze se nocjo vec igrat :D
Abnormal behavior of abnormal brain makes me normal...

Thomas ::

Hehe ... nekak nocjo doumet, da to ni nic osebnega!

Mene zdej resno zanima, kako je s tistim BSR4. Tista operacija znotraj enega registra, če bi bila hitra, je kar zanimiva. Me zanima, če jo bodo procesormani še kej poboljšal. Nekako jo niso skoz vse generacije.

Samo tam debate več ne bo o tem.

Niti o tem, kaj bi pomenila tista moja "hibridizacija", ko za vecino stevil poskrbi binary.

Zdej bi se lahko sele zacelo!
Man muss immer generalisieren - Carl Jacobi

kopernik ::

Wow, temo so zaklenili. Nekaj, kar se ne dogaja vsak dan na gamedev.net :-)

Thomas, fajn si jih sprovociral.

snow ::

> Anyone who's taken grade 11 math should know this. 2^0 = 1, 2^-1 = 1/2 ... 2^-inf = 0

Ja a si hodu v 11 razred al ne? :))

nextpow(0) je tud po moje 0 ja.
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Sergio ::

To je pa tut vse, kar je naredil. Dobro provokacijo. Dvanajst ljudi ga je poslalo v rit, nato je bila tema zaklenjena.

Mogoce bi moral Thomas, ce ze tako stavi na svojega paradnega konja, za prednost v dirki nameniti tudi nekaj poslusalnega casa nasprotnim stranem, da bi le-te lahko priznale premoc Critticalla.

Dokler bo pa avtorjev ego stopal na pot temu programu, se pa skupnost ne bo premaknila v prid, kar zna skodovati avtorjevim nacrtom s tem programom.
Tako grem jaz, tako gre vsak, kdor čuti cilj v daljavi:
če usoda ustavi mu korak,
on se ji zoperstavi.

Thomas ::

Samo to je vprašanje, če je nextpow(0) = 1 ali 0.

Brez dvoma 1, ker tisti -INF ni definirana zadeva. Sorry.

Kar se tiče emocij, so pa samo v napoto.
Man muss immer generalisieren - Carl Jacobi

snow ::

Thomas kaj pa 2^-2 recimo? 1/4.. ta je bližje 0.
Random mutation plus nonrandom cumulative natural selection - Richard Dawkins

Sergio ::

%NEXTPOWOF2 Next power of 2.
%
% P = NEXTPOWOF2(X) returns the smallest integer P such that 2^P >= abs(X).

nextpowof2(0)?

Torej 2^p >= 0.

Hm.

Rešitev je očitno, ker vračamo integer, najmanjši možni še predstavljivi int v obsegu računalnika.

V predstavitvi z dvojiskim komplementom pri 32-bitnem intu bi stvar morala vrnit:
1000 0000 0000 0000 0000 0000 0000 0000

Torej -2147483648.
Tako grem jaz, tako gre vsak, kdor čuti cilj v daljavi:
če usoda ustavi mu korak,
on se ji zoperstavi.

Sergio ::

>> Samo to je vprašanje, če je nextpow(0) = 1 ali 0.

2^p >= 0

2^1 = 2 >= 0
2^0 = 1 >= 0

2^0 is smaller. Samo to se vedno ni prava resitev. Glej zgoraj.

Mal si ga usekal, T.
Tako grem jaz, tako gre vsak, kdor čuti cilj v daljavi:
če usoda ustavi mu korak,
on se ji zoperstavi.

Thomas ::

No tole sem jim zdej odpru.


Tukaj je jasno, da 0 ni ni faktorel. Torej

0->1
1->1
2->2
3->6
4->6
5->6

No, pri faktorelu je to samo bolj jasno, kot pri potenci.

Se motim?

Se ne.
Man muss immer generalisieren - Carl Jacobi

Thomas ::

> Thomas kaj pa 2^-2 recimo?

Očitno nismo obravnavali negativnih števil:

> unsigned __stdcall NextPow2_DD3(unsigned n)
Man muss immer generalisieren - Carl Jacobi

Zgodovina sprememb…

  • spremenil: Thomas ()

Sergio ::

Joj kok te bodo benal iz tega foruma ... Skoda.
Tako grem jaz, tako gre vsak, kdor čuti cilj v daljavi:
če usoda ustavi mu korak,
on se ji zoperstavi.
««
16 / 29
»»


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Najhitrejši programski jezik? (strani: 1 2 )

Oddelek: Programiranje
757766 (5586) Senitel
»

Funkcija z logičnimi operaterji.... (strani: 1 2 )

Oddelek: Programiranje
905620 (4966) CaqKa
»

Petaflopsu naproti (strani: 1 2 3 )

Oddelek: Novice / Procesorji
1058911 (8911) Marjan
»

cene permutacij help please

Oddelek: Programiranje
262080 (1687) Sergio
»

kako definirtati prastevilo

Oddelek: Programiranje
143805 (3610) ooux

Več podobnih tem