[ Srđan Pavlović @ 29.10.2008. 12:29 ] @
Hehe - combuster i ja smo se malo zezali pa napravili jedan krajnje retardiran programcic za merenje brzine procesora,
ja cu da okacim x_64 build za sada, dakle ovo radi na 64-bit Linuxima:

program se startuje sa

$ chmod +x Test-Brzine-C
$ time ./Test-Brzine-C

Inace ovo je verzija u C-u koju je uradio combuster (malo sam je samo prepravio da bude na srpskom - spram moje verizije u Paskalu :)


Kod mene na C2D na 3Ghz je real oko 4.5 sekundi, kod prijatelja sa sempronom 3000+ real je oko 23 sekunde :)

Pozzz :)

Ako budemo imali jos malo vremena za retardirane programe - bice i unapredjena verzija :)))

Evo kako izgleda:

Citat:

srdjan@Desktop:~/Programi$ time ./Test-Brzine-C
Program Test-Brzne (verzija u C-u) (TM) :)))
Startujte ga sa 'time ime_programa da bi merio brzinu.'
Merim skor za vas procesor...

25 posto kompletirano...
50 posto kompletirano...
75 posto kompletirano...
100 posto - Test kompletiran!

real 0m4.507s
user 0m4.496s
sys 0m0.000s
srdjan@Desktop:~/Programi$


[Ovu poruku je menjao Kernel-1 dana 29.10.2008. u 13:41 GMT+1]
[ Jbyn4e @ 29.10.2008. 13:13 ] @
Jel' to samo da vidite ciji je veci? :)

Evo kod mene...

Masina 1:

Citat:

real 0m7.341s
user 0m6.980s
sys 0m0.004s


procesor:
Citat:

AMD Athlon(tm) 64 X2 Dual Core Processor 4600+
cpu MHz : 1800.000
cache size : 512 KB
bogomips : 3621.35


RAM: 4Gb
OS: OpenSuSE 11

Masina 2 je fenomen, najstarija a najbrza :)
zanimljivost:
Citat:

time sh ./Test-Brzine-C
./Test-Brzine-C: ./Test-Brzine-C: cannot execute binary file

real 0m0.004s
user 0m0.001s
sys 0m0.003s

- zasto se javlja ovo da ne moze da izvrsi fajl?
.
Inace je masina AMD Athlon(tm) XP 2000+,
RAM: 1Gb
OS: SuSE Linux 9.0 (i586)

EDIT: SHVATIO SAM ... zato sto je 32bit sistem...
Evo i rezultata sa 32-bit cputest...:
Citat:

real 0m9.143s
user 0m9.138s
sys 0m0.003s

sto ce reci - ne drzi se lose stari XP2000+!

Mashina 3: Dell poweredge t-300 :)),
Citat:

real 0m5.203s
user 0m5.200s
sys 0m0.004s


Masina:
Citat:

Intel(R) QUAD CORE Xeon(R) CPU X3323 @ 2.50GHz
cpu MHz : 2499.988
cache size : 3072 KB
bogomips : 5000.00

RAM: 6Gb
OS: OpenSuSE 11


[Ovu poruku je menjao Jbyn4e dana 29.10.2008. u 14:26 GMT+1]

[Ovu poruku je menjao Jbyn4e dana 29.10.2008. u 14:30 GMT+1]
[ combuster @ 29.10.2008. 13:16 ] @
Heh, ma zezancija, testirali smo preload da vidimo je li sta brzi :D sa aplikacijom od 10KB lol lol lol lol....Inace kernel je bio zasluzan za logistiku i ideja je njegova ali ja to ne bih pokretao da sam na vasem mestu, ko zna sta je on radio i petljao sa kodom, ako je nabio neki deadloop pa vam sprzi cpu ne obracajte se meni :D :D :D

rezultati na C2D 1.8GHz mobile

real 0m6.795s
user 0m6.756s
sys 0m0.020s


Evo vam i 32-bit
[ Srđan Pavlović @ 29.10.2008. 13:19 ] @
@combuster



@jbn4e

Citat:
Jel' to samo da vidite ciji je veci? :)


egzeeeeeektli! :))

/edit:
Citat:
zasto se javlja ovo da ne moze da izvrsi fajl?

zato sto si je izvrsio na 32-bit instalaciji, skini ovo sto je combuster aploadovao pa pokreni to.
[ combuster @ 29.10.2008. 13:28 ] @
Ja se sad upisa od smeha zbog quad-a :D :D :D
[ Srđan Pavlović @ 29.10.2008. 13:32 ] @
@combuster - jesmo li ukljucili optimizaciju za vise jezgara? Nesto se ne secam? - ja za svoju 64-bit verziju nisam to nista ni gledao...
Al nek ostane ovako, prija mi da je moj "veci" :))))
[ combuster @ 29.10.2008. 13:33 ] @
Ma jok, opterecenje proc-a 50% na duo-u :D

a da pitamo nemesys-a da nam kompajlira on na gentoo-u, verovatno ima u make.conf-u MAKEOPTS -j3 :D :D :D :D
[ Srđan Pavlović @ 29.10.2008. 13:36 ] @
Dok ja ne kupim Kvad-kor, stavicu jednu liniju tipa:

If quad_core_detected = true then loop_one_more_krug :)))))

[ Jbyn4e @ 29.10.2008. 13:43 ] @
Hm... nije da nemam sta da radim,al' ajde jos malo:

masina 4:
Citat:

real 0m4.945s
user 0m4.888s
sys 0m0.000s


Masina je:
Citat:

Intel(R) Core(TM)2 Duo CPU E8200 @ 2.66GHz
cpu MHz : 2666.364
cache size : 6144 KB
bogomips : 5332.82

RAM: 4 Gb
OS: openSUSE 10.3 (X86-64)

masina 5:
cputest (greskom pokrenut jer je 64-bit masina)
Citat:

real 0m7.644s
user 0m7.570s
sys 0m0.017s

Test-Brzine-C
Citat:

real 0m8.109s
user 0m8.075s
sys 0m0.016s


Zanimljivo da je 32-btina aplikacija bila brza...

Masina je
Citat:

AMD Athlon(tm) 64 Processor 3200+
cpu MHz : 2000.138
cache size : 1024 KB
bogomips : 3940.35

RAM: 1 Gb
OS: SUSE LINUX Enterprise Server 9

Ja mislim da je dosta od mene, a ako pronadjem neki backdoor ili slicno u ovim programima, doci cu vam direktno na kucu sa stanglom... Jesmo se razumeli?
[ combuster @ 29.10.2008. 13:49 ] @
Nema problema brate, pade mi napamet da otvorim jedan portic kroz iptables ali ce pre to da ide ako ga iskompajliram kroz bash a ne ovako u c-u :D. Dont worry... Kazem ti ideja bila blesava, trazili kako da kesiramo aplikacije, nasli preload, palo nam napamet da napravimo nesto sto opterecuje cpu cisto onako iz zezanja i tako... Hvala na poredjenjima, vidis da ima interesantnih finding-a ...
[ Srđan Pavlović @ 29.10.2008. 13:57 ] @
Sad sam ga kompajlirao sa -j3 opcijom.. :)
samo da vidim sad sta opterecuje...

/edit: hmm... i dalje mi cepa samo jedno jezgo - na 100%, drugo ne dira...
Mada pri uzastopnim startovanjima postoje varijacije od nekih 0.10 sec...


Citat:
ko pronadjem neki backdoor ili slicno u ovim programima, doci cu vam direktno na kucu sa stanglom... Jesmo se razumeli?


...ok je stangla, ali bez litre domace sljivovice ne dolazi! :)

@combuster - sad sam probao tvoj 32-bit kompajl, isto se izvrsava kod mene i 32 i 64 bit nema neke razlike u brzini.


A po ovom nalazu sa jedne od masina jbn4e-a, i sudeci po poredjenju sa mojim skorom, izgleda je ovaj test osetljiv samo na gigaherce:

Citat:

masina 4:
Citat:

real 0m4.945s
user 0m4.888s
sys 0m0.000s


Masina je:
Citat:

Intel(R) Core(TM)2 Duo CPU E8200 @ 2.66GHz
cpu MHz : 2666.364
cache size : 6144 KB
bogomips : 5332.82


Moj ima manje kesa (E6850, 4mb), isto dva jezgra, ali je na 3Ghz, i izvrsava se za oko 0.40s brze.
Ako neko zna kako da kompajliram program da bude optimizovan za 2 ili vise jezgara, recite da ubacimo...
opcija sa make -j3 ocigledno ne radi... hmm bar tako izgleda.

@jbn4e - na onom Kvad-Kore-u jel ti zakuca samo jedno jezgro na 100% ? Pretpostavljam da je tako...

[Ovu poruku je menjao Kernel-1 dana 29.10.2008. u 16:35 GMT+1]
[ combuster @ 29.10.2008. 15:37 ] @
ma j3 je samo optimizacija pri kompajliranju, brze se kompajlira program od 10k :D
[ Srđan Pavlović @ 29.10.2008. 15:39 ] @
:))) - pa covece sta mi to radis!? :)))

Kako god... ne znam kako da iskoristim vise jezgara :(
[ Srđan Pavlović @ 29.10.2008. 15:50 ] @
> Hi,
>
> I do a lot of gcc compiling. I have a dual core system and by observing
> the CPU usage I think only one of bot cores is working at each time
> (total CPU load is about 52%). I read somewhere that by specifying some
> environmental variables, you can use simultaneously both cores. I lost
> sight of this reference and can no longer find it by googleing for it.
> Does anyone know how to adjust my settings?

I have never heared that the gcc can make use of more than one core, but make
can. With the option -j 2 you can use both of your cores, but I don't know an
environment variable that will do this. There was one for building rpm
packages,
but I don't know it for debian packages.

Gerald


Ovo je sa nekog foruma, znaci ovaj kaze da sam GCC ne moze da "make use of dual core", ali
make MOZE - ovo dalje za -j 2 .... nisam razumeo do kraja, pominje neke varijable.
[ peromalosutra @ 29.10.2008. 16:18 ] @
Prvo je bilo:
Code:
ivan@ivan-desktop:~/Desktop$ time ./cputest 
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real    0m16.900s
user    0m9.461s
sys    0m0.068s


.. a onda sam ugasio Firefox i ponovio test:
Code:
ivan@ivan-desktop:~/Desktop$ time ./cputest 
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real    0m8.944s
user    0m8.545s
sys    0m0.008s


OT: Da li je normalno da mi FF stalno vuce bar 30-50% cpu usage-a a otvoren mi je samo ovaj tab na ES-u u kome pišem poruku?
[ combuster @ 29.10.2008. 16:19 ] @
Vrlo moguce, koji proc imas?
[ peromalosutra @ 29.10.2008. 16:22 ] @
Athlon XP 2200+, 1GB RAM (ddr1, na 333mhz), Ubuntu 8.04..
[ combuster @ 29.10.2008. 16:29 ] @
Ne znam, moguce da ti je iskesirao nekako ovo pa je zato po drugi put bilo brze... probaj da restartujes masinu i pre nego sto startujes ista idi u konzolu pa ponovi komandu pa onda startuj firefox pa ponovi opet test pa vidi...
[ Srđan Pavlović @ 29.10.2008. 16:34 ] @
Sad sam ga rekompajlirao sa gcc -mtune=core2 s-test.c

...ali ne vidim neke bitne promene ni sto se vremena izvrsenja tice (kod mene), ni sto
se tice raspodele na jezgra...

@pero - oce FF da vuce procesor nije to nista cudno.
[ peromalosutra @ 29.10.2008. 16:37 ] @
Ok su rezultati jer je user brzina podjednaka u oba slučaja, razlikuje se samo real brzina (tj. ukupno vrijeme trajanja testa). U prvom testu je radio Firefox koji je očigledno koristio oko 50% cpu resursa, u drugom je on bio ugašen pa je većinu procesorskog vremena dobio test program i zato se zavrsio otprilike duplo brže. Mene je zanimalo samo da li Firefox i na drugim mašinama traži ovako veliki dio procesorskog vremena, ili nešto kod mene ne valja.
[ Srđan Pavlović @ 29.10.2008. 16:42 ] @
^ kod mene na ovom mom variraju jezgra tako od nekoliko procenata pa i do 25 u nekim trenucima (za FF mislim)
ali sa ukljucenim kompizom i tim nekim sranjima..
[ combuster @ 29.10.2008. 16:45 ] @
real 0m6.664s
user 0m6.628s
sys 0m0.000s

bez firefox-a

real 0m6.730s
user 0m6.716s
sys 0m0.000s

sa firefox-om :D znaci otprilike isto

[ jablan @ 29.10.2008. 17:10 ] @
E ja jako cenim vaš entuzijazam, ali je pisanje benčmark testova ipak ozbiljna stvar. Nisam proveravao, ali kladim se da u skladištima svih popularnijih distribucija postoji par benčmark alata...

Što se tiče FF i zauzeća procesora, fleš baneri umeju da budu jako loše napisani, probaj flashblock ako već nisi...
[ Srđan Pavlović @ 29.10.2008. 17:40 ] @
Citat:
E ja jako cenim vaš entuzijazam, ali je pisanje benčmark testova ipak ozbiljna stvar


ja sam smrtno ozbiljan ;)

[Ovu poruku je menjao Kernel-1 dana 29.10.2008. u 19:17 GMT+1]
[ Branimir Maksimovic @ 29.10.2008. 18:44 ] @
e8400 na 3.6, ubuntu 8.04

Citat:

bmaxa@maxa:~$ time ./Test-Brzine-C
Program Test-Brzne (verzija u C-u) (TM) :)))
Startujte ga sa 'time ime_programa da bi merio brzinu.'
Merim skor za vas procesor...

25 posto kompletirano...
50 posto kompletirano...
75 posto kompletirano...
100 posto - Test kompletiran!

real 0m3.656s
user 0m3.648s
sys 0m0.004s


Pozdrav!
[ Srđan Pavlović @ 29.10.2008. 18:52 ] @
Bravo Branimire, sad je tvoj najveci :))))

Ja sam mislio da kloknem svoj na 4Ghz samo za ovo, ali onda bi bio vec jedan suvise besposlen pop :))
[ combuster @ 29.10.2008. 22:09 ] @
Ma ovo je samo cpu i to alu stres. Sledece je nadogradnja za fpu, disk i memory i/o kao i przenje gpu-a sa scenom sa gomilom hidden objekata sa disable-ovanim hyper-z-jem :D
[ jonathan @ 29.10.2008. 23:53 ] @
Athlon64 x2 @ 4600+, BW64 (kastomizirani slackware-current na 64 bita, KDE 4.1.2) :

real 0m6.724s
user 0m6.712s
sys 0m0.004s

p0z, Alek
[ Jbyn4e @ 30.10.2008. 08:27 ] @
Citat:
Kernel-1
@jbn4e - na onom Kvad-Kore-u jel ti zakuca samo jedno jezgro na 100% ? Pretpostavljam da je tako...

Stalno zaboravljas da ja imam i jedno Y u nick-u... sta je tesko koristiti copy/paste? :)

zanimljivo je da kad se pokrene nekoliko puta tvoj Test-Brzine-C, da jednom koristi CPU 1 a drugi put CPU 3 pa onda opet 1, pa opet 3.. 0 i 2 nikad ne dira? Mozda OpenSuSE 11.0 nema pojma o 4 jezgra??? Moracu da proverim to nekako na net-u...

Evo primera sto sam uspeo da uhvatim iz top komande (isao je i na 100% procesor)..:
Citat:

Prvi put:
Cpu0 : 0.0%us, 0.3%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 58.9%us, 0.3%sy, 0.0%ni, 40.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 0.0%us, 0.3%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 0.4%us, 0.7%sy, 0.0%ni, 98.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

Drugi put:
Cpu0 : 0.3%us, 0.3%sy, 0.0%ni, 99.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 0.0%us, 0.7%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 0.3%us, 0.0%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 43.1%us, 0.0%sy, 0.0%ni, 56.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

[ combuster @ 30.10.2008. 08:42 ] @
Pa ja koliko vidim svaki se opterecuje samo sto se brzo izvrsi program pa ne stigne da optereti sva cetiri skroz na skroz, uvek jedan core ide na pola (dvojka i cetvorka).

@alex

thnx za rezultate...
[ Srđan Pavlović @ 30.10.2008. 09:54 ] @
@Jbyn4e - suvise ti je kriptican nick za moj ukus pa gutam slova ;)

Citat:
zanimljivo je da kad se pokrene nekoliko puta tvoj Test-Brzine-C, da jednom koristi CPU 1 a drugi put CPU 3 pa onda opet 1, pa opet 3.. 0 i 2 nikad ne dira? Mozda OpenSuSE 11.0 nema pojma o 4 jezgra??? Moracu da proverim to nekako na net-u...


Kod mene na C2D uvek bira CPU0, nikad CPU1, zanimljivo...
Ili mozda gleda koje je u tom trenutku najmanje zauzeto pa da njemu da radi. Stvarno nemam pojma.

@Jablan - kad si vec pomenuo, ako znas neke dobre CPU testove za Linux, slobodno ih spomeni u ovoj temi, nece biti off-topic,
pogotovo ako imaju opciju biranja jezgra / jezgara koja ce da opterecuju ;)

@jonatan - thnx za rezultate, too.
[ Jbyn4e @ 30.10.2008. 10:46 ] @
Evo vam jedan jednostavniji test (ne mora ni da se kompajlira, ni da se downloaduje, ni da zauzima i 1KB na disku,samo da imate bc instaliran...): a i pritom cete nauciti neke decimale broja pi :)

time echo 'scale=5000; 4*a(1)' | bc -l -q


Rezultati:
1) AMD Athlon(tm) 64 X2 Dual Core Processor 4600+
Citat:

real 0m41.736s
user 0m41.723s
sys 0m0.008s


2) Kvad-kor Intel(R) Xeon(R) CPU X3323 @ 2.50GHz
Citat:

real 0m34.305s
user 0m34.266s
sys 0m0.000s


3)Intel(R) Core(TM)2 Duo CPU E8200 @ 2.66GHz

Citat:

real 0m31.122s
user 0m31.114s
sys 0m0.004s


4) AMD Athlon(tm) XP 2000+
Citat:

real 1m17.449s
user 1m17.320s
sys 0m0.010s


[Ovu poruku je menjao Jbyn4e dana 30.10.2008. u 12:01 GMT+1]
[ Srđan Pavlović @ 30.10.2008. 10:53 ] @
^^ Odlicno ^^ :)


real 0m27.649s
user 0m27.582s
sys 0m0.048s
srdjan@Desktop:~$

Mada, i ovde pici po samo jednom jezgru:




[ Časlav Ilić @ 30.10.2008. 11:10 ] @
Citat:
jablan: E ja jako cenim vaš entuzijazam, ali je pisanje benčmark testova ipak ozbiljna stvar. Nisam proveravao, ali kladim se da u skladištima svih popularnijih distribucija postoji par benčmark alata...


Na to bih dodao i da je ova tema u principu besmislena bez izvornog koda, jer se bez njega ne može zaključiti ni šta ni kako se odmerava, niti se mogu isprobati različite optimizacije kompilatora za različite arhitekture (što se obavezno čini ako se želi iole merodavno upoređenje sistemâ).
[ combuster @ 30.10.2008. 11:11 ] @
svaka cast, eto nam fpu stress-a za prosirenje programa :D

real 0m46.885s
user 0m46.455s
sys 0m0.184s

C2D 1.8GHz Mobile...
[ Srđan Pavlović @ 30.10.2008. 11:16 ] @
@Časlav - Pa kompajler je gcc:

srdjan@Desktop:~$ gcc --version
gcc (Ubuntu 4.3.2-1ubuntu11) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

srdjan@Desktop:~$


Citat:
isprobati različite optimizacije kompilatora za različite arhitekture


Pa ako si upoznat sa nacinima za optimizaciju za vise jezgara za 64-bit arhitekturu, slobodno reci rec-dve.... ;)

Dalje, postovacu sors - vec sam rekao da je krajnje retardiran (mislim na test) - (ovo je za ovaj 64-bit sto sam ja kompajlirao i okacio):

Code:
#include <stdio.h>



long i = 1 ;



int main ()

{

   printf ("Program Test-Brzne (verzija u C-u) (TM) :)))\n");    
   printf ("Startujte ga sa 'time ime_programa da bi merio brzinu.'\n");
   printf ("Merim skor za vas procesor...\n");
   printf (" \n");
     

    do {

    if (i==250000000) printf ("25 posto kompletirano...\n"); else

    if (i==500000000) printf("50 posto kompletirano...\n"); else

    if (i==750000000) printf("75 posto kompletirano...\n"); else

    if (i==1000000000) printf("100 posto - Test kompletiran!\n");

    i++; }

    

    while (i < 1000000001);

    return (1);

}


[Ovu poruku je menjao Kernel-1 dana 30.10.2008. u 12:33 GMT+1]
[ combuster @ 30.10.2008. 11:31 ] @
Code:

#include <stdio.h>

long i = 1 ;

int main ()
{
    do {
    if (i==250000000) printf ("25 percent done:\n"); else
    if (i==500000000) printf("50 percent done:\n"); else
    if (i==750000000) printf("75 percent done:\n"); else
    if (i==1000000000) printf("100 percent done - Test completed!\n");
    i++; }
    
    while (i < 1000000001);
    return (1);
}


Moj je nesto kraci :D
[ Jbyn4e @ 30.10.2008. 11:32 ] @
@caslav - ionako se samo igramo ...

Inace kod koji sam ostavio nije moj, nasao sam ga na nekom forumu... sad da me ubijete gde..
[ Srđan Pavlović @ 30.10.2008. 11:35 ] @
Opusteno samo, valjda se nesto iz ovog i nauci ;)

Samo jos da nam Caslav optimizuje za Multi-Core, sad kad ima sors....... ;)
[ combuster @ 30.10.2008. 11:36 ] @
Ma bre smejali smo se kernel i ja preko irc-a, ciji ce da izbroji brze do milijardu... :D Hvala bogu tu je time da meri vreme :D
[ Jbyn4e @ 30.10.2008. 12:11 ] @
Zanimljivo je da kad se izbace vasi if-ovi, dobije se duplo brze :)

Citat:

time ./t1
100 percent done
real 0m3.646s
user 0m3.640s
sys 0m0.008s


A kad se umesto vasih if-ova, stavi nesto ovako, "elegantnije" resenje:
Code:

if (i%250000000 == 0) printf ("%i percent done\n",(i/10000000));

onda vremena odu u ....:
Citat:

time ./t1
25 percent done
50 percent done
75 percent done
100 percent done
real 0m17.261s
user 0m17.261s
sys 0m0.000s


I jos nesto - zavisi kako je kompajlirano (optimizacije):
Citat:

(64 bit, optimizovan sa O3)
~/test> gcc -m64 -O3 t1.c -o t1
~/test> time ./t1
100 percent done
real 0m1.282s
user 0m1.276s
sys 0m0.004s

(32 bit, optimizovan sa O3)
~/test> gcc -O3 t1.c -o t1
~/test> time ./t1
100 percent done
real 0m1.590s
user 0m1.584s
sys 0m0.008s

(64 bit, ne optimizovan)
~/test> gcc -m64 t1.c -o t1
~/test> time ./t1
100 percent done
real 0m3.356s
user 0m3.344s
sys 0m0.004s

[ Srđan Pavlović @ 30.10.2008. 12:31 ] @
Citat:
Zanimljivo je da kad se izbace vasi if-ovi, dobije se duplo brze :)


Pa normalno :)

To za optimizacije cu da pogledam kako je kod mene, ali na prvobitnom kodu, onakav kakav je.
Nije cilj da se sam kod optimizuje - da sam hteo da dobijem na brzini stavio bih 1000 a ne milijardu ;)
- ne tezi se tome, nije poenta sam kod - vec samo optimizacija u smislu da se
teret rada rasporedi na 2 ili vise jezgara, a ne da sav teret bude na jednom.
[ combuster @ 30.10.2008. 12:33 ] @
Pa probao sam ja i bez if-ova, naravno da ce brze da izbroji, ovako ima 4 uslova da prodje pri svakom uvecanju za jedan, ovo sto si ti uradio je isto ok ali je jos zahtevnije jer racuna ostatak pri deljenju (ovo sto smo mi uradili lici na boolean - true false kombinacija pa ide brze)...
[ Goran Rakić @ 30.10.2008. 12:45 ] @
Na stranu besmislenost testa (valjanom optimizacijom kompajlera ovaj loop prosto nestane), da bi opteretio oba jezgra moraš imati dve petlje koje se izvršavaju paralelno kao dve niti http://en.wikipedia.org/wiki/POSIX_Threads - pola izbrojiš u jednoj, pola na drugoj, istovremeno. Pri tome nemaš garanciju da će jednako brzo da broje (jer drugi programi uskaču čas na jedno, čas na drugo, čas na oba). Zato paralelno programiranje i jeste toliko teško.

E sada, neki mudri ljudi su smislili olakšice koje neke česte obrasce koji su idejno laki za paralelizaciju zapakuju u crnu kutijcu, pa tako imaš OpenMP (i podršku za to u savremenom GCCu - http://gcc.gnu.org/onlinedocs/libgomp/)...

Pogledaj primere na http://en.wikipedia.org/wiki/OpenMP
[ Srđan Pavlović @ 30.10.2008. 12:45 ] @
@JByn4e - E ovo vec radi, dakle samo optimizacija pri kompajliranju, kod je ISTI, skraceno vreme izvrsavanja:

Citat:
srdjan@Desktop:~/Programi$ time ./Test-Brzine-C
Program Test-Brzne (verzija u C-u) (TM) :)))
Startujte ga sa 'time ime_programa da bi merio brzinu.'
Merim skor za vas procesor...

25 posto kompletirano...
50 posto kompletirano...
75 posto kompletirano...
100 posto - Test kompletiran!

real 0m4.451s
user 0m4.408s
sys 0m0.004s
srdjan@Desktop:~/Programi$ rm a.out
srdjan@Desktop:~/Programi$ gcc -m64 -O3 s-test.c -o optimizovan
srdjan@Desktop:~/Programi$ time ./optimizovan
Program Test-Brzne (verzija u C-u) (TM) :)))
Startujte ga sa 'time ime_programa da bi merio brzinu.'
Merim skor za vas procesor...

25 posto kompletirano...
50 posto kompletirano...
75 posto kompletirano...
100 posto - Test kompletiran!

real 0m1.765s
user 0m1.756s
sys 0m0.004s
srdjan@Desktop:~/Programi$


(sve probe sa kompajlerom radim na originalnom kodu koji sam postovao)

@Goran Rakic - hvala za koristan info - mene je zanimalo da li se optimizacija ISTOG OVOG programa moze izvrsiti
samo switchevima gcc-a, i ocigledno moze (pokazano gore). Ovo sto si ti linkovao podrazumeva samo OPTIMIZOVANO
kodiranje, i tu je razlika:

#include <omp.h>
#include <stdio.h>

int main (int argc, char *argv[]) {
int th_id, nthreads;
#pragma omp parallel private(th_id)
{
th_id = omp_get_thread_num();
printf("Hello World from thread %d\n", th_id);
#pragma omp barrier
if ( th_id == 0 ) {
nthreads = omp_get_num_threads();
printf("There are %d threads\n",nthreads);
}
}
return 0;
}

...dakle optimizacije ukljucene u sam izvorni kod, sto je naravno uredu, ali nije ono sto mene zanima, tj - to je vec druga prica.

[Ovu poruku je menjao Kernel-1 dana 30.10.2008. u 13:57 GMT+1]
[ combuster @ 30.10.2008. 12:56 ] @
@goran rakic

Pa u pravu si 100%, test je besmislen, sto se tice nekog objektivnog benchmarking-a o tome ni govora nema nego smo pricali malo o mrtvim petljama, drz ne daj, mene ubi vb ovih dana pa rekoh onako iz zezancije da odradimo nesto u c-u... Promene radi :D Jedino sto ne bi pomogla nikakva optimizacija kompajlera pa da loop nestane jer se proveravaju vrednosti pri svakom inkrementu, mozda samo ubrzava dosta situaciju to sto se sve vuce iz i-cache-a na procesoru pa je mislim smesna skroz cela diskusija :D
[ Srđan Pavlović @ 30.10.2008. 13:00 ] @
Ma da, ovo jeste zaebacnija, ali ipak pokazuje razlike u brzini procesora, molim lepo ;)

- kad smo kod dead-loop-ova, sad nesto prckam malopre sa Lazarusom i negde se potkrade
jedan, morao je da radi hard-reset :)))


/edit: medjutim ona optimizacija gcc -m64 -O3 - i dalje se izvrsava samo na 1 jezgru, sad sam proverio,
(stavio sam 10 milijardi da mogu malo duze da pratim opterecenja jezgara malo duze, jer mi se milijarda izvrsi za manje od
2 sec, procesor ni ne stigne da se "zauka" ":)
- ali optimizacija u nekom drugom smislu postoji, vidi se razlika gore u vremenu izvrsavanja.
[ Srđan Pavlović @ 30.10.2008. 13:15 ] @
Citat:
da bi opteretio oba jezgra moraš imati dve petlje koje se izvršavaju paralelno kao dve niti


E to me je zanimalo, znaci sam gcc ne moze da radi optimizaciju ovog tipa, ako sam dobro shvatio.

[Ovu poruku je menjao Kernel-1 dana 30.10.2008. u 14:42 GMT+1]
[ Časlav Ilić @ 30.10.2008. 13:44 ] @
Citat:
Kernel-1: [...] Ovo sto si ti linkovao podrazumeva samo OPTIMIZOVANO kodiranje, i tu je razlika:


Upošljavanje više jezgara obično se ne zove baš optimizacijom, nego paralelizacijom. „Optimizacija za više jezgara“ zapravo je poboljšavanje paralelizacije, potrebno kada u početnoj izvedbi vreme izvršavanja nije srazmerno manje prema broju jezgara (npr. kada sa dva jezgra nije 2,0 puta brže, nego 1,4 puta).

A automatska paralelizacija je manje-više problem na nivou veštačke inteligencije, i više od toga, jer računar ne može znati preko programera kakve sve međuzavisnosti postoje u prirodi problema.

Za trivijalne slučajeve, kada je mali broj paralelnih jedinica (kao u višejezgarnom procesoru), i kada telo petlje ne zavisi od indeksa pored trenutnog, openMP omogućava vrlo laku paralelizaciju ako se jednojezgarni kôd napiše u odgovarajućem obliku:
Code:
$ cat test-01.c
#include <stdio.h>

int main ()
{
    long i;

    for (i = 1; i < 1000000001; ++i) {
        if (i==250000000) printf ("25 percent done:\n");
        else if (i==500000000) printf("50 percent done:\n");
        else if (i==750000000) printf("75 percent done:\n");
        else if (i==1000000000) printf("100 percent done - Test completed!\n");
    }

    return 0;
}
$ gcc test-01.c
$ time ./a.out
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real    0m3.577s
user    0m3.576s
sys     0m0.000s

i openMP-paralelni:
Code:
$ cat test-01-omp.c
#include <stdio.h>

int main ()
{
    long i;

    #pragma omp parallel for
    for (i = 1; i < 1000000001; ++i) {
        if (i==250000000) printf ("25 percent done:\n");
        else if (i==500000000) printf("50 percent done:\n");
        else if (i==750000000) printf("75 percent done:\n");
        else if (i==1000000000) printf("100 percent done - Test completed!\n");
    }

    return 0;
}
$ gcc test-01.c -fopenmp
$ time ./a.out
75 percent done:
25 percent done:
100 percent done - Test completed!
50 percent done:

real    0m1.475s
user    0m2.924s
sys     0m0.000s

Znači, samo dodat red #pragma omp ... pred zaglavlje petlje, i zastavica -fopenmp pri kompilaciji. Po tome što je, do na tačnost merenja, stvarno vreme dvostruko manje od korisničkog, vidi se da je paralelizacija sasvim efikasna i da nema šta da se optimizuje. (A zašto je korisničko sa dva jezgra manje od korisničkog s jednim, to je već softveraškija stvar nego što bih ja umeo da objasnim :)
[ Jbyn4e @ 30.10.2008. 13:57 ] @
Hm, zanimljivo je ovo paralelno programiranje :)

Vidim da si koristio izmenjen kod - for umesto do while. Zasto?

Btw. Kvad-kor sad radi malo bolje:

Citat:

gcc -fopenmp t1.c -o t1
time ./t1
50 percent done:
75 percent done:
25 percent done:
100 percent done - Test completed!

real 0m0.817s
user 0m3.208s
sys 0m0.000s

gcc t1.c -o t1
time ./t1
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m4.404s
user 0m4.396s
sys 0m0.000s


A i vidi se da radi sva 4 jezgra:
Citat:

Cpu0 : 66.7%us, 0.3%sy, 0.0%ni, 33.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu1 : 65.3%us, 0.7%sy, 0.0%ni, 34.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu2 : 65.4%us, 0.7%sy, 0.0%ni, 33.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Cpu3 : 66.1%us, 0.0%sy, 0.0%ni, 33.9%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

[ Časlav Ilić @ 30.10.2008. 14:11 ] @
Citat:
Jbyn4e: Vidim da si koristio izmenjen kod - for umesto do while. Zasto?


Zato što openMP direktive očekuju tačno određen oblik kôda — u ovom slučaju, kompilator mora da prepozna promenljivu koja je brojač petlje, njenu početnu i krajnju vrednost, da rezerviše njene lokalne kopije u nitima, da podeli opseg petlje među nitima, i šta ga znam šta još.

Zato lično i ne volim openMP, mnogo crne magije :)
[ Srđan Pavlović @ 30.10.2008. 14:12 ] @
^ Da, ako menjate izvorni kod naglasite, meni je promaklo, ali je Jbyn4e primetio.

Inace, Caslave, hvala puno na ovim primerima koda i objasnjenju za optimizacije, bas su dobri i jednostavni, a bogami i poucni :)

Sad se bas lepo vidi ravnomerna rasporedjenost na jezgra.

/edit: odredjeni deo proc. vremena se gubi i na ispisivanje onih glupsti (original kod) pre samog testa ;)

/edit2: pardon, ne optimizacije, vec paralelizacije :) - vec sam jednom uneo zabunu, da ne unosim opet :)

[Ovu poruku je menjao Kernel-1 dana 30.10.2008. u 15:38 GMT+1]
[ Branimir Maksimovic @ 31.10.2008. 01:28 ] @
Cudi me da niko nije primetio da paralelizovana verzija ne radi korektno.
printf-ovi moraju da ispisu u redosledu koji je zadat a ne neki random
slucaj i treba da odliskaju kad se doslo do 25,50,75 i sto posto
takodje , inace paralelizacija ne znaci i korektan program ;)

Pozdrav!

[ Jbyn4e @ 31.10.2008. 07:57 ] @
Vidju stvarno :)

Nisam obratio paznju na taj detalj, vise mi je bilo zanimljivo kako rade sva 4 jezgra :)

Bice da je to do one "crne magine" openMP-a
[ combuster @ 31.10.2008. 09:08 ] @
Ja se izvinjavam, izasao novi ubuntu, pa dok sam ispodesavao i slavim danas ali cu da se bacim na to sutra prepodne da vidim je li openMP stvarno voodoo orijentisan :D
[ Srđan Pavlović @ 31.10.2008. 10:14 ] @
Citat:
Branimir Maksimovic: Cudi me da niko nije primetio da paralelizovana verzija ne radi korektno.
printf-ovi moraju da ispisu u redosledu koji je zadat a ne neki random
slucaj i treba da odliskaju kad se doslo do 25,50,75 i sto posto
takodje , inace paralelizacija ne znaci i korektan program ;)

Pozdrav!


Huh...ja sam samo pogledao one procente opterecenosti jezgra koje je postovao
jbyn4e, pa reko nema potrebe da probavam ako radi... :)
Kad ono... :) - i sto rece combuster izasao novi Ubuntu... odvuce paznju od ovog bitnog projekta... :))
[ Branimir Maksimovic @ 04.11.2008. 10:44 ] @
Evo i ja malo da modifikujem benchmark. Ovaj przi 256 mega rama i radi u 4 threada.
Radi korektno na izlazu, tj ispisuje 25,50,75, 100 kako zavrsi deo po deo ;)

Probajte posto se sada testira i brzina memorije.

Code:

#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>

#define BLCK_SIZE 16777216

sem_t sema,sema1;

void* tf(void* p)
{
  int j = 80;
  while(j--)
  {
    int i = 0;
    for(;i<BLCK_SIZE;++i)
    {
      *((int*)p+i) = i;
    }
    if(j%20==0)
    {
      sem_post(&sema);
      sem_wait(&sema1);
    }
  }
  return 0;
}

int main ()
{
  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);
  
  int* mem = calloc(4,BLCK_SIZE*sizeof(int));
  if(!mem)
  {
    printf("not enough memory\n");
    return 0;
  }
  pthread_t tid[4];

  pthread_create(tid+0,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+1,0,tf,mem+1*BLCK_SIZE);
  pthread_create(tid+2,0,tf,mem+2*BLCK_SIZE);
  pthread_create(tid+3,0,tf,mem+3*BLCK_SIZE);

  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("25 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("50 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("75 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("100 percent done - Test completed!\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  pthread_join(tid[0],NULL);
  pthread_join(tid[1],NULL);
  pthread_join(tid[2],NULL);
  pthread_join(tid[3],NULL);

  free(mem);
  sem_destroy(&sema);
  sem_destroy(&sema1);

  return 0;
}



Kompajlira se sa

Code:


gcc -Wall -lpthread -O2 ime.c -o ime



bmaxa@maxa:~$ gcc -Wall -lpthread -O2 omp.c -o omp
bmaxa@maxa:~$ time ./omp
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m6.677s
user 0m11.761s
sys 0m0.132s

Sad bi quadovi trebali da budu najbrzi.

Pozdrav!

[ Jbyn4e @ 04.11.2008. 11:41 ] @
Hm, iz nekog razloga nisu, mozda je memorija problem - a ne bi smela da bude...
AMD Athlon(tm) 64 X2 Dual Core Processor 4600+ (koji pritom jos i radi nesto), 4Gb RAM, gcc (SUSE Linux) 4.3.1
Citat:

time ./omp
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m6.933s
user 0m12.397s
sys 0m0.356s

i quad Intel(R) Xeon(R) CPU X3323 @ 2.50GHz koji pritom ne radi nista..., 6Gb RAM, gcc (SUSE Linux) 4.3.1
Citat:

time ./omp
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m9.983s
user 0m38.330s
sys 0m0.080s

i
AMD Athlon(tm) XP 2000+, 1Gb RAM, gcc (GCC) 3.3.1 (SuSE Linux)
Citat:

time ./omp
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m47.767s
user 0m47.348s
sys 0m0.267s
[ Branimir Maksimovic @ 04.11.2008. 11:53 ] @
Ovde se vec vidi superiornost athlona x2 u odnosu na intela. Pogledaj tvoj athlon
x2 4600 ima skoro iste performanse u pogledu memorije ko moj overklokovani intel e8400 na 3.6ghz
i to 400mhz bus isto oveklokovan. Quad takodje izgleda pokazuje da spori intelov bus uzima danak.
Znaci kad je sve u cache-u intel dobija ali kad se memorija malo povuce onda amd
kompenzuje. Znaci intel amd 1-1 ;)

Pozdrav!
[ Jbyn4e @ 04.11.2008. 13:17 ] @
Hm, ajde jos malo. Ispade da je dual core brzi od quad-a.
Intel(R) Core(TM)2 Duo CPU E8200 @ 2.66GHz, 4Gb RAM, gcc (GCC) 4.2.1 (SUSE Linux)
Citat:

time ./omp
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m8.344s
user 0m16.073s
sys 0m0.252s


i jedan jaci amd
AMD Athlon(tm) 64 X2 Dual Core Processor 6000+, 4Gb RAM, gcc (SUSE Linux) 4.3.1 20080507 (prerelease)
Citat:

time ./omp
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m6.527s
user 0m12.065s
sys 0m0.356s


Ispada da AMD nadoknadjuje razlike u brzini boljom komunikacijom sa memorijom?

[ Branimir Maksimovic @ 04.11.2008. 13:30 ] @
Nije dual brzi od quada nego je problem sto je memory bus za quad isti kao na dual-u, pa aplikacija
koja zesce drlja po ramu jednostavno pokazuje da na quadu cak i gubis zato sto
se procesori kolju oko rama, tj bus mu je bottleneck.

Amd ima brzi bus od intela- i u ovom benchu je presudan faktor brzina
bus-a a ne ghz ili performanse samog jezgra.
Tvoj quad ima front sajd bas od 333mhz i to ga kolje, dok amd-ovi imaju interni memorijski kontroler
pa ne znam kako se oni rejtuju, ali ocigledno negde oko 400mhz posto sam na tolko overklokovao
svoj intel. Sama ghz-aza ne utice toliko.
Voleo bih da vidim nekog sa phenom-om x4 u ganged i not ganged modu. U ovom bench-u quad phenom
bi trebao sve da oduva, naravno ukoliko mu je bas znatno brzi.

Pozdrav!
[ Srđan Pavlović @ 05.11.2008. 16:59 ] @
srdjan@Zverko:~$ time ./test-2-run (Branimirov test)
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m8.495s
user 0m15.769s
sys 0m0.128s
srdjan@Zverko:~$

Intel C2D, E6850 3Ghz (stock), 4mb cache, 6000 bogomips.
[ combuster @ 06.11.2008. 10:02 ] @
@branimir

Cekaj, ti si zaglavlje semaphore koristio za signalizaciju kada je funkcija tf obavila posao da bi ispisao pravilno procente, kreirao si cetiri thread-a i prosledio argument mem+0*BLCK_SIZE funkciji tf u prvom thread-u itd... Znas sta mi jedino nije jasno (makar se nadam da mi samo to nije jasno :D)?

void* tf(void* p)
{
int j = 80;
while(j--)
{
int i = 0;
for(;i<BLCK_SIZE;++i)
{
*((int*)p+i) = i;
}
if(j%20==0)
{
sem_post(&sema);
sem_wait(&sema1);
}
}
return 0;
}


Ovde si proveravao ostatak da bi prosledio signal za semafor na svakih 25% a mem+0*BLCK_SIZE se prosledjuje promenljivoj p. E sad sta mene kopka:
*((int*)p+i) = i; dakle (int*)p + i ti daje memorijsku adresu koja sadrzi integer vrednost koja se dodeljuje promenljivoj i i koja se uvecava za jedan sve dok ne dostigne deklarisani block size ili ide kontra - (int*)p + i ti daje integer vrednost cija memorijska adresa se dodeljuje promenljivoj i i ta adresa se uvecava za jedan dok ne dostigne BLCK_SIZE?

Malko sam se pogubio u pointerima...
[ Branimir Maksimovic @ 06.11.2008. 10:42 ] @
U c-u indeksiranje ide preko pointer aritmetike, dakle,
Code:

((int*)p)[i]

je ekvivalentno *((int*)p+i),
pa (int*)p+i daje pointer, a to ti je memorijsak adresa. Operator * daje sadrzaj adrese, tj dereferencira
pointer.

Sto se semafora tice, da, na svakih 25% f-ja prvo signalizira da je zavrsila a onda ceka
na signal da nastavi dalje.

Jel sad jasnije?


Pozdrav!
[ combuster @ 06.11.2008. 11:09 ] @
Pointer od pointera :D Ok, sad mi je jasno, znaci ipak u i smestas sadrzaj adrese a ne samu adresu...
Thnx...

A evo rezultata...

combuster@vostro:~/test$ time ./test
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m11.831s
user 0m22.529s
sys 0m0.148s


Mobile Core2Duo T5670 1.8 GHz, 2GB RAM-a...

Ako hoces 3GB RAM-a da alociras stavlja se pri definiciji BLCK_SIZE vrednost od 201326592 jel tako?

[Ovu poruku je menjao combuster dana 06.11.2008. u 12:43 GMT+1]
[ Srđan Pavlović @ 06.11.2008. 11:45 ] @
srdjan@Zverko:~$ gcc -Wall -lpthread -O2 test-2.c -o test-2-run
srdjan@Zverko:~$ time ./test-2-run
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 1m39.985s
user 3m9.312s
sys 0m1.908s
srdjan@Zverko:~$


201326592 BLCK_SIZE


Bogami, sad sam cuo i ventilator iz kucista ;)

[ combuster @ 06.11.2008. 11:57 ] @
Code:


#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>

#define BLCK_SIZE 16777216

sem_t sema,sema1;

void* tf(void* p)
{
  int j = 80;
  while(j--)
  {
    int i = 0;
    for(;i<BLCK_SIZE;++i)
    {
      *((int*)p+i) = i;
    }
    if(j%20==0)
    {
      sem_post(&sema);
      sem_wait(&sema1);
    }
  }
  return 0;
}

int main ()
{
  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);
  
  int* mem = calloc(4,BLCK_SIZE*sizeof(int));
  int d = 0.000015259 * BLCK_SIZE;
  if(!mem)
  {
    printf("not enough memory\n");
    return 0;
  }
  else printf("program allocated %d MB of RAM\n", d);

  pthread_t tid[4];

  pthread_create(tid+0,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+1,0,tf,mem+1*BLCK_SIZE);
  pthread_create(tid+2,0,tf,mem+2*BLCK_SIZE);
  pthread_create(tid+3,0,tf,mem+3*BLCK_SIZE);

  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("25 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("50 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("75 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("100 percent done - Test completed!\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  pthread_join(tid[0],NULL);
  pthread_join(tid[1],NULL);
  pthread_join(tid[2],NULL);
  pthread_join(tid[3],NULL);

  free(mem);
  sem_destroy(&sema);
  sem_destroy(&sema1);

  return 0;
}


Ispisace vam koliko memorije alocira...
Sad cu da vidim da napravim i da korisnik ukuca kolicinu memorije za alokaciju... U MB...
[ Srđan Pavlović @ 06.11.2008. 12:03 ] @
ajd da neko implementira u sam program merenje vremena da se izbegne ovo startovanje sa time...


Evo 64-bit izvrsni samo za 201326592 BLCK_SIZE, na srpskom :D

srdjan@Zverko:~$ time ./test-2-run
Alocirano 3072 MB RAM memorije...
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test kompletiran!

real 1m40.002s
user 3m9.208s
sys 0m1.948s
srdjan@Zverko:~$

/edit: parcijalno prevedeno... :D

[Ovu poruku je menjao Kernel-1 dana 06.11.2008. u 13:17 GMT+1]
[ combuster @ 06.11.2008. 12:14 ] @

int BLCK_SIZE;
int memory;
printf("Unesite vrednost memorije za alokaciju u MB:");
scanf("%d", &memory);
BLCK_SIZE = memory * 65536;
return BLCK_SIZE;


e sad kako da namestim da mi bude public BLCK_SIZE posto ga koristis i u tf i u main, to mi je sad problematicno...
[ combuster @ 06.11.2008. 16:30 ] @
Code:

#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>

sem_t sema,sema1;

int memparse ();
int memload ();

int memparse()
{
  int d;
  int i;
  i = memload ();
  d = i * 65536;
  return d;
}

int memload()
{
  int memory;
  scanf("%d", &memory);
  return memory;
}

void* tf(void* p)
{
  int j = 80;
//  KAKO DA UCITAM BLCK_SIZE IZ MAIN FUNKCIJE???
  while(j--)
  {
    int i = 0;
    for(;i<BLCK_SIZE;++i)
    {
      *((int*)p+i) = i;
    }
    if(j%20==0)
    {
      sem_post(&sema);
      sem_wait(&sema1);
    }
  }
  return 0;
}

int main ()
{
  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);
  int BLCK_SIZE;
  printf("Unesite vrednost memorije za alokaciju u MB:");
  BLCK_SIZE = memparse ();
  int* mem = calloc(4,BLCK_SIZE*sizeof(int));
  if(!mem)
  {
    printf("not enough memory\n");
    return 0;
  }
  pthread_t tid[4];

  pthread_create(tid+0,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+1,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+2,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+3,0,tf,mem+0*BLCK_SIZE);

  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("25 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("50 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("75 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("100 percent done - Test completed!\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  pthread_join(tid[0],NULL);
  pthread_join(tid[1],NULL);
  pthread_join(tid[2],NULL);
  pthread_join(tid[3],NULL);

  free(mem);
  sem_destroy(&sema);
  sem_destroy(&sema1);

  return 0;
}


Eto pitanje je u samom kodu :D
KAKO DA UCITAM BLCK_SIZE IZ MAIN FUNKCIJE U TF FUNKCIJU *(:()
[ k0m1kku @ 06.11.2008. 19:58 ] @
2 x Intel(R) Xeon(TM) CPU 3.00GHz
Motherboard Intel S5000PAL

Citat:
real 0m4.051s
user 0m4.050s
sys 0m0.001s
[ Branimir Maksimovic @ 06.11.2008. 20:13 ] @
combuster, samo stavi definiciju BLOCK_SIZE-a na pocetak tj kod semafora da bude globalna, bice dovoljno ;)

Pozdrav!
[ combuster @ 06.11.2008. 22:22 ] @
Code:

#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>

sem_t sema,sema1;
int BLCK_SIZE;

int memparse ();
int memload ();

int memparse()
{
  int d;
  int i;
  i = memload ();
  d = i * 65536;
  return d;
}

int memload()
{
  int memory;
  scanf("%d", &memory);
  return memory;
}

void* tf(void* p)
{
  int j = 80;
  while(j--)
  {
    int i = 0;
    for(;i<BLCK_SIZE;++i)
    {
      *((int*)p+i) = i;
    }
    if(j%20==0)
    {
      sem_post(&sema);
      sem_wait(&sema1);
    }
  }
  return 0;
}

int main ()
{
  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);
  int mb;
  printf("Unesite vrednost memorije za alokaciju u MB:");
  BLCK_SIZE = memparse ();
  mb = 0.000015259 * BLCK_SIZE;
  int* mem = calloc(4,BLCK_SIZE*sizeof(int));
  if(!mem)
  {
    printf("not enough memory\n");
    return 0;
  }
  else printf("program allocated %d MB of RAM\n", mb);

  pthread_t tid[4];

  pthread_create(tid+0,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+1,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+2,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+3,0,tf,mem+0*BLCK_SIZE);

  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("25 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("50 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("75 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("100 percent done - Test completed!\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  pthread_join(tid[0],NULL);
  pthread_join(tid[1],NULL);
  pthread_join(tid[2],NULL);
  pthread_join(tid[3],NULL);

  free(mem);
  sem_destroy(&sema);
  sem_destroy(&sema1);

  return 0;
}


Hvala Branimire, hvala, e sad jos samo da integrisemo merenje vremena u kodu, ja mislim da ima jedan header koji sadrzi funkcije za rad sa vremenom, provericemo...
Inace sada program pita korisnika koliko ram-a da alocira (radi provereno)...
[ Srđan Pavlović @ 06.11.2008. 22:37 ] @
Ovaj kod kod mene se zaglavi ako stavim manje od 20 (stane na 75%) i moram Ctrl-C.

Sa 19 mi zaglavi (MB), ako stavim 20 i vise, onda prolazi.
[ combuster @ 06.11.2008. 22:54 ] @
Ovo je sad islo mnogo lakse... Sada meri i vreme...

Code:

#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>

time_t timer1,timer2;
struct tm *tarray1,*tarray2;
sem_t sema,sema1;
int BLCK_SIZE;

int memparse ();
int memload ();

int memparse()
{
  int d;
  int i;
  i = memload ();
  d = i * 65536;
  return d;
}

int memload()
{
  int memory;
  scanf("%d", &memory);
  return memory;
}

void* tf(void* p)
{
  int j = 80;
  while(j--)
  {
    int i = 0;
    for(;i<BLCK_SIZE;++i)
    {
      *((int*)p+i) = i;
    }
    if(j%20==0)
    {
      sem_post(&sema);
      sem_wait(&sema1);
    }
  }
  return 0;
}

int main ()
{
  int min1, sec1, min2, sec2;
  timer1 = time(NULL);
  tarray1 = localtime(&timer1);
  min1 = tarray1->tm_min;
  sec1 = tarray1->tm_sec;  
  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);
  int mb;
  printf("Enter the amount of memory to be allocated in MB:");
  BLCK_SIZE = memparse ();
  mb = 0.000015259 * BLCK_SIZE;
  int* mem = calloc(4,BLCK_SIZE*sizeof(int));
  if(!mem)
  {
    printf("not enough memory\n");
    return 0;
  }
  else printf("program allocated %d MB of RAM\n", mb);

  pthread_t tid[4];

  pthread_create(tid+0,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+1,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+2,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+3,0,tf,mem+0*BLCK_SIZE);

  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("25 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("50 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("75 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("100 percent done - Test completed!\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  pthread_join(tid[0],NULL);
  pthread_join(tid[1],NULL);
  pthread_join(tid[2],NULL);
  pthread_join(tid[3],NULL);

  free(mem);
  sem_destroy(&sema);
  sem_destroy(&sema1);
  timer2 = time(NULL);
  tarray2 = localtime(&timer2);
  min2 = tarray2->tm_min;
  sec2 = tarray2->tm_sec;
  printf ("Time of execution is %d min : %d sec\n", min2-min1,sec2-sec1);
  return 0;
}


Cheers 4 branimir, kernel-1, jbyn4e, lil' o me and everyone that tested this peace of code... :D
[ Srđan Pavlović @ 06.11.2008. 23:00 ] @
radi, samo sa vise MB, sad mi je zakucao na 75% i na 30mb....
...vreme meri OK, ako moze stotinke da se mere jos bolje, samo sekunde su malo grube za ovaj sport ;)

(jbt, ja samo narucujem) ;)
[ combuster @ 06.11.2008. 23:04 ] @
Da, zeza sa manje MB, sumnjam na semaforcice ali ne mora da znaci... Ohoho jos jedna greska, hehehehe izlazi mi -9 sec sto znaci da moram da stavim ovo kao apsolutnu vrednost... lupetam, samo treba sekunde da oduzmem i ostatak na minute :D, opet lupetam, parsujem vrednost time-a... Moram da razmislim malo...
[ combuster @ 06.11.2008. 23:32 ] @
Evo ga ljudi konacno finito... Problem sa alociranjem MB-a ostaje ali je merenje vremena ispravljeno. Sad i ako ga pokrenete ko sto kaze nas narod u minut do 12 radice ispravno... :D Evo ga RC:

Code:

#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>

time_t timer1,timer2;
struct tm *tarray1,*tarray2;
sem_t sema,sema1;
int BLCK_SIZE;

int memparse ();
int memload ();

int memparse()
{
  int d;
  int i;
  i = memload ();
  d = i * 65536;
  return d;
}

int memload()
{
  int memory;
  scanf("%d", &memory);
  return memory;
}

void* tf(void* p)
{
  int j = 80;
  while(j--)
  {
    int i = 0;
    for(;i<BLCK_SIZE;++i)
    {
      *((int*)p+i) = i;
    }
    if(j%20==0)
    {
      sem_post(&sema);
      sem_wait(&sema1);
    }
  }
  return 0;
}

int main ()
{
  int min1,min2,sec1,sec2,minf,secf;
  timer1 = time(NULL);
  tarray1 = localtime(&timer1);
  min1 = tarray1->tm_min;
  sec1 = tarray1->tm_sec;  
  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);
  int mb;
  printf("Enter the amount of memory to allocate in MB:");
  BLCK_SIZE = memparse ();
  mb = 0.000015259 * BLCK_SIZE;
  int* mem = calloc(4,BLCK_SIZE*sizeof(int));
  if(!mem)
  {
    printf("not enough memory\n");
    return 0;
  }
  else printf("program allocated %d MB of RAM\n", mb);

  pthread_t tid[4];

  pthread_create(tid+0,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+1,0,tf,mem+1*BLCK_SIZE);
  pthread_create(tid+2,0,tf,mem+2*BLCK_SIZE);
  pthread_create(tid+3,0,tf,mem+3*BLCK_SIZE);

  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("25 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("50 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("75 percent done:\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf("100 percent done - Test completed!\n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  pthread_join(tid[0],NULL);
  pthread_join(tid[1],NULL);
  pthread_join(tid[2],NULL);
  pthread_join(tid[3],NULL);

  timer2 = time(NULL);
  tarray2 = localtime(&timer2);
  min2 = tarray2->tm_min;
  sec2 = tarray2->tm_sec;
  if (min2 < min1) 
{
  minf = min2 + 60 - min1;
}
  else 
  minf = min2 - min1;
  
  if (sec2 < sec1) 
{
  secf = sec2 + 60 - sec1;
  minf -= 1;
}  
  else
  secf = sec2 - sec1;
  printf ("Time of execution is %d min : %d sec\n",minf,secf);
  free(mem);
  sem_destroy(&sema);
  sem_destroy(&sema1);
  return 0;
}


EVO SAD SVE RADI !!! Izmenjeno, ja sam napravio bug u izmenama u pthread-ovima, pokusavao sam da prosledim BLCK_SIZE funkciji tf kao atribut ali pthread_create moze da prosledi samo jedan argument i onda sam tu vracao nesto i bilo je mem+0*BLCK_SIZE na sva cetiri thread-a umesto da inkrementira za 1...

Moze se reci da je ovo sad final release...

[Ovu poruku je menjao combuster dana 07.11.2008. u 01:06 GMT+1]
[ Srđan Pavlović @ 06.11.2008. 23:40 ] @
srdjan@Zverko:~$ ./test-2-run
Unesite vrednost memorije za alokaciju u MB:4096
program allocated 4096 MB of RAM
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!
Time of execution is 2 min : 17 sec
srdjan@Zverko:~$


Zauzece se cudno ponasa... recimo pise da imam free 3348MB trenutno.
Pustim test sa 348mb, i dok radi, pise 3260mb free (tako nesto), ili kada
stavim 1024 mb, pise da tokom rada testa zauzima samo oko 280mb rama... nesto se tu optimizuje, ili se ne alocira dobro.

[Ovu poruku je menjao Kernel-1 dana 07.11.2008. u 00:56 GMT+1]

/edit: provera fixed coda.. :)

[Ovu poruku je menjao Kernel-1 dana 07.11.2008. u 01:04 GMT+1]

/edit: Sada radi OK, imao sam 3346mb free, zadao mu 346, tokom rada 3000mb mem free - bravo :)

[Ovu poruku je menjao Kernel-1 dana 07.11.2008. u 01:07 GMT+1]
[ Srđan Pavlović @ 07.11.2008. 01:14 ] @
Evo i prevedene verzije, i dodao sam samo ogranicenja za min i max mem unos, ostaje pitanje zasto program ne radi sa nizim vrednostima unosa (oko 30 i nize),
i da se implementira preciznije merenje vremena (bar stotinke):

Code:

#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>

time_t timer1,timer2;
struct tm *tarray1,*tarray2;
sem_t sema,sema1;
int BLCK_SIZE;

int memparse ();
int memload ();

int memparse()
{
  int d;
  int i;
  i = memload ();
  d = i * 65536;
  return d;
}

int memload()
{
  int memory;
  scanf("%d", &memory);
  return memory;
}

void* tf(void* p)
{
  int j = 80;
  while(j--)
  {
    int i = 0;
    for(;i<BLCK_SIZE;++i)
    {
      *((int*)p+i) = i;
    }
    if(j%20==0)
    {
      sem_post(&sema);
      sem_wait(&sema1);
    }
  }
  return 0;
}

int main ()
{
  int min1,min2,sec1,sec2,minf,secf;
  timer1 = time(NULL);
  tarray1 = localtime(&timer1);
  min1 = tarray1->tm_min;
  sec1 = tarray1->tm_sec;  
  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);
  int mb;
  printf ("\n"); 
  printf("Unesite koliko memorije alocirate za test (64 do 512 MB):");
  BLCK_SIZE = memparse ();
  mb = 0.000015259 * BLCK_SIZE;
  int* mem = calloc(4,BLCK_SIZE*sizeof(int));

  if (mb < 64) 
{
printf("\n"); 
printf("Postavljena vrednost nije dozvoljena.\n"); 
printf("\n");
return 0;
}

if (mb > 512)
{
printf("\n");
printf("Postavljena vrednost nije dozvoljena.\n"); 
printf("\n");
return 0;
}

  
  if(!mem)
  {
    printf("Nema dovoljno memorije.\n");
    return 0;
  }
  else printf("Program je alocirao %d MB RAM-a.\n", mb);

  pthread_t tid[4];

  pthread_create(tid+0,0,tf,mem+0*BLCK_SIZE);
  pthread_create(tid+1,0,tf,mem+1*BLCK_SIZE);
  pthread_create(tid+2,0,tf,mem+2*BLCK_SIZE);
  pthread_create(tid+3,0,tf,mem+3*BLCK_SIZE);

  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("25 procenata komletirano... \n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("50 procenata komletirano... \n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("75 procenata komletirano... \n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  sem_wait(&sema);
  printf ("100 procenata komletirano! \n");
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  sem_post(&sema1);
  
  pthread_join(tid[0],NULL);
  pthread_join(tid[1],NULL);
  pthread_join(tid[2],NULL);
  pthread_join(tid[3],NULL);

  timer2 = time(NULL);
  tarray2 = localtime(&timer2);
  min2 = tarray2->tm_min;
  sec2 = tarray2->tm_sec;
  if (min2 < min1) 
{
  minf = min2 + 60 - min1;
}
  else 
  minf = min2 - min1;
  
  if (sec2 < sec1) 
{
  secf = sec2 + 60 - sec1;
  minf -= 1;
}  
  else
  secf = sec2 - sec1;
  printf ("\n");
  printf ("Vreme izvrsavanja je %d minuta i %d sekundi.\n",minf,secf);
  printf ("\n");
  free(mem);
  sem_destroy(&sema);
  sem_destroy(&sema1);
  return 0;
}


U attachment-u je izvrsna verzija ovoga za 64-bit sistem, program se vise ne mora startovati sa "time" (10x to combuster) :)

Interesantno je pratiti i krivulju rasta potrebnog vremena kada se kolicina memorije uduplava:

Na mom racunaru izgleda ovako: 64mb --> 4 sekunde, 128mb --> 10 sekundi, 256mb --> 14 sekundi, 512mb --> 20 sekundi.

/edit: btw, jel ima neko eeeAsus-a za probu? :D

[Ovu poruku je menjao Kernel-1 dana 07.11.2008. u 06:13 GMT+1]
[ Tyler Durden @ 07.11.2008. 08:05 ] @
Stavljajte kod samo u attachmentu, radi preglednosti....
[ combuster @ 07.11.2008. 09:44 ] @
Aha, jesmo preterali, potkrali se neki bug-ovi a mi svaki put ko blesavi:
Code:

150 linija koda


Pa nemamo vise ni da postujemo kodove jer smo zavrsili, dakle jos jednom source i bin evo ga ovaj put u attachmentu i to je to....
[ Branimir Maksimovic @ 07.11.2008. 12:26 ] @
Za malu vremensku rezoluciju koristite clock() funkciju i clock_t tip pa rezultat
delite sa CLOCKS_PER_SEC kako bi dobili rezoluciju u sekundama.
Sto se tice problema sa manje od 30mb to je zato sto ako neki thread zavrsi
dva puta pre nego neki drugi a 30mb se zavrsi za malo vremena
dolazi do greske jer se koriste samo dva semafora, tj neki thread
ce biti aktiviran dva puta dok neki nece pa ce izostati potrebna
4 sem_posta kako bi main thread nastavio da signalizira.
U tom slucaju treba staviti po par semafora za svaki thread, a same semafore i mem
blok proslediti thread f-ji preko strukture, recimo struct Data{ sem_t sem,sem1; int* mem; };

Pozdrav!
[ mjux @ 07.11.2008. 13:00 ] @
a da neko stavi exe za windows... ili da napise kompajler koji je koristen posto meni nece da se kompajlira... imam msi wind pa bi to da testiram :)
[ Tyler Durden @ 07.11.2008. 13:16 ] @
Ne furamo windows na ovom forumu... :)
Salim se.

Bilo bi zanimljivo da vidimo ista masina, isti kod - kakve bi razlike bile u brzini izvrsavanja na linuxu i na windowsu.
[ Srđan Pavlović @ 07.11.2008. 13:30 ] @
@mjux - http://www.q-software-solutions.de/pub/lccwin32.exe - skini kompajler ovaj ili neki drugi free izgooglaj, pa kompajliraj na windozi.
[ combuster @ 07.11.2008. 13:42 ] @
Ja skidam sad minigw i trebalo bi da do veceras ispostujem 32-bit exe...
[ Srđan Pavlović @ 07.11.2008. 14:29 ] @
-lpthread switch daje podrsku za koriscenje thread-ova koji se u ovom
kodu koriste, pa ako neko bude kompajlirao za windows pazite i na to
koji je kompajler i sta treba ukljuciti za ovo na njemu za ovu podrsku.

(-Wall je manje bitna opcija cini mi se, samo vezana za neka dodatna upozorenja oko kompajliranja)
[ combuster @ 07.11.2008. 15:57 ] @
Ne moze... Losi su pthread header-i za windows, semaphore.h je lose napisan i to kolje kompajliranje... Probao sam sa Bloodshed, cygwin, lcc32, visual studiom (skidao sam header-e sa neta) i ne vredi. Uvek zeza semaphore.h koji sam skidao sa dva izvora, jedan direktno sa net-a a drugi preko paketa iz bloodshed-a! Jedino da probam da napravim exe iz linux-a...
Evo i iz linuxa sa mingw-om

Code:

combuster@vostro:~/test$ i586-mingw32msvc-gcc -x c test.c
/tmp/ccGW9wEm.o:test.c:(.text+0x92): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0xa2): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x118): undefined reference to `_sem_init'
/tmp/ccGW9wEm.o:test.c:(.text+0x12c): undefined reference to `_sem_init'
/tmp/ccGW9wEm.o:test.c:(.text+0x1d5): undefined reference to `_pthread_create'
/tmp/ccGW9wEm.o:test.c:(.text+0x1f9): undefined reference to `_pthread_create'
/tmp/ccGW9wEm.o:test.c:(.text+0x21d): undefined reference to `_pthread_create'
/tmp/ccGW9wEm.o:test.c:(.text+0x248): undefined reference to `_pthread_create'
/tmp/ccGW9wEm.o:test.c:(.text+0x258): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x268): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x278): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x288): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x2a8): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x2b8): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x2c8): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x2d8): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x2e8): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x2f8): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x308): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x318): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x338): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x348): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x358): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x368): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x378): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x388): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x398): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x3a8): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x3c8): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x3d8): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x3e8): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x3f8): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x408): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x418): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x428): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x438): undefined reference to `_sem_wait'
/tmp/ccGW9wEm.o:test.c:(.text+0x458): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x468): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x478): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x488): undefined reference to `_sem_post'
/tmp/ccGW9wEm.o:test.c:(.text+0x499): undefined reference to `_pthread_join'
/tmp/ccGW9wEm.o:test.c:(.text+0x4aa): undefined reference to `_pthread_join'
/tmp/ccGW9wEm.o:test.c:(.text+0x4bb): undefined reference to `_pthread_join'
/tmp/ccGW9wEm.o:test.c:(.text+0x4cc): undefined reference to `_pthread_join'
/tmp/ccGW9wEm.o:test.c:(.text+0x589): undefined reference to `_sem_destroy'
/tmp/ccGW9wEm.o:test.c:(.text+0x599): undefined reference to `_sem_destroy'
collect2: ld returned 1 exit status


Slicno mi javlja i na windows-u kada resim probleme sa semaphore.h i sl...

[Ovu poruku je menjao combuster dana 07.11.2008. u 17:24 GMT+1]
[ slobapet @ 09.11.2008. 22:00 ] @
hmmm.. meni na ubuntu 32bit 8.04 samo opterecuje jedno jezgro, i to konstantno, znaci ne prebacuje na drugo....
da li je to do koda ne znam, jer ja ne znam da iskompajliram kod mene, ne bavim se toliko time ali resio da probam ...
[ Srđan Pavlović @ 10.11.2008. 02:44 ] @
Napisi koji ti je tacno procesor, koji su rezultati, i koji si od ovih
programa pokrenuo koje smo do sada kacili.

(Ako je 32-bit masina, onda skini i pokreni poslednji fajl uz poruku koji je okacio combuster,
a ako je 64-bit masina, onda skini i pokreni poslednji fajl koji sam ja okacio uz svoju poruku)

Ako nisi siguran koji ti je procesor pokreni u konzoli ove 2 komande:

cat /proc/cpuinfo | grep model
cat /proc/cpuinfo | grep cache


i prenesi sta tacno dobijes kada ih pokrenes.


Dobar program za pracenje opterecenja koji lepo graficki prikazuje opterecenja po jezgrima je gkrellm.
Instaliras ga sa:

sudo apt-get install gkrellm

Jos jednom uploadujem konacnu verziju za 64 bit-a - V 1.0.0 - minorne izmene kozmeticke prirode (source i kompajlirana izvrsna verzija ko nece da kompajlira sam):

Izgleda ovako:

Code:

srdjan@Zverko:~$ ./ProcTest64-v1.0.0 
Test Brzine Procesora - 64-bit - Verzija 1.0.0  - [ES]

Unesite koliko memorije alocirate za test (64 do 512 MB):32

Postavljena vrednost nije dozvoljena. Minimum je 64.

srdjan@Zverko:~$ ./ProcTest64-v1.0.0 
Test Brzine Procesora - 64-bit - Verzija 1.0.0  - [ES]

Unesite koliko memorije alocirate za test (64 do 512 MB):513

Postavljena vrednost nije dozvoljena. Maksimum je 512.

srdjan@Zverko:~$ ./ProcTest64-v1.0.0 
Test Brzine Procesora - 64-bit - Verzija 1.0.0  - [ES]

Unesite koliko memorije alocirate za test (64 do 512 MB):128
Program je alocirao 128 MB RAM-a.
25 procenata komletirano... 
50 procenata komletirano... 
75 procenata komletirano... 
100 procenata komletirano! 

Vreme izvrsavanja je 0 minuta i 11 sekundi.

srdjan@Zverko:~$ 


Ko kompajlira source sam, da podsetimo na komandu (sa opcijama):

gcc -Wall -lpthread -O2 ProcTest64-v1.0.0.c -o ProcTest64-v1.0.0

[Ovu poruku je menjao Kernel-1 dana 10.11.2008. u 06:13 GMT+1]
[ combuster @ 10.11.2008. 08:25 ] @
Eve ga, kernel je krenuo svojim putem, ovako rano pa "developeri" krenuli razlicitim putevima :D
@sloba5 Skini jedan od ovih novijih source-eva i kompajliraj sa branimirovim stringovima za gcc obavezno...
[ Srđan Pavlović @ 10.11.2008. 08:32 ] @
ako neko nece da ima ogranicenje na 512 max memorije, samo izbacite TACNO ovaj deo koda pre kompajliranja,
ali mislim da nema potrebe za vise od 512 da se maltretira racunar :)

if (mb > 512)
{
printf("\n");
printf("Postavljena vrednost nije dozvoljena. Maksimum je 512.\n");
printf("\n");
return 0;
}


Dognju granicu ostavite iz sigurnosnih razloga.

@combuster - hehe, ne brini ako se odvojim u frakciju, propade moj solo projekat posto C znam malo zesce :)))

[Ovu poruku je menjao Kernel-1 dana 10.11.2008. u 10:07 GMT+1]
[ combuster @ 10.11.2008. 18:53 ] @
Sta ti hvali, znas dovoljno da radis reviziju software-a, ti zaelotu jedan sto bi rek'o dimke... Neprijatelju terranske rase (tj nas zemljana). :D Ortak mi sad javnuo da njemu blokira program ako nema dovoljno ram-a tj ne radi mu if !mem uslov, a ne radi ni meni, izgleda mi da trpa u swap... Provericu sutra, radim sad onu bazu... Ili proveri ti veceras ako imas vremena...
[ Branimir Maksimovic @ 10.11.2008. 19:22 ] @
malloc vraca null kad nema dovoljno continuous rama te velicine. Medjutim na 64 bitnim
sistemima to je sav ram + swap ;) Na 32 bitnim mislim da ne moze vise od 2gb (mozda i moze).

Pozdrav!

[ Srđan Pavlović @ 10.11.2008. 20:06 ] @
Kod mene je 4GB rama i swap od oko 1,3GB na 64-bit sistemu, i sad sam mu stavio 4500MB,
poceo je da radi, a onda da drlja po swapu, prekinuo sam ga naravno, verovatno bi zavrsio
za nekih godinu dana ako mi pre toga ne crkne disk :)))

Dakle, ako se alocira onoliko memorije da to zahvata i swap, onda krece disk da drlja
(kada se popuni RAM) ... i to vec onda postaje benchmark izdrzljivosti HDD-a :)

Kada stavim 5000, onda ispise da nema dovoljno memorije (a zajedno sa swap-om imam oko 5,3GB
ali deo te memorije je vec zauzet kojecime, pa onda u tom trenutku nema da alocira 5000 mb valjda)

Ali necemo se sad baviti limesima ;) - ogranicenje od 64 do 512 does the job - a moglo bi i na 128, dosta je...

[Ovu poruku je menjao Kernel-1 dana 10.11.2008. u 21:20 GMT+1]
[ Časlav Ilić @ 10.11.2008. 21:08 ] @
Citat:
Branimir Maksimovic:
Code:
int main ()
{
  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);

  int* mem = calloc(4,BLCK_SIZE*sizeof(int));


Ovim će samo jedan procesor (tj. jezgro) rezervisati svu memoriju, što posle može iskvariti performanse ako postoji „afinitet“ memorije po procesoru, tj. ako svaki procesor ima deo memorije kojem najbrže pristupa. Zato, za svaki slučaj, uspostavljanje memorije kad god može treba da ide paralelno na isti način kao i izračunavanje.

Citat:
[...] posto se sada testira i brzina memorije.
[...]

Code:
    int i = 0;
    for(;i<BLCK_SIZE;++i)
    {
      *((int*)p+i) = i;
    }


Neko uobičajeno preznojavanje memorije, zapravo minimalno smisleno odmeravanje brzine podsklopa procesor-keš-memorija, bio bi euklidski skalarni proizvod:
Code:
double a[VSIZE], b[VSIZE];
double sum;

// Uspostavljanje a, b...

// Štoperica počinje ovde.
sum = 0.0;
for(i = 0; i < VSIZE; ++i) {
    sum += a[i] * b[i];
}
// Štoperica staje ovde.

Zatim se ovaj kôd vrti za različite veličine vektora, da bi se iscrtao grafik zavisnosti broja operacija u pokretnom zarezu (FLOP) u sekundi od veličine vektora. Kao ovde. U njemu se ogleda brzina FPU-a procesora, brzina, veličina i broj keševa, i brzina memorije. Kada se izvršava paralelno, onda se rezultat može uporediti sa jednoprocesorskim, odnosno proveriti ubrzanje po segmentima x-ose.

Ceo program u prilogu, zajedno sa skripticom za crtanje grafika (mora da bude instaliran Gnuplot i Imejdžmedžik, tj. naredbe gnuplot i convert u putanji). OpenMP podrazumevno račva onoliko niti koliko ima procesora (tj. jezgara), a određen broj može se zadati promenljivom okruženja OMP_NUM_THREADS:
Code:
$ gcc test-02.c -O3 -fopenmp
$ OMP_NUM_THREADS=1 ./a.out > t1.dat
$ OMP_NUM_THREADS=2 ./a.out > t2.dat
$ OMP_NUM_THREADS=4 ./a.out > t4.dat
$ ./test-02-plot.py t1.dat t2.dat t4.dat
t1~t2~t4.png
$


Ovo je uzgred prvo odmeravanje koje vam pokažu na vežbama, da odmah shvatite koliko je jedan jedini broj kao mera „brzine procesora“ besmislen :) Bar na C2D-u, gornji grafik će pokazati da su za euklidski skalarni proizvod sva jezgra preko jednog bespotrebna, jer i to jedno potpuno zaguši memorijsku magistralu čim veličina vektora premaši kapacitet keša. A to znači, bespotrebna za sve proračune koji uključuju velike sisteme linearnih jednačina (npr. naučno-inženjerske simulacije).

No, da se ne bismo štrecali, probe mogu da se pokreću i sa ./a.out 1, za upotrebu drugog, hipotetičkog (mada beskorisnog) skalarnog proizvoda, ali takvog da izvodi mnogo više računskih operacija po jednom dohvatanju iz memorije. Tada ne dolazi do zagušenja memorije (bar s dve niti, nemam četvorojezgarni procesor pri ruci), i dobija se reklamirano ubrzanje.
[ slobapet @ 10.11.2008. 21:22 ] @
evo da dopunim svoju poruku
kao sto sam napisao, u pitanju je 32-bitni Kubuntu 8.04
koristio sam cputest koji je postavio combuster na prvoj strani http://www.elitesecurity.org/p2092218

masina je dual 2 core
model : 15
model name : Intel(R) Pentium(R) Dual CPU T2330 @ 1.60GHz
model : 15
model name : Intel(R) Pentium(R) Dual CPU T2330 @ 1.60GHz
cache size : 1024 KB
cache size : 1024 KB
2GB RAM

i rezultati su sledeci:
sloba@sloba-laptop:~/Desktop$ time ./cputest
25 percent done:
50 percent done:
75 percent done:
100 percent done - Test completed!

real 0m8.247s
user 0m8.233s
sys 0m0.004s

i preko gkreallm i htop vidim da samo opterecuje prvo jezgro...

sto se tice kompajliranja to nisam nikad probao pa ako neko zeli nek pusti na pm objasnjenje kako da odradim, ako je vama bitno...


[ Branimir Maksimovic @ 11.11.2008. 02:39 ] @
Citat:

Ovim će samo jedan procesor (tj. jezgro) rezervisati svu memoriju, što posle može iskvariti performanse ako postoji „afinitet“ memorije po procesoru, tj. ako svaki procesor ima deo memorije kojem najbrže pristupa. Zato, za svaki slučaj, uspostavljanje memorije kad god može treba da ide paralelno na isti način kao i izračunavanje.



Tacno, ali to nece ti biti dovoljno posto moras da znas koji memorijski deo pripada jednom, drugom trecem
procesoru i da alociras tako. Takodje onda moras da bindujes threadove za odredjene procesore
koji su alocirali date blokove, tj ne mozes blok1 da izvrsavas na procesoru2,
a to ne mozes ni sa malloc ni sa calloc niti mozes to da radis preko omp-a koji izvlaci najgore
moguce performanse iz numa arhitekture ),vec sa libnuma na linux-u
i pthreads ako cemo vec tako ;)

Drugo program ti ne skalira bas najbolje, identicne su mi performanse i sa 1 , 2 i 4 threada.
edit: Mada u stvari, ovde bi tako i trebalo da bude posto je jedan bus, i u mjom primeru
mislim da bi 1 thread radio isto kao i 2 ili 4 posto je jedan procesor dovoljan da se saturise
bus, vec drugi mora da deli isti bus pa se ne dobija nista.
edit2: ali definitivno nesto ne valja posto time komanda vraca isto vreme i kad su jedan i kad su dva
threada a imam dual, a meris samo read?
edit3: na osnovu merenja se vidi da omp ima neki overhead koji se eliminise kad je veci
broj ciklusa i to je to, i jos imas efekat kad podaci staju u cache i kad ne staju ;)
E sad sta u stvari meris ovim benchmarkom ;)? brzinu cache-a, memorije? ili procesora.
Cilj bench-a je da se vidi koliko vremena treba nekoj konfiguraciji da to odradi,
a na amd-ovima ti nece nista brze raditi posto ne setujes afinitet i ne alociras
po numa nodama, mada ionako sa dva cpu-a to se i ne primeti.
I na kraju interesantno je sto u globalu program ima isto vreme izvrsavanja za sve kombinacije,
ali to je verovatno zbog toga sto sinhronizujes na vreme izvrsavanja petlje.

Pozdrav!

bmaxa@maxa:~$ time OMP_NUM_THREADS=1 ./flops
# Selected loop: 0
# VSIZE [*] SPEED [MFLOPS] SUMSUM [*]
100 474 16.7
200 807 33.3
500 1315 83.3
1000 1639 166.7
2000 1853 333.3
5000 2076 833.3
10000 2166 1666.7
20000 2264 3333.3
50000 2297 8333.3
100000 2288 16666.7
200000 2287 33333.3
500000 1211 83333.3
1000000 1109 166666.7
2000000 1113 333333.3
5000000 1129 833333.3
10000000 1132 1666666.7

real 0m31.833s
user 0m29.446s
sys 0m2.360s
bmaxa@maxa:~$ time OMP_NUM_THREADS=2 ./flops
# Selected loop: 0
# VSIZE [*] SPEED [MFLOPS] SUMSUM [*]
100 40 16.7
200 85 33.3
500 175 83.3
1000 382 166.7
2000 688 333.3
5000 1108 833.3
10000 1733 1666.7
20000 1766 3333.3
50000 2531 8333.3
100000 2966 16666.7
200000 2896 33333.3
500000 1314 83333.3
1000000 1133 166666.7
2000000 1109 333333.3
5000000 1103 833333.3
10000000 1143 1666666.7

real 0m31.645s
user 0m26.870s
sys 0m9.573s

a evo i za drugu petlju:

bmaxa@maxa:~$ time OMP_NUM_THREADS=2 ./flops 1
# Selected loop: 1
# VSIZE [*] SPEED [MFLOPS] SUMSUM [*]
100 624 20.9
200 899 41.8
500 1340 104.6
1000 1878 209.2
2000 2369 418.4
5000 2434 1046.0
10000 2780 2092.0
20000 2800 4184.0
50000 2269 10460.0
100000 3138 20920.0
200000 2284 41839.9
500000 2287 104599.8
1000000 2931 209199.6
2000000 3934 418399.2
5000000 3928 1045997.9
10000000 3970 2091995.8

real 0m32.107s
user 0m35.638s
sys 0m3.908s
bmaxa@maxa:~$ time OMP_NUM_THREADS=1 ./flops 1
# Selected loop: 1
# VSIZE [*] SPEED [MFLOPS] SUMSUM [*]
100 1805 20.9
200 2046 41.8
500 2182 104.6
1000 2224 209.2
2000 2251 418.4
5000 2268 1046.0
10000 2270 2092.0
20000 2222 4184.0
50000 2260 10460.0
100000 2282 20920.0
200000 2297 41839.9
500000 2228 104599.8
1000000 2221 209199.6
2000000 2296 418399.2
5000000 2298 1045997.9
10000000 2299 2091995.8

real 0m32.210s
user 0m31.654s
sys 0m0.500s


[Ovu poruku je menjao Branimir Maksimovic dana 11.11.2008. u 07:25 GMT+1]

[Ovu poruku je menjao Branimir Maksimovic dana 11.11.2008. u 08:32 GMT+1]
[ Branimir Maksimovic @ 11.11.2008. 05:07 ] @
Evo malo preradjeni test, detektuje broj procesora i dize broj threadova po tome,
ali i alocira paralelno i setuje afinitet po procesoru tako da ako je malloc numa aware
ovo bi trebalo da sljaka ok i kad je numa. Nisam bas hteo da koristim libnuma,
to bi bilo preterivanje za ovo ;)

Code:

#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>

#define BLCK_SIZE 16777216

sem_t sema,sema1;
typedef struct Data{ int blck_size,cpu; } Data_t;

void* tf(void* p)
{
  Data_t* dt = (Data_t*)p;
  int *mem=NULL;
  cpu_set_t set;
  CPU_ZERO(&set);
  CPU_SET(dt->cpu,&set);
  if(sched_setaffinity(0,sizeof(cpu_set_t),&set)<0)
    printf("set affinity failed cpu %d\n",dt->cpu);

  printf("set affinity cpu %d\n",dt->cpu);

  mem = malloc(dt->blck_size*sizeof(int));
  if(!mem)return 0;

  int j = 80;
  while(j--)
  {
    int i = 0;
    unsigned long long sum=0;
    for(;i<dt->blck_size;++i)
    {
      *(mem+i) = i;
    }
    for(i=0;i<dt->blck_size;++i)
    {
      sum += mem[i];
    }
    if(j%20==0)
    {
      printf("thread %lu, sum %llu\n",(unsigned long)pthread_self(),sum);
      sem_post(&sema);
      sem_wait(&sema1);
    }
  }
  free(mem);
  return 0;
}

static void waitT(int count)
{
  while(count--)
  {
    sem_wait(&sema);
  }
}

static void postT(int count)
{
  while(count--)
  {
    sem_post(&sema1);
  }
}

int main (int argc,char* argv[])
{
  int single=0;
  
  int numcpus=0,i;
  pthread_t* tid=NULL;
  cpu_set_t set;

  if(argc>1)single=1;

  sem_init(&sema,0,0);
  sem_init(&sema1,0,0);

  CPU_ZERO(&set);
  CPU_SET(0,&set);
  
  while(sched_setaffinity(0,sizeof(cpu_set_t),&set)==0)
  {
    ++numcpus;
    CPU_ZERO(&set);
    CPU_SET(numcpus,&set);
  }
  printf("numcpus %d\n",numcpus);  
  tid = calloc(numcpus,sizeof(pthread_t));
  Data_t dt[numcpus];
  if(single)numcpus=1;
  for(i=0;i<numcpus;++i)
  {
      dt[i].blck_size = BLCK_SIZE*4/numcpus;
      dt[i].cpu = i;
      pthread_create(tid+i,NULL,tf,dt+i);
  }
  
  waitT(numcpus);
  printf ("25 percent done:\n");
  postT(numcpus);  

  waitT(numcpus);
  printf("50 percent done:\n");
  postT(numcpus);  

  waitT(numcpus);
  printf("75 percent done:\n");
  postT(numcpus);  

  waitT(numcpus);
  printf("100 percent done - Test completed!\n");
  postT(numcpus);  

  for(i=0;i<numcpus;++i)
    pthread_join(tid[i],NULL);

  free(tid);
  sem_destroy(&sema);
  sem_destroy(&sema1);

  return 0;
}



Kompajlira se sa:
gcc -Wall -O2 -D_GNU_SOURCE -lpthread ime.c -o ime

mora _GNU_SOURCE zbog afinitija, ako nekome treba moze dodati i #include <sched.h>
mada meni nije bilo potrebno


bmaxa@maxa:~$ time ./omp 1
numcpus 2
set affinity cpu 0
thread 1092589904, sum 2251799780130816
25 percent done:
thread 1092589904, sum 2251799780130816
50 percent done:
thread 1092589904, sum 2251799780130816
75 percent done:
thread 1092589904, sum 2251799780130816
100 percent done - Test completed!

real 0m9.828s
user 0m9.641s
sys 0m0.144s
bmaxa@maxa:~$ time ./omp
numcpus 2
set affinity cpu 0
set affinity cpu 1
thread 1106848080, sum 562949936644096
thread 1115240784, sum 562949936644096
25 percent done:
thread 1106848080, sum 562949936644096
thread 1115240784, sum 562949936644096
50 percent done:
thread 1115240784, sum 562949936644096
thread 1106848080, sum 562949936644096
75 percent done:
thread 1115240784, sum 562949936644096
thread 1106848080, sum 562949936644096
100 percent done - Test completed!

real 0m8.669s
user 0m15.941s
sys 0m0.160s


edit: Dodao sam i memory read test osim samo write-a a ko hoce moze modifikovati da radi i sa
razlicitim velicinama blokova, stavio sam da se velicina rasporedi po threadovima itd
edit2: potkrala mi se greska morao sam da bacim razilicite data strukture za svaki thread ;)
dodao sam i mogucnost ako se baci neki parametar onda program racuna u samo jednom threadu.

Pozdrav!


[Ovu poruku je menjao Branimir Maksimovic dana 11.11.2008. u 06:25 GMT+1]

[Ovu poruku je menjao Branimir Maksimovic dana 11.11.2008. u 09:21 GMT+1]
[ Tyler Durden @ 11.11.2008. 08:05 ] @
STAVITE KOD U ATTACHMENT, molim vas!
[ Jbyn4e @ 11.11.2008. 09:13 ] @
Hm, razlika se primecuje.... ovo je na onoj x2 4600+ na kojoj radi i muzika i svasta nesto...
Citat:

time ./omp1
numcpus 2
set affinity cpu 0
set affinity cpu 1
thread 1116985680, sum 562949936644096
thread 1108592976, sum 562949936644096
25 percent done:
thread 1116985680, sum 562949936644096
thread 1108592976, sum 562949936644096
50 percent done:
thread 1116985680, sum 562949936644096
thread 1108592976, sum 562949936644096
75 percent done:
thread 1116985680, sum 562949936644096
thread 1108592976, sum 562949936644096
100 percent done - Test completed!

real 0m14.627s
user 0m20.965s
sys 0m0.324s

time ./omp1 1
numcpus 2
set affinity cpu 0
thread 1110628688, sum 2251799780130816
25 percent done:
thread 1110628688, sum 2251799780130816
50 percent done:
thread 1110628688, sum 2251799780130816
75 percent done:
thread 1110628688, sum 2251799780130816
100 percent done - Test completed!

real 0m24.469s
user 0m19.877s
sys 0m0.404s


Nemam sad OS na onom quad-u da ga testiram :( (vrse se neke izmene...)

@tyler - slazem se :)
[ Časlav Ilić @ 11.11.2008. 10:24 ] @
Citat:
Branimir Maksimovic: Tacno, ali to nece ti biti dovoljno posto moras da znas koji memorijski deo pripada jednom, drugom trecem procesoru i da alociras tako. [...]


Zapravo, nije bitan sam trenutak rezervisanja u programu, već koji procesor prvi dohvati određeni podatak, odnosno u petlji koja uspostavlja vrednosti — tek tada operativni sistem odredi gde će taj podatak zaista biti smešten, tj. stavi ga u deo memorije koji je najpristupačniji datom procesoru. (Doduše, svojim očima da vidim presudan uticaj ovoga na performanse, imao sam prilike samo na jednoj itanijumskoj NUMA mašini pod Linuksom...)

Citat:
[...] ali definitivno nesto ne valja posto time komanda vraca isto vreme i kad su jedan i kad su dva threada a imam dual, a meris samo read?


time vraća isto vreme zato što program skalira broj ponavljanja merne petlje po veličini vektora, kako bi održao neko razumno vreme izvršavanja za uprosečivanje rezultata. Zato brzinu daje u FLOP-ovima po sekundi.

Citat:
na osnovu merenja se vidi da omp ima neki overhead koji se eliminise kad je veci broj ciklusa [...]


Gubi se vreme na sinhronizaciju niti, npr. radi redukcije suma koje petlje računaju, i možda još po nešto (to je ono da je openMP malo vudu...) To se lako odrazi na performanse kad je petlja kratka, ali kad dođe do i preko 100.000, mislim da više nije od značaja.

Citat:
[...] i jos imas efekat kad podaci staju u cache i kad ne staju ;) E sad sta u stvari meris ovim benchmarkom ;)? brzinu cache-a, memorije? ili procesora.


Merim ono što je meni bitno, jasno :) Stvarni programi za koje mi je potrebna brzina takvi su da deo grafika od veličine 100.000 i naviše prilično dobro odmerava koliko će ih sistem brzo izvršavati. Znači, kad kupujem sistem, ne interesuje me: broj jezgara, arhitektura ovo-ono, kung-fu-bu, itd. već me interesuje šta kaže druga polovina ovih grafika (i još ponekih). Ovo znači da u razmatranje ulazi ne samo hardver, već i operativni sistem i kompilator, kao što i treba.

Ali je poenta upravo da pokažem da nije smisleno meriti „brzinu procesora“ ili „brzinu memorije“ ili „brzinu keša“, već da, ako se već za to ne koriste krajnji programi od značaja, onda treba sastaviti modelsko odmeravanje koje koliko-toliko podražava njihove zahteve.

Nego, koji je to tačno sistem za koji si ispostavio rezultate? Ovaj C2D E6600 koji je meni pri ruci ima magistralu 266 i daje ~650 MFLOPS za petlju 0 (grafici u prilogu) van keša, što bi trebalo da se prenese na ~1000 MFLOPS za magistralu 400, odnosno ~1300 MFLOPS za 533. Hoću reći, pošto kod tebe vidim ~1100 MFLOPS, ako ti je magistrala 400, nije malo tih 10% preko očekivanog :)
[ Branimir Maksimovic @ 11.11.2008. 11:29 ] @
Jbyn4e, zaista iznenadjujuca razlika. Kao sto vidis kod mene je razlika 1.2 sekunde sto i nije malo
ali kod tebe bas iznenadjuje.

Caslave, kod numa je stvar vrlo prosta. Neki procesori direktno pristupaju jednom delu memorije
neki drugom, itd. OS tu ne moze mnogo sta sem da alocira memoriju sa procesora
koji trenutno vozi dati thread (osim ako ne alocira interleaved, no i to se posebno setuje). Ako jos i operises
sa tom memorijom na istom procesoru gde si alocirao, onda ce se dobiti ubrzanje na numa,
tako da ako se ne setuje afinitet moze se desiti da usled context switch-a, da ce sa drugog procesora pristup ici
posredno preko prvog i dolazi do nekog usporenja.
Ovo sto sam uradio bi trebalo da bude dovoljno mada nema garancija. Za tako nesto
morao bih da radim preko libnuma. No, kazem to drasticno moze da uspori na velikom broju procesora.
2-4 i ne oseti se nesto.

Sto se tice sistema, to je e8400 overklokovan na 3.6 i bus od 400mhz. Mislim da tih 10% ide zbog
toga sto je memorija na 1066.

Tyler, sad videh, ako budem postovao ovako malo veci kod stavicu u attach, samo da provalim kako
se to radi ;0)
tj ne vidim nigde kako to da uradim?
edit: Da video sam pise u faq-u da ima link pri dnu.


Pozdrav!

[ Jbyn4e @ 11.11.2008. 12:55 ] @
Citat:
Branimir Maksimovic: Jbyn4e, zaista iznenadjujuca razlika. Kao sto vidis kod mene je razlika 1.2 sekunde sto i nije malo
ali kod tebe bas iznenadjuje.

Testa radi, probao sam i na dve druge masine:AMD Athlon(tm) 64 X2 Dual Core Processor 6000+ i na Intel(R) Core(TM)2 Duo CPU E8200 @ 2.66GHz

Rezultati?
amd:
Citat:

time ./omp1
numcpus 2
set affinity cpu 0
set affinity cpu 1
thread 1104513360, sum 562949936644096
thread 1096120656, sum 562949936644096
25 percent done:
thread 1096120656, sum 562949936644096
thread 1104513360, sum 562949936644096
50 percent done:
thread 1096120656, sum 562949936644096
thread 1104513360, sum 562949936644096
75 percent done:
thread 1104513360, sum 562949936644096
thread 1096120656, sum 562949936644096
100 percent done - Test completed!

real 0m10.850s
user 0m20.805s
sys 0m0.408s

time ./omp1 1
numcpus 2
set affinity cpu 0
thread 1082538320, sum 2251799780130816
25 percent done:
thread 1082538320, sum 2251799780130816
50 percent done:
thread 1082538320, sum 2251799780130816
75 percent done:
thread 1082538320, sum 2251799780130816
100 percent done - Test completed!

real 0m16.409s
user 0m15.961s
sys 0m0.404s


Intel:
Citat:

time ./omp1
numcpus 2
set affinity cpu 0
set affinity cpu 1
thread 1090525520, sum 562949936644096
thread 1082132816, sum 562949936644096
25 percent done:
thread 1082132816, sum 562949936644096
thread 1090525520, sum 562949936644096
50 percent done:
thread 1082132816, sum 562949936644096
thread 1090525520, sum 562949936644096
75 percent done:
thread 1082132816, sum 562949936644096
thread 1090525520, sum 562949936644096
100 percent done - Test completed!

real 0m11.547s
user 0m22.709s
sys 0m0.160s

time ./omp1 1
numcpus 2
set affinity cpu 0
thread 1082132816, sum 2251799780130816
25 percent done:
thread 1082132816, sum 2251799780130816
50 percent done:
thread 1082132816, sum 2251799780130816
75 percent done:
thread 1082132816, sum 2251799780130816
100 percent done - Test completed!

real 0m12.968s
user 0m12.837s
sys 0m0.124s


Hm, nesto je cudno kod AMD-ova :(

I jos nesto, htedoh da probam na "obicnom" jednojezgarnom procesoru, matoroooooom...:
Citat:

gcc -Wall -O2 -D_GNU_SOURCE -lpthread omp1.c -o omp1
omp1.c: In function `tf':
omp1.c:18: warning: passing arg 2 of `sched_setaffinity' makes pointer from integer without a cast
omp1.c:18: error: too many arguments to function `sched_setaffinity'
omp1.c: In function `main':
omp1.c:82: warning: passing arg 2 of `sched_setaffinity' makes pointer from integer without a cast
omp1.c:82: error: too many arguments to function `sched_setaffinity'
omp1.c:123:2: warning: no newline at end of file

uname -a
Linux xxxx 2.4.21-99-athlon #1 Wed Sep 24 13:34:32 UTC 2003 i686 athlon i386 GNU/Linux

cat /proc/cpuinfo |grep model
model : 6
model name : AMD Athlon(tm) XP 2000+

gcc -v
Reading specs from /usr/lib/gcc-lib/i586-suse-linux/3.3.1/specs
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --enable-languages=c,c++,f77,objc,java,ada --disable-checking --enable-libgcj --with-gxx-include-dir=/usr/include/g++ --with-slibdir=/lib --with-system-zlib --enable-shared --enable-__cxa_atexit i586-suse-linux
Thread model: posix
gcc version 3.3.1 (SuSE Linux)
[ Branimir Maksimovic @ 11.11.2008. 13:49 ] @
Kod amd-ova izgleda da memory bus ima presudnu ulogu u brzini, tj jedan procesor nije
dovoljan da se saturise bus, jedino tako mogu da objasnim.
Dok kod intela i jedan procesor prevuce sav bw, ukupno amd ima brzi bus. Time objasnjavam razliku.

Nazalost sched_setaffinity ima razlicite parametre og glibc-a do glibca, koristio sam najsveziji.
Pogledaj kod sebe sta se baca u slucaju tog starog, mozda ne treba size za cpu_set_t
nego samo ide sched_setaffinity(0,&set) sto je najverovatnije posto ima dva parametra.

Pozdrav!

edit: jedina verzija glibc-a koja ima verziju sa dva parametra je devel 2.3.2 a inace sam syscall
se pojavio od verzije 2.3 pre toga ga nema heh.


[Ovu poruku je menjao Branimir Maksimovic dana 11.11.2008. u 15:20 GMT+1]
[ combuster @ 11.11.2008. 15:48 ] @
Joj ne stizem da vas propratim, ubise me i geometri i profesori i drustvo i svakom treba nesto ne stigoh da kompajliram ovih 100 linija koda...
Evo rezultata:
Code:

combuster@vostro:~$ time ./a.out
# Selected loop: 0
#       VSIZE [*]  SPEED [MFLOPS]      SUMSUM [*]
              100              21            16.7
              200              56            33.3
              500             103            83.3
             1000             173           166.7
             2000             390           333.3
             5000             597           833.3
            10000             795          1666.7
            20000             974          3333.3
            50000            1105          8333.3
           100000             939         16666.7
           200000             566         33333.3
           500000             540         83333.3
          1000000             571        166666.7
          2000000             584        333333.3
          5000000             614        833333.3
         10000000             580       1666666.7

real    0m32.034s
user    0m32.382s
sys    0m6.400s


Eh da C2D Mobile 1.8GHz T5670...

Code:

combuster@vostro:~$ time ./test1
numcpus 2
set affinity cpu 0
set affinity cpu 1
thread 1111632208, sum 562949936644096
thread 1103239504, sum 562949936644096
25 percent done:
thread 1103239504, sum 562949936644096
thread 1111632208, sum 562949936644096
50 percent done:
thread 1103239504, sum 562949936644096
thread 1111632208, sum 562949936644096
75 percent done:
thread 1111632208, sum 562949936644096
thread 1103239504, sum 562949936644096
100 percent done - Test completed!

real    0m16.518s
user    0m30.890s
sys    0m0.392s


Sry Tyler...

[Ovu poruku je menjao combuster dana 11.11.2008. u 16:59 GMT+1]
[ Srđan Pavlović @ 11.11.2008. 21:11 ] @
srdjan@Zverko:~$ time ./test-1
numcpus 2
set affinity cpu 0
set affinity cpu 1
thread 1115986256, sum 562949936644096
thread 1107593552, sum 562949936644096
25 percent done:
thread 1107593552, sum 562949936644096
thread 1115986256, sum 562949936644096
50 percent done:
thread 1115986256, sum 562949936644096
thread 1107593552, sum 562949936644096
75 percent done:
thread 1107593552, sum 562949936644096
thread 1115986256, sum 562949936644096
100 percent done - Test completed!

real 0m11.568s
user 0m20.569s
sys 0m0.276s
srdjan@Zverko:~$

Evo kod mene. FSB mi je 333, ("1333Mhz") (9 x mnozilac = 3Ghz procesor)
Memorija je 4 DDR2 modula od 800Mhz po 1GB u Dual Channel Interleaved modu.

[Ovu poruku je menjao Kernel-1 dana 11.11.2008. u 22:44 GMT+1]
[ Sasha_bn @ 11.11.2008. 22:59 ] @
Citat:

Dual-Core AMD Opteron(tm) Processor 2218
real 0m5.793s
user 0m5.792s
sys 0m0.000s


Citat:

Intel(R) Xeon(R) CPU E5320 @ 1.86GHz
real 0m7.016s
user 0m7.016s
sys 0m0.000s


Sto sam ja svo vreme mislio da je Xeon brzi????

/edit
Sa novim testom:
Citat:

Xeon

real 0m18.995s
user 1m15.277s
sys 0m0.508s



Citat:

AMD

real 0m14.416s
user 0m28.430s
sys 0m0.272s


@Kernel-1 kako dobijas brze rezultate na svom procesoru od mene sa c2d nego ja sa xeon-om i optereonom??? Dali je do 64 bit ?

[Ovu poruku je menjao Sasha_bn dana 12.11.2008. u 00:12 GMT+1]

[Ovu poruku je menjao Sasha_bn dana 12.11.2008. u 00:13 GMT+1]

[Ovu poruku je menjao Sasha_bn dana 12.11.2008. u 00:21 GMT+1]
[ combuster @ 11.11.2008. 23:06 ] @
Mozda zato sto je na cirka 800MHz visoj frekvenciji od xeona?
[ Srđan Pavlović @ 11.11.2008. 23:52 ] @
Citat:
@Kernel-1 kako dobijas brze rezultate na svom procesoru od mene sa c2d nego ja sa xeon-om i optereonom??? Dali je do 64 bit ?

Sasha_bn, taj Xeon je na 1,86Ghz, dok je E6850 na 3Ghz, velika je razlika u brzini. Nema veze sa 32/64 bit arhitekturom.

[Ovu poruku je menjao Kernel-1 dana 13.11.2008. u 13:55 GMT+1]
[ Srđan Pavlović @ 13.11.2008. 13:45 ] @
http://homepage.virgin.net/roy.longbottom/index.htm - zanimljivo, vezano za temu, sa sourcevima, uglavnom C++, assembler, negde VB, itd...
[ Srđan Pavlović @ 28.11.2008. 05:27 ] @
Zanimljiv nalaz... Host je Ubuntu 8.10 x_64, a u VirtualBox-u je openSuSE 11.0 x_64.

Rezultati u attachmentu...
[ Branimir Maksimovic @ 28.11.2008. 20:17 ] @
Virtual box uzima 100% 1 od cpu-a kada je idle, bar kod mene posto hostovani os stalno vrti halt, a vbox
valjda to emulira pa trosi cpu vreme. Kad startujes program u vm on koristi maksimalno
oba cpu-a a kad ostavis vbox i sa strane nesto startujes onda se koristi samo jedan.

Valjda je zato razlika.

Pozdrav!
[ mm2000 @ 30.11.2008. 19:08 ] @

Nisam pratio od pocetka "ravoj dogadjaja", ali da i ja dodam svoj komentar :)

Kao prvo ako se zele meriti performanse nekog procesora, 'time' je potpuno beskorisna komanda gde brzina procesora (u vecini slucajeva) dolazi do izrazaja i utice na rezultat (najbrzi skoro uvek pobedjuje). Assembler instrukcija rdtsc (vraca broj clock-ova) i mnogo je relevantnija za merenje perfomansi procesora. Sa nekoliko assembler instrukcija se mogu dobiti mnogo pouzdaniji rezultati nego sa 'time'.

Sto se tice paralelnog izvrsavanja na vise procesora, OpenMP je za sada najbolje resenje i ono se nalazi kao standarni paket u gcc-u od verzije 4.2.4 (ako se dobro secam :) ). OpenMP se odavno nalazi kao sastavni paket kod Intel-ovog (a mislim i kod Microsoft-ovog) kompajlera.
Za paralelno izvrsavanje moze se uzeti i Cilk (mislim da se ovako pise) kao opcija, mada je dosta (bar po meni) komplikovano za pisanje. U stvari to je C sa nekim dodacima za paraleno izvrsavanje. Takodje ima i svoj "kompajler" preko kojeg se kompajlira.

@Sasha_bn kako dobijas brze rezultate na svom procesoru od mene sa c2d nego ja sa xeon-om i optereonom??? Dali je do 64 bit ?

Kao sto sam gore napisao, verovatno brzina procesora je veca na C2D nego na xeon-u i opteronu. Mada ni to ne mora da znaci, jer je dosta parametara u "igri". Ja sam na primer na nekim benchmark-ima dobijao bolje rezultate na mom laptopu C2D 2.00GHz (T7200), nego na Quad Core Xeon-u na 3.00GHz, za oko 5-10% je bio brzi nego Xeon. Merenje je vrseno u broju clock/byte.
[ Srđan Pavlović @ 30.11.2008. 19:26 ] @
Citat:
Assembler instrukcija rdtsc (vraca broj clock-ova) i mnogo je relevantnija za merenje perfomansi procesora. Sa nekoliko assembler instrukcija se mogu dobiti mnogo pouzdaniji rezultati nego sa 'time'.


Jel bi znao ti, posto vec imas kod ovde, da implementiras da se meri vreme preko
clock-ova, dakle taj asemblerski deo, eto ako imas malo slobodnog vremena slobodno prepravi
kod pa postuj ovde... ;)


Meni je ovde najzanimljivije poredjenje Intel i AMD rezultata kada su procesori na
istom (ili vrlo bliskom) taktu. Tada se vidi uticaj magistrale.

[Ovu poruku je menjao Kernel-1 dana 30.11.2008. u 20:38 GMT+1]
[ mm2000 @ 30.11.2008. 23:19 ] @
Kod bi izgledao ovako nekako za 64-bitne procesore.

Code:

    unsigned int ticks_lo, ticks_hi;

    __asm__ volatile
        ("\n  rdtsc"
        : "=a" (ticks_lo), "=d" (ticks_hi));

//
//  ovde ide deo koda koji se zeli meriti
//

    __asm__ volatile
        ("\n  rdtsc"
        "\n  sub  %2, %%eax"
        "\n  sbb  %3, %%edx"
        : "=&a" (ticks_lo), "=&d" (ticks_hi)
        : "g" (ticks_lo), "g" (ticks_hi));

    printf("Broj clock-ova: %lld\n", (long long)ticks_lo + 4294967296 * (long long)ticks_hi);


Takodje mozes koristiti i clock(), ali se meni vise svidja gore pomenuti nacin merenja.
[ Branimir Maksimovic @ 01.12.2008. 08:15 ] @
rdtsc ne mozes koristiti na multi core procesorima zato sto to cita posebno time stamp counter
sa svakog procesora koji ne mora biti sinhronizovan. Zbog toga su stare igre koje su koristile
ovo zveketale posto moze da se dobije i negativna razlika.
No ukoliko hoces da koristis ovo onda moraju i sami counteri da se sinhronizuju (amd je izbacio poseban
cpu driver za to za windows, intel nije).
edit: Dakle ako hoces da koristis rdtsc za merenje onda podji od onog bencha gde bindujem svaki
thread za cpu, pa meri posebno izvrsavanje svakog threada,
inace bilo sta drugo ce citati razilicite countere cim dodje do context switch-a i dati bogus rezultate.

Pozdrav!
[ Srđan Pavlović @ 01.12.2008. 13:29 ] @
i jos nesto - ono sa ubacivanjem pitanja koliko MB da se alocira mora da se izbaci :)

Zasto? Pa zato sto startujes aplikaciju, i onda cekas 5 sekundi, i onda uneses 64mb,
ili cekas 8 sekundi pa uneses 64mb, ili cekas 2 minuta... a meri se vreme od starta aplikacije sa time - hehe...

Ili samo napraviti da aplikacija odma u komandnoj liniji kao parametar prima broj megabajta, tako da
kada se startuje, izvrsavanje krene odmah.
[ Srđan Pavlović @ 25.10.2009. 20:24 ] @
Jel ima jos neko zaludan da za ovo napravi neki mali gtk GUI? :)