Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: dušo 10. 03. 2014, 15:48:17
-
Ahojte,
v škole na IT som nedal pokoj učiteľovi ohľadom veľkosti premenných typu boolean v jave a došli sme až k tomu, či sa dá rozložiť byte premenná na 8 booleanov... takže som dostal špeciálnu domácu úlohu za bonusové body: Rozložiť byte na 8 booleanov :D
riešil som to hľadaním na nete a upravením na moj prípad:
public static boolean[] ByteToBooleanArray(byte p)
{
boolean bTemp[]=new boolean[8];
bTemp[0]=((p & 0x01)!=0);
bTemp[1]=((p & 0x02)!=0);
bTemp[2]=((p & 0x03)!=0);
bTemp[3]=((p & 0x04)!=0);
bTemp[4]=((p & 0x05)!=0);
bTemp[5]=((p & 0x06)!=0);
bTemp[6]=((p & 0x07)!=0);
bTemp[7]=((p & 0x08)!=0);
return bTemp;
}
funguje to dobre (alebo aspoň sa to tak zdá), ale tak nejak nerozumiem čo robí časť "(p & 0x01)"... z anglického tutoriálu som nepochopil, a pýtať sa učiteľa nemá zmysel...
A ďalšia vec, ako to urobiť opačne - teda z poľa booleanov urobiť 1 byte ?
-
http://www.vipan.com/htdocs/bitwisehelp.html
-
Urcite to funguje dobre? A nemaji byt ty masky 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80? Pripada me to, ze se sice uci Java, ale nejen, ze tomu nerozumi zak, ale ani ucitel. Co takhle si to otestovat v cyklu pro hodnoty 0 az 255 pro ten byte. Driv se na vyuku programovani pouzival Pascal, ktery tvrde nutil zaky rozumet typum, polim a podobne a jeste umel i kontrolovat preteceni poli a hodnot. Java se na vyuku programovani moc nehodi, ale vsichni v tom jedou a vsichni jsou spokojeni.
-
Bych blil...
-
Urcite to funguje dobre? A nemaji byt ty masky 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80?
jj, mám to zle... co sa tyka pascalu: o tom neviem nič - my sme prebrali uplne základy aj v tej jave (hello world a pod.) toto je nad rámec osnov z mojej vlastnej iniciatívy... učiteľ nema šajnu o IT - minule ho na pol hodinu odpálilo keď si odbehol a spolužiak na jeho pc nechal zoradiť ikonky na ploche podľa názvu...
-
Pokud je něco takového potřeba, použije se třída java.util.BitSet. Nakonec to nejspíš bude i efektivnější, než 8× převádět byte na int.
Radši by vás ve škole měli naučit, že p ani bTemp v tomto případě rozhodně nejsou dobré názvy proměnných, a název metody ByteToBooleanArray začínající velkým písmenem je také dobrý způsob, jak zmást kohokoli, kdo se kolem Javy alespoň mihnul.
Jinak & je bitový AND operátor (http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.22.1), na každé dvojici bitů obou operandů udělá logický AND a výsledek určuje hodnotu příslušného bitu výsledku.
Pokud se chcete opravdu naučit základy Javy, doporučuji knížku Učebnice jazyka Java (http://www.kopp.cz/www/cz/687-vyrobek-ucebnice-jazyka-java) od Pavla Herouta, nic lepšího v češtině asi nevyšlo.
-
Driv se na vyuku programovani pouzival Pascal, ktery tvrde nutil zaky rozumet typum, polim a podobne a jeste umel i kontrolovat preteceni poli a hodnot. Java se na vyuku programovani moc nehodi, ale vsichni v tom jedou a vsichni jsou spokojeni.
Tak zrovna toto java ma stejne a zde to je nazorne videt - pokud nevim co je byte a neznam operatory, nevyresim ani tuto trivialni ulohu.
-
pokud nevim co je byte a neznam operatory, nevyresim ani tuto trivialni ulohu
A pokud to vím, vyřeším ji špatně. Výsledkem takové výuky bude velká většina lidí, kteří budou mít nesprávný pocit, že programování jsou jakési podivné manipulace s bity a poli, a budou se divit, proč tuhle nudnou rutinu nedělá za člověka počítač. Zbytek budou ti, kteří to pochopí a budou to používat všude, bitové mapy budou používat místo atributů objektů, pole místo kolekcí, a budou umět z voleje naprogramovat quicksort, který nebude fungovat.
-
pokud nevim co je byte a neznam operatory, nevyresim ani tuto trivialni ulohu
A pokud to vím, vyřeším ji špatně. Výsledkem takové výuky bude velká většina lidí, kteří budou mít nesprávný pocit, že programování jsou jakési podivné manipulace s bity a poli, a budou se divit, proč tuhle nudnou rutinu nedělá za člověka počítač. Zbytek budou ti, kteří to pochopí a budou to používat všude, bitové mapy budou používat místo atributů objektů, pole místo kolekcí, a budou umět z voleje naprogramovat quicksort, který nebude fungovat.
Já jsem na Javu přecházel z C a proto mi bitové operace připadají přirozené (kromě té zrady se zachováváním znaménka v Javě). Když se ohlédnu zpátky za C tak uznávám že má svou roli - ale psát v tom velké projekty bych nerad. Myslím si že je třeba znát jak základy (tedy C) tak objektový přístup (Java) a volit to co je třeba. Nedokážu si představit jak asi můžou fungovat "programátoři" kteří se "naučí Javu" ale při dotazu na to jak jsou v paměti uložená data nebo i na to jak naprogramovat quicksort naprosto netuší (pokud se jim zakáže zavolat knihovnu). Ale možná je to jen tím že jsem už moc starý a polodementně blábolím o tom jak je dnešní mládež zkažená...
-
public static boolean[] ByteToBooleanArray(byte p)
{
boolean bTemp[]=new boolean[8];
bTemp[0]=((p & 0x01)!=0);
bTemp[1]=((p & 0x02)!=0);
bTemp[2]=((p & 0x03)!=0);
bTemp[3]=((p & 0x04)!=0);
bTemp[4]=((p & 0x05)!=0);
bTemp[5]=((p & 0x06)!=0);
bTemp[6]=((p & 0x07)!=0);
bTemp[7]=((p & 0x08)!=0);
return bTemp;
}
Az si tam spravis ty masky (0x01, 0x02, 0x04...), tak bych doporucoval si to v ramci treningu prepsat do smycky, protoze jestli dalsi uloha bude naprogramovat longToBooleanArray(), tak uz to bude vypadat silene :)
Hint: pouzijes porad maskovani s 0x01 a potom bitovy posun doprava.
-
Popravde receno, operator "&" jsem uz nekolik mesicu nepouzil, zatimco "&&" pouzivam bezne.
Velmi strucne a laicky pro puvodniho tazatele:
"&" je bitovy soucin. Tzn. tam kde je v promenne A i v promenne B na stejne pozici jednicka, tak bude ve vysledku taky jednicka.
Napr. (obecny jazyk typu C):
promennaA = 0b00110011;
promennaB = 0b01000110;
vysledek = promennaA & promennaB; /// melo by byt: 0b00000010
Kdybys nevedel, jak slozit bajt z osmi bitu, tak doporucuji "Uz vim proc, 2. dil" :)
-
No, já si myslím že s úsporou pár bajtů na booleanech v javě díru neuděláš. V javě která má žravej GC, a na stacku nic neukládá (něco asi jo, nestudoval sem to víc, nezajímá mne). Takovíhle hraní si s bitama je třeba pouze u low level vývoje (nastavování příznaků v registrech a tak podobně). BTW, když si s tím chceš hrát, napřed si nastuduj binární soustavu a binární operátory, jinak fakt na profesora dojem neuděláš (vysvětli...), z netu to umí zkopírovat každej (v tvým případě ještě blbě). Jinak, proč mám dojem že na školách sou vymaštěný profesoři?
-
Kdybys nevedel, jak slozit bajt z osmi bitu, tak doporucuji "Uz vim proc, 2. dil" :)
Mas pravdu, jsem se ted dival do druheho dilu (ktery mi uz davno znarodnil nas mladej pan :-) a skutecne to tam popisuji...
-
Nedokážu si představit jak asi můžou fungovat "programátoři" kteří se "naučí Javu" ale při dotazu na to jak jsou v paměti uložená data nebo i na to jak naprogramovat quicksort naprosto netuší (pokud se jim zakáže zavolat knihovnu).
Řekl bych, že podobně, jako fungují řidiči, kteří neumí osedlat koně. Akorát podíl profesionálních programátorů, kteří dnes musí znát způsob uložení dat v paměti, bude dnes pořád ještě víc, než profesionálů, kteří se zabývají koňmi.
-
No, já si myslím že s úsporou pár bajtů na booleanech v javě díru neuděláš. V javě která má žravej GC, a na stacku nic neukládá (něco asi jo, nestudoval sem to víc, nezajímá mne). Takovíhle hraní si s bitama je třeba pouze u low level vývoje (nastavování příznaků v registrech a tak podobně).
Sice se v Javě ty bitové operace nepoužívají nijak extrémně často, ale už jsem optimalizoval dvourozměrné pole booleanů za jednorozměrné pole BitSet, používalo se to totiž v rekurzivním algoritmu a prováděly se tam kopie, takže optimalizace program změnila z nepoužitelně pomalého na rozumně rychlý.
Další reálné použití jsem viděl pri parsování binárního protokolu který byl daný a nebylo ho možné změnit protože ho používala krabice (blackbox) od neflexibilního dodavatele.
Takže nevidím důvod proč by programátor v Javě neměl chápat bitové operace.
K tomu žravému GC - Java má naopak velmi efektivní GC. Připomínám že jde o zkratku Garbage Collector, takže vzhledem k tomu že programátor má plně pod kontrolou kolik vytváří toho Garbage tak když programuje efektivně, GC nezatěžuje a program mu pak běhá velmi rychle. Když programátor nepřemýšlí a tvoří spoustu Garbage tak mu pak nezbývá než se vymlouvat na neefektivní GC.
Formulaci "Java na stacku nic neukládá (něco asi jo, nestudoval sem to víc, nezajímá mne)" radši nechám bez komentáře.
BTW, když si s tím chceš hrát, napřed si nastuduj binární soustavu a binární operátory, jinak fakt na profesora dojem neuděláš (vysvětli...), z netu to umí zkopírovat každej (v tvým případě ještě blbě). Jinak, proč mám dojem že na školách sou vymaštěný profesoři?
100% souhlas, kdyby mi někdo k zápočtu nebo na zkoušku přinesl tohle tak si ho pěkně vychutnám. Je naprosto evidentní že vůbec netuší co v tom programu je napsáno a co hůř: ani ho to nezajímá, vůbec to nemá otestované a naprosto mu není blbé to do toho programu dát! Copy&paste "programování" jako náhrada přemýšlení je příšernost kterou je třeba potírat kdykoliv a kdekoliv!
-
TO STAŘEŠINA: Hele, java na stacku pokud vím tak fakt nic neukládá, vše jede na heap. Pokud si Java guru, tak nepochybuju že mne můj názor vyvrátíš. Ale nevyvrátíš, že je java pomalá (a i GC je pomalé, je jedno jak je optimalizované, RAII bude vždy rychlejší->dokonce až 2 krát!!)....No, podle mého názoru fakt v jave s bitovejma operacema díru neudělá (s jeho přístupem). Spíš by dokázal ňákej program tímhle stylem rozbít. ALE, už jsem si uvědomil proč je takové tažení proti pointerům a RAII, takovídle tydýti z toho udělaj nástroj zkázy.
-
TO STAŘEŠINA: Hele, java na stacku pokud vím tak fakt nic neukládá, vše jede na heap.
Tak proč by existovala volba -Xss která nastavuje velikost stacku (pro každý thread)? Faktem je že kromě návratových adres pro volání (viz stack trace) jsou v Javě na stacku primitivní datové typy a reference na objekty, objekty samotné jsou alokované na stacku (výjimečně, to je optimalizace) nebo na heapu, jak uzná JVM za vhodné. Jinak je stack v Javě dost hloupý, už třeba jen to že je pro všechny thready stejně velký a konstantní (není možné ho rozšířit) může být v některých případech nepříjemné.
-
TO STAŘEŠINA: Hele, java na stacku pokud vím tak fakt nic neukládá, vše jede na heap. Pokud si Java guru, tak nepochybuju že mne můj názor vyvrátíš. Ale nevyvrátíš, že je java pomalá (a i GC je pomalé, je jedno jak je optimalizované, RAII bude vždy rychlejší->dokonce až 2 krát!!)....No, podle mého názoru fakt v jave s bitovejma operacema díru neudělá (s jeho přístupem). Spíš by dokázal ňákej program tímhle stylem rozbít. ALE, už jsem si uvědomil proč je takové tažení proti pointerům a RAII, takovídle tydýti z toho udělaj nástroj zkázy.
V Javě vlastně ani klasicky pojatý zásobník není, jsou to jen svázané zásobníkové rámce, které navíc nemusí ležet za sebou (většinou ano, ale není to nutné). Hodnoty primitivních datových typů z lokálních proměnných v této oblasti zásobníku jsou, popř. se kopírují na zásobník operandů. Ale ono je to jedno, stejně se bajtkód později převede JITem do nativního kódu s již docela normálně pojatým zásobníkem, alespoň na těch zvrácených :-) architekturách, které něco podobného potřebují používat :-) Ale asi jsme úplně odbočili od původního tématu; pokud se tazatel zabývá bitovými operacemi, tak si to může prozkoušet i v Javě, prakticky se to použije při ukládání bitových polí, ale na to jsou v praxi lepší způsoby, BitSet, BigInteger atd.
-
... pokud se tazatel zabývá bitovými operacemi, tak si to může prozkoušet i v Javě, prakticky se to použije při ukládání bitových polí, ale na to jsou v praxi lepší způsoby, BitSet, BigInteger atd.
... EnumSet. :)
-
Ale nevyvrátíš, že je java pomalá (a i GC je pomalé, je jedno jak je optimalizované, RAII bude vždy rychlejší->dokonce až 2 krát!!)
Problém není ani tak v tvrzení "java je pomalá" (to je relativní, záleží s čím se porovnává), ale spíš v předchozím výroku "java je pomalá, takže nemá cenu optimalizovat" - to je self-fulfilling prophecy.
-
TO PODLESH: pěkný rekurzivní výrok xD. Ale ne. Tak sem to nemyslel. Optimalizovat samozřejmě Javu také, ale používání bitových operací mi přijde (když to není vyžadováno...) na tak pomalí jazyk zbytečně hardcore optimalizace. C/C++ neřeknu ani slovo, tam je základní filozofie co nejefektivnější kód.
-
tak pomalí jazyk
Teď nevím, zda jste si tím připravoval půdu pro omluvu, že za to „í“ nemůžete, protože čeština je tak chybový jazyk… Nebo jestli spojení „pomalý programovací jazyk“ myslíte vážně. Nenapadlo vás, že je možné zdrojový kód v jednom jazyce převést do zdrojového kódu v jazyce jiném? Že je možné ve dvou jazycích napsat takový kód, který povede na stejnou posloupnost instrukcí? To trochu nabourává vaší představu, že může existovat rychlý nebo pomalý programovací jazyk, nemyslíte?
-
TO PODLESH: pěkný rekurzivní výrok xD. Ale ne. Tak sem to nemyslel. Optimalizovat samozřejmě Javu také, ale používání bitových operací mi přijde (když to není vyžadováno...) na tak pomalí jazyk zbytečně hardcore optimalizace. C/C++ neřeknu ani slovo, tam je základní filozofie co nejefektivnější kód.
Nějak nechápu to porovnávání bitových operací a optimalizací. Pár brutálně optimalizovaných kousků kódu jsem už psal, ale na bitových operacích to teda nestálo ani omylem. Ale vzhledem k těm perlám, co tu trousíš, se až tak moc nedivím.
-
TO FILIP JIRSÁK: No hele, Java je interpretovaná ... = pomalá. TO JSH: To že nevíš jak vypadá optimalizace pomocí bitových operací ještě nic neznamená, asi toho nevíš víc (třeba ušetření místa hmm?).
-
Tak nejak mi to pripomnelo meho kamarada, ktery ve druhem ci tretim rocniku VS - informatika - vyrabel v ramci nejakeho projektu prevod byte do retezce v binarnim formatu (osm jednicek/nul). Delal to v pascalu. Jeho reseni vypadalo asi takhle:
if b = 0 then
s := '00000000';
else if b = 1 then
s := '00000001';
else if b = 2 then
s := '00000010';
.....
Cili funkce na prevod zabrala neco lehce pres 512 radku a obsahovala 256 ifu. :)
Nejvic me ale dostalo, ze tam mel i opacny prevod - binarni zapis cisla na byte a tam bylo dalsich 256 ifu a samosebou cca dvakrat tolik radku.
Kamarad je dnes inzenyr :)
-
No hele, Java je interpretovaná ... = pomalá.
Nerovná se. Navíc Javu můžete klidně překládat do nativního kódu, běžně používané JVM pro PC to tak dělají, pokud jim explicitně neřeknete, že mají bajtkód jen interpretovat. C může být také interpretované, takže podle vaší logiky je také pomalé.
To že nevíš jak vypadá optimalizace pomocí bitových operací ještě nic neznamená, asi toho nevíš víc (třeba ušetření místa hmm?).
To, že vy tvrdíte, že víte, jak vypadá optimalizace pomocí bitových operací, neznamená, že byste věděl cokoli jiného. Zatím jste se moc nepředvedl.
-
TO PODLESH: pěkný rekurzivní výrok xD. Ale ne. Tak sem to nemyslel. Optimalizovat samozřejmě Javu také, ale používání bitových operací mi přijde (když to není vyžadováno...) na tak pomalí jazyk zbytečně hardcore optimalizace. C/C++ neřeknu ani slovo, tam je základní filozofie co nejefektivnější kód.
Tak ona optimalizace na objem obsazene pameti je v tomto pripade uplne stejna v C ci v Jave, navic to vysledke bitove pole obsadi (podle "umeni" programatora) prakticky stejne mnozstvi haldy ne? (+pokud to nekdo nebude chtit prosevat GC, taky je to relativne snadne).
Pokud se jedna o optimalizaci na rychlost, nelze obecne rict, jestli bude lepsi pole intu ve funkci pole booleanu nebo to nacpavat do jednotlivych bitu - zalezi na spouste veci, takze by se stejne musel pouzit benchmark, popr. se mrknout na vygenerovany assembler.
-
Tak nejak mi to pripomnelo meho kamarada, ktery ve druhem ci tretim rocniku VS - informatika - vyrabel v ramci nejakeho projektu prevod byte do retezce v binarnim formatu (osm jednicek/nul). Delal to v pascalu. Jeho reseni vypadalo asi takhle:
if b = 0 then
s := '00000000';
else if b = 1 then
s := '00000001';
else if b = 2 then
s := '00000010';
.....
Cili funkce na prevod zabrala neco lehce pres 512 radku a obsahovala 256 ifu. :)
Nejvic me ale dostalo, ze tam mel i opacny prevod - binarni zapis cisla na byte a tam bylo dalsich 256 ifu a samosebou cca dvakrat tolik radku.
Kamarad je dnes inzenyr :)
No a nejzajimavejsi na tom je, ze tento Tvuj prispevek je ted zaindexovan googlem a az si bude nekdy v budoucnu chtit nejaky student "vypomoci" s domaci ulohou, treba zrovna na nej narazi a udela ^Cizi^Vlastni :D
-
TO FILIP JIRSÁK: Java má taktéž GC, což je zpomalení jak prase. Vzhledem k tomu že hello world sežere několik MB, tak prosím nemluv o efektivitě Javy. To zaprvé. A za druhé, jediná a opravdu velká výhoda Javy je v multiplatformnosti. A ta se ztratí když se program nepřeloží do bajtkódu.
-
Boze, boze, boze...
Java má taktéž GC, což je zpomalení jak prase.
Alokace v ramci GC je na par instrukci, schvalne srovnej s tim, jak vypada dvojice malloc/free. Navic GC preskladava data v pameti, tim je mnohem vic cache-friendly nez explicitni alokace, ktera nechava pamet fragmentovanou. V rade pripadu to vyjde +/- nastejno.
Vzhledem k tomu že hello world sežere několik MB
To nezere hello world, ale behove prostredi, ktere je nutne tak nejak z podstaty.
A ta se ztratí když se program nepřeloží do bajtkódu.
Prosim te, vygoogli si aspon pojem JIT preklad, nez se zacnas vyjadrovat k Jave nebo k necemu ze sveta pocitacu.
-
TO FILIP JIRSÁK: Java má taktéž GC, což je zpomalení jak prase. Vzhledem k tomu že hello world sežere několik MB, tak prosím nemluv o efektivitě Javy. To zaprvé. A za druhé, jediná a opravdu velká výhoda Javy je v multiplatformnosti. A ta se ztratí když se program nepřeloží do bajtkódu.
Těch dobrých vlastností je tam mnohem víc; od stability a velkého záběru základních knihoven přes automatickou správu paměti až po možnost vzdáleného managementu JVM i samotné apikace; potom samozřejmě taky vlastnosti toho programovacího jazyka, které jsou sice založeny na OOP (což ne vždy je ta správná cesta :-), ale v oblasti staticky typovaných OO jazyků je na tom Java podle mě dost dobře, i přes některé přehmaty vzniklé i tím, že se Gosling až moc snažil zalíbit lidem od céčka :-) [a to říkám jako programátor pracující někdy až hodně low level].
-
TO ded.kenedy: To že sežere Java jen tak z podstaty několik mega právě považuju za špatné (teda běhové prostředí, pro hnidopichy). Alokace je skutečně při použití GC velmi rychlá, samotný hledání garbage už ani tak moc ne xDD. GC přeskládává data v paměti, hezký. No, zas takový žůžo to není, když musí takhle překopírovávat sem a tam třeba ... 200 MB či víc...A využití cache? OS používají page coloring, takže tvou prezentovaná výhoda ztrácí na kráse. Pokud netušíš co to je, tak googl. A radši už nepiš, krom vykváknutí z temnoty si toho moc jinýho neukázal xD
-
TO PAVEL TISNOVSKY: Souhlasím s Vámi. Kdyby Java neměla žádné výhody, nebyla by tak používaná. Navíc, v dnešní době se na efektivitu kódu zas tak nehledí, je levnější dokoupit komponenty než optimalizovat.
-
To že sežere Java jen tak z podstaty několik mega právě považuju za špatné
A to, ze operacni system zabira pamet taky povazujes za spatne?
No, zas takový žůžo to není, když musí takhle překopírovávat sem a tam třeba ... 200 MB či víc..
Realne neni problem, objektu, ktere preziji eden je sakramentsky malo. Uvolnit velky kus pameti a ne se trckat s kazdym kouskem pameti je taky sakramentsky rozdil.
A využití cache? OS používají page coloring
Tak treba Linux page coloring nema. I tak sance, ze dva objekty spadnou do stejne cache line je u compacting collectoru vetsi nez v pripade malloc/free.
A radši už nepiš, krom vykváknutí z temnoty si toho moc jinýho neukázal xD
To jsi mi to nandal!
-
To že sežere Java jen tak z podstaty několik mega právě považuju za špatné (teda běhové prostředí, pro hnidopichy).
Dufam, ze nepouzivas to spatne to behove prostredie pre programy nazyvane "operacny system". Ved to ide aj bez neho a usetris par MB v pamati ;-).
GC přeskládává data v paměti, hezký. No, zas takový žůžo to není, když musí takhle překopírovávat sem a tam třeba ... 200 MB či víc..
Sem-tam sa to tak casto nekopiruje - prevazuje kopirovanie "tam". U generaceho garbage collectoru sa vlastne najcastejsie uvolnuje Eden a to dava zmysel.
-
TO PAVEL TISNOVSKY: Souhlasím s Vámi. Kdyby Java neměla žádné výhody, nebyla by tak používaná. Navíc, v dnešní době se na efektivitu kódu zas tak nehledí, je levnější dokoupit komponenty než optimalizovat.
Nojo je to tak, nijak z toho nadseny nejsem (reseni problemu tim, ze se na nej hodi silnejsi HW a kdyz to nestaci, tak jeste vice HW), na druhou stranu ted vyvoj procesoru s vyssi hodinovou frekvenci trosku zastavuje a spis se pridavaji jadra - takze to zase je z vyvojarskeho hlediska zajimave, muzeme si hrat s multiprocessingem na ruzne urovni a neni to (aspon na par nejblizsich let) jen bezduche lepeni komponent dohromady :)
-
TO PAVEL TISNOVSKY: Je to tak. Osobně velmi rád studuji různé experimentální architektury s mnoha jádry. Třeba Epiphany. Více jader je budoucnost, frekvenci není tak snadné šroubovat nahoru, a pak to navíc pekelně žere (a hřeje).
To DED.KENEDY: No, ty asi budeš ňákej zhrzenej Javista, kterej není ochoten akceptovat že jeho java není rychlejší než světlo ... až si rozšíříš obzory, přijď.
TO STUDENT: Radši běž studovat, potřebuješ to...zřejmě si nepochopil smysl diskuze a to co chci říci.
-
To že sežere Java jen tak z podstaty několik mega právě považuju za špatné
Když plus mínus tu samou paměť sežere běhové prostředí C/C++ (základní knihovny), tak to za špatné nepovažujete?
Java má taktéž GC, což je zpomalení jak prase.
Nejdřív jste tvrdil, že je Java pomalá, protože je interpretovaná. Když jste byl usvědčen z omylu, zkusil jste něco jiného. A zase špatně. Například GC používá i spousta aplikací napsaných v C nebo C++. Dále existují různé způsoby, jak GC implementovat, jenom v JVM od Oraclu je jich implementováno několik. Výkon GC také závisí na tom, jak programátor s pamětí zachází. Takže opět, to, že něco má GC, nevypovídá vůbec nijak o rychlosti aplikace - může být kvůli špatnému GC a špatnému programu velmi pomalá, a taky může být díky dobrému GC a dobrému programu rychlejší, než aplikace s ruční správou paměti.
Zatím tu prezentujete jen pověry. A ve výsledku není rozdíl, zda programátor napíše program neefektivně kvůli tomu, že si neumí dohledat efektivní řadicí algoritmus, nebo kvůli tomu, že věří pověrám.
-
(http://www.wwenews.net/wp-content/uploads/2014/02/obvious-troll-is-obvious.jpg)
-
TO FILIP JIRSÁK: No, takže, standardní C++ knihovny opravdu nesežerou MB RAMky...To jen tak pro pořádek. Nebyl jsem usvědčen z omylu, jen sem neměl energii reagovat na ty marný kraviny xD Takže, Java je pomalá protože je interpretovaná (jasně, používá JIT překlad no a?) a má GC. A prosím, nekecej nic o JIT překladači. Je jedno že se na začátku kusy programu přeloží, furt je to zpomalení oproti nativnímu kódu. A GC? Prosimtě, naprogramoval si někdy něco bez GC? Asi ne. Tak nekecej, jinak by ses totiž nesnažil tvrdit že "voda je suchá"(obrazně řečeno) xD. Jinak pěknej obrázek trola, sedí na tebe xD.
-
Ano, je možné i v C++ používat GC, ale není to nutné (ani implicitní), v Javě ano...
-
No, takže, standardní C++ knihovny opravdu nesežerou MB RAMky...
Kolik tedy sežerou? A kolik sežere třeba Oracle Java SE Embeded? Určitě to víte, když jste takový odborník.
Takže, Java je pomalá protože je interpretovaná (jasně, používá JIT překlad no a?) a má GC.
Aby tohle tvrzení platilo, musel byste nejprve dokázat, že:
- Java je interpretovaná
- Interpretace nebo JIT překlad znamená zpomalení proti nativnímu kódu
- GC znamená zpomalení
Přeju hodně úspěchů při dokazování, zatím se to nikomu nepodařilo.
Jinak pokud je podle vás interpretace, JIT nebo GC taková brzda, proč nekritizujete také ostatní programy, které tyhle techniky používají? Třeba Linuxové jádro, tam musejí být některé části také hrozně pomalé, když používají GC nebo interpret.
Prosimtě, naprogramoval si někdy něco bez GC? Asi ne.
Zase vedle.
-
Takže, Java je pomalá protože je interpretovaná (jasně, používá JIT překlad no a?) a má GC.
java je pomala
a) v porovnani s cim?
b) pri akych konkretnych problemoch?
-
No vážně, co blbnete? Samo o sobě je to téma dost kontroverzní a málokdy vede k něčemu, ale pokoušet se diskutovat s někým kdo začne házet osobní invektivy hned při první náznaku kritiky, to je fakt jen otravování ovzduší.
-
TO FILIP JISÁK:
1) Hello world sežere v C++ 156 KB. Java SE Embedded? Nepoužívám, nejsem schopen říci kolik bere paměti.
2) Musel bych dokázat zpomalení? xD Důkaz je skoro každá aplikace napsaná v Javě xDD
3) Radši nic, nebo bych zas hodil nějakou osobní invektivu xD ...
-
Pre info: Java ME Embedded dokaze bezat na 192 KB RAM. Tym sa mysli aj viac ako hello world. Je pravda, ze to nie je Java SE, ale od takeho maleho runtime snad nikto necaka ovela viac ako od c runtime.
-
1) Hello world sežere v C++ 156 KB. Java SE Embedded? Nepoužívám, nejsem schopen říci kolik bere paměti.
2) Musel bych dokázat zpomalení? xD Důkaz je skoro každá aplikace napsaná v Javě xDD
3) Radši nic, nebo bych zas hodil nějakou osobní invektivu xD ...
Aha, takže nevíte, důkazy nemáte, a ještě si sám protiřečíte. To jsou opravdu pádné důvody pro způsob, jakým tady vystupujete. Čeština pro to má hezké rčení: prázdný sud nejvíc duní.
-
1) Hello world sežere v C++ 156 KB. Java SE Embedded? Nepoužívám, nejsem schopen říci kolik bere paměti.
2) Musel bych dokázat zpomalení? xD Důkaz je skoro každá aplikace napsaná v Javě xDD
3) Radši nic, nebo bych zas hodil nějakou osobní invektivu xD ...
Aha, takže nevíte, důkazy nemáte, a ještě si sám protiřečíte. To jsou opravdu pádné důvody pro způsob, jakým tady vystupujete. Čeština pro to má hezké rčení: prázdný sud nejvíc duní.
Rád bych získal vysvětlení, že co tu předvádíte se dotýká tématu : Java: byte to 8 boolean ;D Trochu mi to připomíná diskuzi teenagerů kdo ho má většího, či kdo se dostal více pičkám mezi stehna. .... 8)
PS. já sám programuji pro zábavu a hlavně z 99% jenom v Javě ale
- zkoušel jste někdo násobení matic (datových typu int) třeba matice A 20000x20000 s nasobením matice B 20000x20000 v C vs čistě Java(bez JNI) na stejném stroji? Zde je Java skutečně skoro 2x pomalejší. A dle mnou provedených pokusů není problém vysledovat lineární závislost zpomalení na velikosti matic. Není problém vám tu lupnost triviální zdroje ať si to ověříte a budu vděčen když mi někdo ukážete jakoukoliv možnost jak to zrychlit aby to bylo konkurenceschopné.
-
- zkoušel jste někdo násobení matic (datových typu int) třeba matice A 20000x20000 s nasobením matice B 20000x20000 v C vs čistě Java(bez JNI) na stejném stroji? Zde je Java skutečně skoro 2x pomalejší. A dle mnou provedených pokusů není problém vysledovat lineární závislost zpomalení na velikosti matic. Není problém vám tu lupnost triviální zdroje ať si to ověříte a budu vděčen když mi někdo ukážete jakoukoliv možnost jak to zrychlit aby to bylo konkurenceschopné.
V jiném vlákně jsem zkoušel počítat RMSD (viz http://forum.root.cz/index.php?topic=8163.msg84097#msg84097). Začal jsem s časy: Java: 14.984s, C++/icc: 5.58s, C++/g++: 2.64s. A nakonec jsme to u Javy stáhli až na 4.23s.
V Javě jsou pole trochu o něčem jiném, takže bych začal tím, že bych tu matici reprezentoval jedním polem.
-
budu vděčen když mi někdo ukážete jakoukoliv možnost jak to zrychlit aby to bylo konkurenceschopné.
Obvyklý postup, jak něco zrychlit, je použít vhodný nástroj. Třeba pojídání polévky zrychlíte tak, že odložíte vidličku a místo ní použijete lžíci. Až se po polévce pustíte do řízku, je zase dobré místo lžíce použít vidličku. Na různé věci se totiž hodí různé nástroje – to, že použijete špatný nástroj, není chyba toho nástroje. Pokud někdo jí polévku vidličkou a usuzuje z toho, že vidlička je pomalá, je to především jeho hloupost.
Pokud potřebujete násobit velké matice, použijte k tomu výpočty na GPU. Volat je můžete jak z C tak z Javy.
-
PS. já sám programuji pro zábavu a hlavně z 99% jenom v Javě ale
- zkoušel jste někdo násobení matic (datových typu int) třeba matice A 20000x20000 s nasobením matice B 20000x20000 v C vs čistě Java(bez JNI) na stejném stroji? Zde je Java skutečně skoro 2x pomalejší. A dle mnou provedených pokusů není problém vysledovat lineární závislost zpomalení na velikosti matic. Není problém vám tu lupnost triviální zdroje ať si to ověříte a budu vděčen když mi někdo ukážete jakoukoliv možnost jak to zrychlit aby to bylo konkurenceschopné.
Ja bych se na to rad podival, pokud se pouzivaji "normalni" matice v Jave, tak tady prostor pro urychleni pravdepodobne bude.
-
PS. já sám programuji pro zábavu a hlavně z 99% jenom v Javě ale
- zkoušel jste někdo násobení matic (datových typu int) třeba matice A 20000x20000 s nasobením matice B 20000x20000 v C vs čistě Java(bez JNI) na stejném stroji? Zde je Java skutečně skoro 2x pomalejší.
Talk is cheap, show me the code ;-).
-
Tak začneme : program který vygeneruje soubor obsahujici matici nahodných cisel
Pozn. nezapomět nastavit v Java pri spoustění parametr -Xmx + hlavně při větších maticích je nutná větší RAM
(viz. např. Java pro jednu matici v paměti : 20 000 * 20 000 = 400 000 000 * 4byte(int) = 1matice(1,6GB RAM) +prostředí + Windows atd..)
import java.util.*;
import java.io.*;
public class B02_GeneratorMaticInt {
@SuppressWarnings("resource")
private static int nacteniVelikosti() {
Scanner key = new Scanner(System.in);
System.out.print("Vlozte Celociselne Cislo :");
int n = key.nextInt();
return n; }
@SuppressWarnings("resource")
private static String nacteniNazvu() {
Scanner key = new Scanner(System.in);
System.out.print("Vlozte Nazev souboru :");
String jmeno = key.nextLine();
return jmeno; }
private static int [][] vygenerovaniMatice(int velikost){
int [][] matice = new int [velikost][velikost];
for(int i=0;i<matice.length;i++) { // nacitani hodnot do matice z klavesnice
for(int j=0;j<matice[i].length;j++) {
matice[i][j] = (int) (Math.random() * 9); } } // matici naplnime hodnotami od 0 do 9
return matice; }
private static void ulozeniMatice(String s, int [][] matice) {
File NazevSoub = new File(s);
FileWriter ZapisovaciSoubor = null;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
try {
ZapisovaciSoubor = new FileWriter(NazevSoub); }
catch (IOException e) {
System.out.println("Nepodarilo se vytvorit soubor ");
e.printStackTrace(); }
try {
ZapisovaciSoubor.write(matice.length+radek);
for(int i=0;i<matice.length;i++) { // nacitani hodnot do matice z klavesnice
for(int j=0;j<matice[i].length;j++) {
ZapisovaciSoubor.write(matice[i][j]+" "); }
ZapisovaciSoubor.write(radek); } }
catch (Exception e) {System.out.println("Nepodarilo se provest zapis matice"); }
try {
ZapisovaciSoubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } } // uzavreme soubor
@SuppressWarnings("unused")
private static void tiskMatice(int [][] matice) {
System.out.println("Zde je vypsana matice");
for (int i = 0; i < matice.length; i++) {
for (int j = 0; j < matice[i].length; j++) {
System.out.format("%d ", matice[i][j]); }
System.out.println(); } }
public static void main(String [] args) {
String jmenoSouboru;
int velikost;
System.out.println("Program pro vygenerovani matic a jejich ulozeni do souboru");
System.out.println("Vlozte velikost matice - cele cislo (bez desetinne carky)");
while(true) { // nekonecna smycka
try{
velikost=nacteniVelikosti(); break; }
catch(RuntimeException E){ System.err.print("Vstup neni celociselne cislo"); } }
System.out.println("Vlozte prosim jmeno souboru do ktereho chcete provest ulozeni vygenerovane matice");
while(true) { // nekonecna smycka
try {
jmenoSouboru = nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
int [][] Matice;
Matice = vygenerovaniMatice(velikost);
//tiskMatice(Matice); // pro kontrolu
ulozeniMatice(jmenoSouboru,Matice);
}
}
Zde je zdrojak v Cčku, který je schopen načíst námi vygenerovaný soubor
#include<stdio.h>
#include<time.h>
main(){
clock_t startCteni1,konecCteni1,startCteni2,konecCteni2,startNasob,konecNasob,startZapis,konecZapis;
printf("Program na vypocet nasobeni matic\n");
char nazevSouboru1 [15];
printf("Vlozte jmeno souboru pro matici 1 :");
scanf("%15s",nazevSouboru1); // pozor cteme pouze prvnich 15 znaku --- %15s
char nazevSouboru2 [15];
printf("Vlozte jmeno souboru pro matici 2 :");
scanf("%15s",nazevSouboru2); // pozor cteme pouze prvnich 15 znaku --- %15s
FILE *fr1,*fr2;
fr1 = fopen(nazevSouboru1,"r"); // nacteme soubor 1
int velikost1,velikost2;
fscanf(fr1,"%i",&velikost1);
printf("Zde je prvni cislo : %i\n",velikost1);
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) MATICI A pointeru na pointer **/
int i,j,k;
int **maticeA;
maticeA=(int**)malloc(velikost1*sizeof(int*));
for(i=0;i<velikost1;i++) {
maticeA[i]=(int*)malloc(velikost1*sizeof(int)); }
/************* Nacitame matici A *******************/
printf("Nacitame matici 1\n");
startCteni1=clock();
for(i=0;i<velikost1;i++) {
for(j=0;j<velikost1;j++){
fscanf(fr1,"%i",&maticeA[i][j]); } }
konecCteni1=clock();
printf("Nacitani prvni matice trvalo %6.2f sec\n",(konecCteni1-startCteni1)/(double) CLOCKS_PER_SEC);
/*printf("Zde je nactena matice A\n");
for(i=0;i<velikost1;i++) {
for(j=0;j<velikost1;j++) {
printf("%i ",maticeA[i][j]); }
printf("\n"); }*/
fclose(fr1);
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) MATICI B pointeru na pointer **/
fr2 = fopen(nazevSouboru2,"r"); // nacteme soubor 1
fscanf(fr2,"%i",&velikost2);
int **maticeB;
maticeB=(int**)malloc(velikost2*sizeof(int*));
for(i=0;i<velikost2;i++) {
maticeB[i]=(int*)malloc(velikost1*sizeof(int)); }
/************* Nacitame matici B *******************/
printf("Nacitame matici 2\n");
startCteni2=clock();
for(i=0;i<velikost2;i++) {
for(j=0;j<velikost2;j++){
fscanf(fr2,"%i",&maticeB[i][j]); } }
konecCteni2=clock();
printf("Nacitani druhe matice trvalo %6.2f sec\n",(konecCteni2-startCteni2)/(double) CLOCKS_PER_SEC);
/*printf("Zde je nactena matice B\n");
for(i=0;i<velikost2;i++) {
for(j=0;j<velikost2;j++) {
printf("%i ",maticeB[i][j]); }
printf("\n"); }*/
fclose(fr2);
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) MATICI C pointeru na pointer **/
printf("Provadime nasobeni matic \n");
int **maticeC;
maticeC=(int**)malloc(velikost1*sizeof(int*));
for(i=0;i<velikost2;i++) {
maticeC[i]=(int*)malloc(velikost2*sizeof(int)); }
/************* Nasobime matici A x B = vznik matice C *******************/
startNasob=clock();
for(i=0;i<velikost1;i++) { // cyklus pro nasobeni matic
for(j=0;j<velikost2;j++) {
maticeC[i][j] = 0;
for(k=0;k<velikost1;k++) {
maticeC[i][j]=maticeC[i][j] + maticeA[i][k] * maticeB[k][j]; } } }
konecNasob = clock();
printf("Doba nasobeni matice %6.2f sec\n",(konecNasob-startNasob)/(double) CLOCKS_PER_SEC);
/*printf("Zde je vypoctena matice\n");
for(i=0;i<velikost1;i++) {
for(j=0;j<velikost2;j++) {
printf("%i ",maticeC[i][j]); }
printf("\n"); }*/
/****************** Ulozime matici do Souboru ***************************/
free(maticeA);maticeA=NULL; // vymazeme hodnoty a referenci
free(maticeB);maticeB=NULL; // vymazeme hodnoty a referenci
char nazevSouboru3 [15];
printf("Vlozte jmeno souboru pro matici 3 (vyslednou):");
scanf("%15s",nazevSouboru3); // pozor cteme pouze prvnich 15 znaku --- %15s
FILE *fr3;
fr3 = fopen(nazevSouboru3,"w"); // nacteme soubor 1
fprintf(fr3,"%i\n",velikost1); // ulozime rad matice
startZapis =clock();
for(i=0;i<velikost2;i++) {
for(j=0;j<velikost2;j++) {
fprintf(fr3,"%i ",maticeC[i][j]); }
fprintf(fr3,"\n"); }
konecZapis = clock();
printf("Doba ukladani matice %6.2f sec\n",(konecZapis-startZapis)/(double) CLOCKS_PER_SEC);
fclose(fr3);
free(maticeC);maticeC=NULL; // vymazeme hodnoty a referenci
printf("Program ukoncite stiknutim libovolne klavesy");
getch(); // cekame na stiknuti klavesnice
}
A zde je ten naprosto identický kód v Javě
import java.io.*;
import java.util.*;
public class B05_NasobeniMaticInt {
@SuppressWarnings("resource")
private String nacteniNazvu() {
Scanner key = new Scanner(System.in);
System.out.print("Vlozte Nazev souboru :");
String jmeno = key.nextLine();
return jmeno; }
private int [][] nacteniMatice(String s) {
File NazevSoub = new File(s);
FileReader CteciSoubor=null;
BufferedReader Soubor=null;
int velikost;
try { //Zkousime otevrit pripojeni k souboru
CteciSoubor = new FileReader(NazevSoub);
Soubor = new BufferedReader(CteciSoubor); }
catch (IOException e) {
System.out.println("Nepodarilo se otevri soubor pro cteni");
e.printStackTrace(); }
int [][] matice = null;
try { // Zkusime nacist hodnoty
String retezec = Soubor.readLine(); // nacteme prvni radek kde je pouze velikost matice
velikost = Integer.valueOf(retezec).intValue(); // prevedem velikost na integer
matice = new int [velikost][velikost];
for(int i=0;i<matice.length;i++) { // nacitani hodnot do matice z klavesnice
retezec = Soubor.readLine(); // nacteme do stringu cely radek
String [] podretezce = retezec.split(" "); // vytvorime pole hodnot
for(int j=0;j<matice[i].length;j++) {
matice[i][j] = Integer.valueOf(podretezce[j]).intValue(); } } } // Prevedeme jednotlive prvky pole stringu na integer do jednotlivych casti poli
catch (Exception e) {System.out.println("Nepodarilo se provest zapis matice"); }
try { // Zkusime uzavrit pripojeni k souboru
CteciSoubor.close();
Soubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } // uzavreme soubor
return matice; }
@SuppressWarnings("unused")
private void tiskMatice(int [][] matice) {
System.out.println("Zde je vypsana matice");
for (int i = 0; i < matice.length; i++) {
for (int j = 0; j < matice[i].length; j++) {
System.out.format("%d ", matice[i][j]); }
System.out.println(); } }
private int [][] nasobeniMatic(int [][] maticeA,int [][] maticeB) {
int [][] maticeNasob=new int [maticeA.length][maticeB[0].length]; // u vysledne matice rozhoduji sloupce a pak radky
for(int i=0;i<maticeNasob.length;i++) { // cyklus pro nasobeni matic
for(int j=0;j<maticeNasob[i].length;j++) {
maticeNasob[i][j] = 0;
for(int k=0;k<maticeNasob.length;k++) {
maticeNasob[i][j]=maticeNasob[i][j] + maticeA[i][k] * maticeB[k][j]; } } }
return maticeNasob; }
private void ulozeniMatice(String s, int [][] matice) {
File NazevSoub = new File(s);
FileWriter ZapisovaciSoubor = null;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
try {
ZapisovaciSoubor = new FileWriter(NazevSoub); }
catch (IOException e) {
System.out.println("Nepodarilo se vytvorit soubor ");
e.printStackTrace(); }
try {
ZapisovaciSoubor.write(matice.length+radek);
for(int i=0;i<matice.length;i++) { // nacitani hodnot do matice z klavesnice
for(int j=0;j<matice[i].length;j++) {
ZapisovaciSoubor.write(matice[i][j]+" "); }
ZapisovaciSoubor.write(radek); } }
catch (Exception e) {System.out.println("Nepodarilo se provest zapis matice"); }
try {
ZapisovaciSoubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } } // uzavreme soubor
@SuppressWarnings("unused")
public static void main(String [] args) {
B05_NasobeniMaticInt objekt = new B05_NasobeniMaticInt();
System.out.println("Program pro nasobeni matic integeru pro nacitani ze souboru");
String jmenoSouboru1,jmenoSouboru2,jmenoSouboru3;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
System.out.println("Vlozte prosim jmeno souboru ze ktereho chcete nacit matici cislo 1");
while(true) { // nekonecna smycka
try {
jmenoSouboru1 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
System.out.println("Vlozte prosim jmeno souboru ze ktereho chcete nacit matici cislo 2");
while(true) { // nekonecna smycka
try {
jmenoSouboru2 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
System.out.println("Provedem nacteni matice do pole :");
int [][] MaticeA,MaticeB,MaticeZnasobena;
long nacteni1 = System.currentTimeMillis();
MaticeA = objekt.nacteniMatice(jmenoSouboru1);
//tiskMatice(MaticeA); // pro kontrolu
long nacteni2 = System.currentTimeMillis();
MaticeB = objekt.nacteniMatice(jmenoSouboru2);
long nactenikonec = System.currentTimeMillis();
System.out.println("Nacitani matice prvni :\t"+(nactenikonec-nacteni2)+" milisekund\nNacteni matice druhe :\t"+(nacteni2-nacteni1)+" milisekund");
long zacatekNasobeni = System.currentTimeMillis();
MaticeZnasobena = objekt.nasobeniMatic(MaticeA,MaticeB);
long konecNasobeni = System.currentTimeMillis();
System.out.println("Nasobeni matic trvalo :\t"+(konecNasobeni-zacatekNasobeni)+" milisekund\nVelikost Matice :"+MaticeZnasobena.length);
//tiskMatice(MaticeZnasobena); // pro kontrolu
System.out.println("Vlozte prosim jmeno souboru do ktereho chcete ulozit vyslednou matici");
while(true) { // nekonecna smycka
try {
jmenoSouboru3 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
long ulozeni1 = System.currentTimeMillis();
objekt.ulozeniMatice(jmenoSouboru3,MaticeZnasobena);
long ulozeni2 = System.currentTimeMillis();
System.out.println("Ulozeni matice trvalo :\t"+(ulozeni2-ulozeni1)); }
}
Upozorňuji že neřeším načítaní ze souboru, ukládání do souboru ale část kódu kde probíhá násobení matic. Dále upozorňuji neberte vážně mé komentáře hlavně Cčku - terminologii daného jazyka neovládám. V té Javě beru i fígle typu nastavení Oracle JVM atd.. Fakt se rád poučím od lidí, kteří se tomu věnují mnohem,mnohem déle. Většinou je to tu plné blbých hospodských keců (typu :Kaufland je nejlevnější, pivo je zdravé atd..) všechno velmi obecné bez konkrétních důkazů. Zatím je závěr pro mě takový že na matematické výpočty je stále Java zásadně pomalejší. Doměnka :(nechce se mi kupovat stroj s 128,..,512 GBRAM abych si to ověřil) U větších matic velikosti 50 000, 100 000, 200 000 to budou skoro řádové rozdíly v času.
-
PS. já sám programuji pro zábavu a hlavně z 99% jenom v Javě ale
- zkoušel jste někdo násobení matic (datových typu int) třeba matice A 20000x20000 s nasobením matice B 20000x20000 v C vs čistě Java(bez JNI) na stejném stroji? Zde je Java skutečně skoro 2x pomalejší. A dle mnou provedených pokusů není problém vysledovat lineární závislost zpomalení na velikosti matic. Není problém vám tu lupnost triviální zdroje ať si to ověříte a budu vděčen když mi někdo ukážete jakoukoliv možnost jak to zrychlit aby to bylo konkurenceschopné.
Tohle sem nikdy neresil v Jave, ale v C#(.NET) jo, a tam jsem to taky vyresil :). Tipnul bych si, ze v Jave to bude velice podobny. Problem je v hlidani, jestli index nezasahuje mimo hranice pole (for cykly jsou proste zlo), ve chvili kdy v C# predelate kod na unsafe s pointrama tak rozdil vykonu mezi C++ a C# je nemeritelny. Jenze to jde dotahnout jeste dal, v C# i pri velikosti matice 1024*1024 ziskate dalsi 4 nasobny zrychleni jenom pouzitim nativnich knihoven (v mim pripade MathNet.Numerics.MKL). To bych taky povazoval za finalni reseni, sezente si optimalizovanou knihovnu a dosahnete bez prace rychlost na kterou se pravdepodobne rucne nedostanete.
-
vas kod (teraz opomeniem styl) som spustil na svojom stroji a nasledne som pustil verziu napisanu s epml
300x300 = 78 ms
EPML 300x300 = 31 ms
1000 x 1000 = 8320 ms
epml 1000x1000 = 957 ms
epml 5000x5000 = 125512 ms
-
A zde je ten naprosto identický kód v Javě
Provedl jsem v rychlosti jen jednu úpravu - převod na pole. Pro velikost 2000 trvalo násobení 92518 milisekund, po úpravě 14225 milisekund.
import java.io.*;
import java.util.*;
public class B06_NasobeniMaticInt {
class Matice {
final int [] matice;
final int velikost;
public Matice(int v) {
velikost = v;
matice = new int[velikost*velikost];
}
final public int get(int i, int j) {
return matice[i*velikost+j];
}
final public void set(int i, int j, int v) {
matice[i*velikost+j] = v;
}
}
@SuppressWarnings("resource")
private String nacteniNazvu() {
Scanner key = new Scanner(System.in);
System.out.print("Vlozte Nazev souboru :");
String jmeno = key.nextLine();
return jmeno; }
private Matice nacteniMatice(String s) {
File NazevSoub = new File(s);
FileReader CteciSoubor=null;
BufferedReader Soubor=null;
int velikost;
try { //Zkousime otevrit pripojeni k souboru
CteciSoubor = new FileReader(NazevSoub);
Soubor = new BufferedReader(CteciSoubor); }
catch (IOException e) {
System.out.println("Nepodarilo se otevri soubor pro cteni");
e.printStackTrace(); }
Matice matice = null;
try { // Zkusime nacist hodnoty
String retezec = Soubor.readLine(); // nacteme prvni radek kde je pouze velikost matice
velikost = Integer.valueOf(retezec).intValue(); // prevedem velikost na integer
matice = new Matice(velikost);
for(int i=0;i<velikost;i++) { // nacitani hodnot do matice z klavesnice
retezec = Soubor.readLine(); // nacteme do stringu cely radek
String [] podretezce = retezec.split(" "); // vytvorime pole hodnot
for(int j=0;j<velikost;j++) {
matice.set(i,j, Integer.valueOf(podretezce[j]).intValue()); } } } // Prevedeme jednotlive prvky pole stringu na integer do jednotlivych casti poli
catch (Exception e) {System.out.println("Nepodarilo se provest zapis matice"); }
try { // Zkusime uzavrit pripojeni k souboru
CteciSoubor.close();
Soubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } // uzavreme soubor
return matice; }
@SuppressWarnings("unused")
private void tiskMatice(Matice matice) {
System.out.println("Zde je vypsana matice");
for (int i = 0; i < matice.velikost; i++) {
for (int j = 0; j < matice.velikost; j++) {
System.out.format("%d ", matice.get(i,j)); }
System.out.println(); } }
private Matice nasobeniMatic(Matice maticeA,Matice maticeB) {
Matice maticeNasob=new Matice(maticeA.velikost); // u vysledne matice rozhoduji sloupce a pak radky
for(int i=0;i<maticeNasob.velikost;i++) { // cyklus pro nasobeni matic
for(int j=0;j<maticeNasob.velikost;j++) {
int val = 0;
for(int k=0;k<maticeNasob.velikost;k++) {
val+= maticeA.get(i,k) * maticeB.get(k,j); }
maticeNasob.set(i,j, val);
} }
return maticeNasob; }
private void ulozeniMatice(String s, Matice matice) {
File NazevSoub = new File(s);
FileWriter ZapisovaciSoubor = null;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
try {
ZapisovaciSoubor = new FileWriter(NazevSoub); }
catch (IOException e) {
System.out.println("Nepodarilo se vytvorit soubor ");
e.printStackTrace(); }
try {
ZapisovaciSoubor.write(matice.velikost+radek);
for(int i=0;i<matice.velikost;i++) { // nacitani hodnot do matice z klavesnice
for(int j=0;j<matice.velikost;j++) {
ZapisovaciSoubor.write(matice.get(i,j)+" "); }
ZapisovaciSoubor.write(radek); } }
catch (Exception e) {System.out.println("Nepodarilo se provest zapis matice"); }
try {
ZapisovaciSoubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } } // uzavreme soubor
@SuppressWarnings("unused")
public static void main(String [] args) {
B06_NasobeniMaticInt objekt = new B06_NasobeniMaticInt();
System.out.println("Program pro nasobeni matic integeru pro nacitani ze souboru");
String jmenoSouboru1,jmenoSouboru2,jmenoSouboru3;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
System.out.println("Vlozte prosim jmeno souboru ze ktereho chcete nacit matici cislo 1");
while(true) { // nekonecna smycka
try {
jmenoSouboru1 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
System.out.println("Vlozte prosim jmeno souboru ze ktereho chcete nacit matici cislo 2");
while(true) { // nekonecna smycka
try {
jmenoSouboru2 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
System.out.println("Provedem nacteni matice do pole :");
Matice MaticeA,MaticeB,MaticeZnasobena;
long nacteni1 = System.currentTimeMillis();
MaticeA = objekt.nacteniMatice(jmenoSouboru1);
//tiskMatice(MaticeA); // pro kontrolu
long nacteni2 = System.currentTimeMillis();
MaticeB = objekt.nacteniMatice(jmenoSouboru2);
long nactenikonec = System.currentTimeMillis();
System.out.println("Nacitani matice prvni :\t"+(nactenikonec-nacteni2)+" milisekund\nNacteni matice druhe :\t"+(nacteni2-nacteni1)+" milisekund");
long zacatekNasobeni = System.currentTimeMillis();
MaticeZnasobena = objekt.nasobeniMatic(MaticeA,MaticeB);
long konecNasobeni = System.currentTimeMillis();
System.out.println("Nasobeni matic trvalo :\t"+(konecNasobeni-zacatekNasobeni)+" milisekund\nVelikost Matice :"+MaticeZnasobena.velikost);
//tiskMatice(MaticeZnasobena); // pro kontrolu
System.out.println("Vlozte prosim jmeno souboru do ktereho chcete ulozit vyslednou matici");
while(true) { // nekonecna smycka
try {
jmenoSouboru3 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
long ulozeni1 = System.currentTimeMillis();
objekt.ulozeniMatice(jmenoSouboru3,MaticeZnasobena);
long ulozeni2 = System.currentTimeMillis();
System.out.println("Ulozeni matice trvalo :\t"+(ulozeni2-ulozeni1)); }
}
-
Tak začneme : program který vygeneruje soubor obsahujici matici nahodných cisel
:
:
V Javě na rozdíl od C měříte i alokaci výsledné matice což je celkem drahá operace (Java do všech prvků dává default hodnotu, v tomto případě nulu). Dál ve smyčkách vždycky znovu alokujete řídící proměnnou, to by ale mělo být hodně levné. Docela levné by mohlo být i to že si na rozdíl od C nevytahujete hodnotu pro ukončení cyklu do extra proměnné. Nejpodstatnější ale bude že Java je optimalizovaná na dlouhotrvající procesy, takže měřit takovou jednorázovost může být zavádějící protože nezafunguje dobře JIT kompilace. Zkuste přidat další smyčku která bude to násobení opakovat vícekrát a pokud jsem to tipnul správně tak byste měl vidět že první násobení matic bude nejpomalejší a jen co zabere JIT kompilace tak se to zrychlí, ideálně na rychlost toho C.
-
Já se asi picnu. Proč mají největší touhu porovnávat rychlost jazyků lidé, kteří je ani neumí naplno využít? Tohle je už druhé porovnávání rychlosti jazyků, které od základu využívá pitomé datové struktury. Ne, matice MxN se NEREPREZENTUJE M poli o N prvcích, ale jedním polem MxN prvků. Z M+1 alokací paměti je najednou jen 1 a přístup k prvku potřebuje o jeden přístup do paměti míň (o jeden potenciální výpadek cache nebo stránky míň). :o
Dynamické pole dynamických polí se hodí pro něco, kde se od začátku počítá s různou délkou těch menších polí. Pokud ty pole budou stejné, tak to úplně zbytečně obecná struktura. Výsledek bude pomalejší a navíc i složitější. V takhle pitomém srovnání budou navíc od začátku znevýhodněné jazyky, které kontrolují meze polí.
-
A ještě jedna věc. Násobení velkých matic tímhle primitivním způsobem bude pomalé už z principu. Druhou matici opakovaně procházíte po sloupcích. Kdyžtak tu druhou matici aspoň transponujte ať se k oběma přistupuje sekvenčně. Takhle je všechno schované za výpadky cache u druhé matice.
-
Fakt se rád poučím od lidí, kteří se tomu věnují mnohem,mnohem déle. Většinou je to tu plné blbých hospodských keců (typu :Kaufland je nejlevnější, pivo je zdravé atd..) všechno velmi obecné bez konkrétních důkazů. Zatím je závěr pro mě takový že na matematické výpočty je stále Java zásadně pomalejší.
Uz volba nesmyslne datove struktury ukazuje, ze o jave na nizke urovni skoro nic nevis. Co te tedy vede k tomu, abys provadel nejaka srovnani? Jedine co tvuj experiment dokazuje je, ze neumis programovat v jave - co my s tim?
-
A ještě jedna věc. Násobení velkých matic tímhle primitivním způsobem bude pomalé už z principu. Druhou matici opakovaně procházíte po sloupcích. Kdyžtak tu druhou matici aspoň transponujte ať se k oběma přistupuje sekvenčně. Takhle je všechno schované za výpadky cache u druhé matice.
Jo, tím se to (pro matici 2000x2000) stáhne na 5s, což je 18x rychlejší, než ta původní implementace.
-
Ještě tu nezazněla jedna věc. Při násobení matic jsou jednotlivé prvky výsledné matice na sobě nezávislé, je to tedy ideální kandidát na paralelizaci – když máte dost jader, může jednu buňku matice počítat jedno jádro. Pak je možné řešit takové optimalizace, aby jednotlivá vlákna výpočtu s výhodou používala data načtená jiným vláknem.
-
Ještě tu nezazněla jedna věc. Při násobení matic jsou jednotlivé prvky výsledné matice na sobě nezávislé, je to tedy ideální kandidát na paralelizaci – když máte dost jader, může jednu buňku matice počítat jedno jádro. Pak je možné řešit takové optimalizace, aby jednotlivá vlákna výpočtu s výhodou používala data načtená jiným vláknem.
Např. dnešní překladače Fortranu tohleto udělají za vás samy.
-
A ještě jedna věc. Násobení velkých matic tímhle primitivním způsobem bude pomalé už z principu. Druhou matici opakovaně procházíte po sloupcích. Kdyžtak tu druhou matici aspoň transponujte ať se k oběma přistupuje sekvenčně. Takhle je všechno schované za výpadky cache u druhé matice.
Správná poznámka, zvláště pro matice velkého rozměru.
Jen tak pro pošťouchnutí: násobení matic n x n uvedeným naivním algoritmem má časovou náročnost O(n^3). Existují však poněkud sofistikovanější algoritmy s náročností klesající k O(n^2.38). Pro matice 20000 x 20000 to teoreticky (samozřejmě se to v reálu bude brzdit někde jinde) znamená zrychlení téměř 400násobné...
-
Jen tak pro pošťouchnutí: násobení matic n x n uvedeným naivním algoritmem má časovou náročnost O(n^3). Existují však poněkud sofistikovanější algoritmy s náročností klesající k O(n^2.38). Pro matice 20000 x 20000 to teoreticky (samozřejmě se to v reálu bude brzdit někde jinde) znamená zrychlení téměř 400násobné...
Jen tak pro pošťouchnutí: Asymptotickou složitost nemůžeš takto přímo porovnávat, pokud má něco složitost 1000*n^2.38, tak je to pořád O(n^2.38), ale pro matice 20000x20000 to nebude rychlejší, než něco se složitostí n^3.
-
Takže jsme pořád na úrovni hospodských keců? :'(
Och já naivka si myslel že tu někdo konečně předvede důkaz, a zase big shit. Se nedivme, že to tu tak vypadá, to je skoro jako práce na dálnici. Jeden maká a 5 lopat mudruje o ničem .....
viz. Talk is cheap, show me the code ;-).
-
Jsi pěkný kus diskuze přehlédl, ne?
-
Jirsáku, furt křičíš že chceš důkaz. To to nevidíš? Důkazy máš všude kolem sebe. Pro příklad Android. Vnitřně linux s klíčovými knihovnami napsanými v C. Na povrchu číhá Java jež běží pod Dalvikem. Nemusím ani říkat že Android vykazuje abnormální žravost oproti konkurenci, takže potřebuje X jader k rozumnému chodu. Ty však jako zažraný Javista odpovíš: Nedal jsi důkaz ... Uvědom si, že vlastním odmítnutím stavu věcí, stav věcí nezměníš. Pouze budeš mít dobrý pocit xD
-
Och já naivka si myslel že tu někdo konečně předvede důkaz
Nezapomněl jste napsat, důkaz čeho očekáváte? Důkaz, že neefektivní kód lze napsat v jakémkoli jazyce, jste podal vy sám. Jaký chcete další?
Důkazy máš všude kolem sebe. Pro příklad Android.
Tvrzení s velkým kvantifikátorem nelze dokázat příkladem. OpenOffice nebo Firefox také nedokazují, že C++ je pomalé.
-
Jirsáku, furt křičíš že chceš důkaz. To to nevidíš? Důkazy máš všude kolem sebe. Pro příklad Android. Vnitřně linux s klíčovými knihovnami napsanými v C. Na povrchu číhá Java jež běží pod Dalvikem. Nemusím ani říkat že Android vykazuje abnormální žravost oproti konkurenci, takže potřebuje X jader k rozumnému chodu. Ty však jako zažraný Javista odpovíš: Nedal jsi důkaz ... Uvědom si, že vlastním odmítnutím stavu věcí, stav věcí nezměníš. Pouze budeš mít dobrý pocit xD
Uvedomujes si vubec, ze vykon aplikace je VZDY zavisly na tom kdo ji psal? Je spousty aplikaci napsanych v C++, ktere jsou line jako prase. Nemuzes proste navysit vykon jen volbou jazyka, ale hlavne tim jak aplikaci napises. Je to uplne to same jako navysovat vykon pomoci lepsiho HW. Algoritmus je vzdy nejdulezitejsi. Jinak ja mam velmi rad C++, ale takhle hanit Javu je opravdu trapnost. Obzvlaste kdyz o tom opravdu nic nevis. Precti si nekdy clanky pana Tisnovskeho, abys aspon tusil jak hloupe se vyjadrujes.
-
raii, vy mate dobry pocit, ze dokola tvrdite "java sucks, lebo je pomala"?
a na rozumnejsiu notu, co rozumiete presne pod 'android vykazuje abnormalni zravost oproti konkurenci'?
mate nejake exaktne data, ze android na analogickom hardveri bezi rychlejsie nez windows phone alebo ios? alebo mate ine exaktne data, ktore dokazuju zravost? (a dufam, ze nevyleziete s tvrdenim, ze baterka na nokii 3310 vydrzi 7 dni a na androide jeden).
a opat, ako som sa pytal vyssie: who cares? (okrem verklika "java je pomala, c++ rulezz")
vasou logikou by sme mohli ist donekonecna: windowsy napisane v c++ tiez ziadne terno a linux v cistom c tiez ziadna velka slava, trollity troll.
-
to perceptron: zkušenosti ... myslím že sekající se aplikace, jež by na to neměli nárok mluví za vše (zkuste rozběhnout androida 4 na 512 MB RAM ... bude to stát za starou belu)...Je pravda že novější verze to výrazně zlepšili, ale furt je to špatný (a jiné aplikace na marketu tímto trpí furt). Jako poměr lze třeba vzít IOS. Mnohem lépe využívá výkon zařízení. A Who cares? Ano, je to tak. Nebudete věřit, ale nepřišel jsem sem s cílem všechny přesvědčit aby se vysrali na Javu a šli do C++, do této dlouhé a bohužel zbytečné diskuze jsem byl zatažen poté, co jsem tvrdil že optimalizovat v Javě bitovými operacemi je zbytečná práce, neb je nenažraná, takže jakákoli takto drobná optimalizace se ztratí. Bohužel, někteří vytáhli do holi war, a já nemohl zůstat pozadu xD
-
"ios mnohem lepe vyuziva vykon zarizeni", lebo a) apple ma de facto tri zariadenia a nie tritisic, ergo moze optimalizovat prave tak ako to robia na hernych konzolach b) ich zariadenia su high-endove, teda trochu inde, nez vami argumentovane 512mbove zariadenie, ktore sa dnes predava za 50 eur v bazari
to vas argument opat mozeme poslat do roviny "zkuste rozbehnout windows 7 na 512MB ram, bude to stat za starou belu, ergo c++ suxalot"
"jine aplikace tim trpi furt", lebo su mnohokrat zle napisane. napr. pisu asi tak efektivne, ako hore uvedeny kod pre pracu s maticami a podobne. alebo, aby som nekydal, v androide 4.x sa zmenilo pre pracu s databazami, kde sa data neloaduju v hlavnom vlakne, akurat nie kazdy vyvojar na to prisiel.
ja stale netusim, co ine chcete oznamit svetu, len nez java je pomala; nepoviete v porovnani s cim; a ak poviete, tak vase porovnavane veci su z ineho sveta
pointa tejto debaty je v tom, ze na houby budete robit wtf mikrooptimalizacie, ked vas kod algoritmicky smrdi na kilometer a vase znalosti jazyka a platformy su biedne, pripadne na urovni bulvarneho dennika
-
...novější verze to výrazně zlepšili...
Když už chceš psát měkké Y, tak aspoň takhle: "novější verzové to výrazně zlepšili".
Podle některých výroků je vidět, že jsi úplně mimo mísu, tak se nediv, že lidé nevěří věcem, které předkládáš jako fakt bez rozumného zdůvodnění.
Takovíhle hraní si s bitama je třeba pouze u low level vývoje (nastavování příznaků v registrech a tak podobně).
Například ukazuje na malou fantazii a zkušenosti. Velká část ne low level programů, které jsem psal, vyžadovala bitové operace (např. výpočet CRC pro kontrolu dat). A tvrdit člověku, kterému vyřešení domácího úkolu může přinést body navíc, že je Java pomalá, to je taky výrok hodný zápisu na pamětní listinu.
Páni, dneska jsem nějak zlej a agrsivní, radši půjdu spát, dobrou
-
Je pravda že novější verze to výrazně zlepšili
Chcete tím říct, že starší verze byly napsané v Javě a novější ne? Nebo jinak, existuje nějaký výklad tohoto tvrzení, který by vaše tvrzení "Java je pomalá" nevyvracel (ve smyslu, že je nepravdivé, nikoli ve smyslu, že je pravdivý opak), ale podporoval?
jsem tvrdil že optimalizovat v Javě bitovými operacemi je zbytečná práce
Bitové operace se nepoužívají jen k optimalizacím. Jakákoli optimalizace není zbytečná práce právě tehdy, pokud vím, že jí zlepším úzké místo v aplikaci. Na ničem jiném to nezáleží.
-
Nebudete věřit, ale nepřišel jsem sem s cílem všechny přesvědčit aby se vysrali na Javu a šli do C++, do této dlouhé a bohužel zbytečné diskuze jsem byl zatažen poté, co jsem tvrdil že optimalizovat v Javě bitovými operacemi je zbytečná práce, neb je nenažraná, takže jakákoli takto drobná optimalizace se ztratí.
Optimalizace objemu zabrané paměti pomocí bitových operací zcela jistě není zbytečná práce (je docela rozdíl zda program potřebuje 1GB nebo 8GB, zvlášť patrné je to na 32bit architektuře).
-
Jsi pěkný kus diskuze přehlédl, ne?
Za prvé nejsem zaměstnanecká lopata, mám vlastní firmu tak se musím starat. Nemám čas být každých 10 sekund na internetu a číst si kecy úrovně hospodských žvástů asi potomků těchto hospodských povalečů. A ani nechci.
Za druhé, kecy jenom prolítávám jak jsem říkal chci důkaz a to znamená zdroják který si vložím do Eclipse a spustím a poběží na stejném kusu HW rychleji než v Cčku. Já jsem ty porovnávací zdroje svého tvrzení předvedl. Od oponentů očekávám totéž.
Za třetí evidetně jsem zklamán. Od lidí co se tu skoro prezentují jako Java senioři bych očekával krom mudrování i výsledky.( možná to je ten rozdíl mezi podnikatelským myšlením[orientovaným na praktické výsledky] a lidmi kteří jsou asi geneticky předurčeni k lopatě )
Za čtvrté Java mě baví, velmi hezky se mi v tom programuje oproti Pascalu který jsem měl na vysoké skoro před 15 lety a rozsahem JDK nemá naprosto konkurenci ale zatím to prostě vypadá že tento typ problémů konkurenceschopně prostě nedává.( někdo z nás chápe k čemu se ty matice používají např. FEM)
Za páté pokud zde tvz. "Java profíci" mají nějaké tvrzení v obecné rovině a nejsou schopni si jej obhájit na lokálním problému tak sorry ale nejste profíci pořád jste děti co si na něco hrajou. Prosil bych, příště si vaše tvrzení povídejte před zrcadlem, normální lidé na ně nejsou zvědavy.
ZÁVĚR: je to škoda, budu muset používat JNI pro řešení matematických problémů řešených v Javě. Po mnoha provedených pokusech má jenom cca průměrné 5% zpomalení oproti Cčku.
PS. pokud se někoho z vás moje přirovnání dotklo tak se neomlouvám, bylo to tak myšleno.
-
Sorry spletl jsem si NICK. Ten předchozí příspěvek byl od mě.
-
Sorry spletl jsem si NICK.
Za druhé, kecy jenom prolítávám jak jsem říkal chci důkaz a to znamená zdroják který si vložím do Eclipse a spustím a poběží na stejném kusu HW rychleji než v Cčku. Já jsem ty porovnávací zdroje svého tvrzení předvedl. Od oponentů očekávám totéž.
Ty jsi tu snad nějaký zdroják dodal? Anebo je krom xxx také NotBeginner tvůj nick?
Za třetí evidetně jsem zklamán. Od lidí co se tu skoro prezentují jako Java senioři bych očekával krom mudrování i výsledky.( možná to je ten rozdíl mezi podnikatelským myšlením[orientovaným na praktické výsledky] a lidmi kteří jsou asi geneticky předurčeni k lopatě )
Já jsem zase zklamán, že Pavel Tišnovský se ti nabídl, že se ti na to podívá, a tys mu ani neodpověděl (pokud nejsi NotBeginner).
-
Tak začneme : [...]
Zde je zdrojak v Cčku, který je schopen načíst námi vygenerovaný soubor
[...]
A zde je ten naprosto identický kód v Javě
[...]
Tak jsem se na to podíval ještě jednou, opět jsem použil matici 2000x2000. Verze psaná v C/gcc na to potřebovala cca 64 sekund. Ta verze v Javě na to potřebovala 88 sekund. Mnou upravená verze (jedno pole, transpozice před násobením) v Javě to zvládla za 5 sekund. A aby to bylo vtipnější, tak C verze přeložená icc to zvládne za 0.85 sekund.
-
A tady je ten upravený kód:
import java.io.*;
import java.util.*;
public class B06_NasobeniMaticInt {
class Matice {
final int [] matice;
final int velikost;
public Matice(int v) {
velikost = v;
matice = new int[velikost*velikost];
}
final public int get(int i, int j) {
return matice[i*velikost+j];
}
final public void set(int i, int j, int v) {
matice[i*velikost+j] = v;
}
final public void trans() {
for(int i = 0; i < velikost; i ++)
for(int j = 0; j < i; j ++) {
int val = matice[i*velikost+j];
matice[i*velikost+j] = matice[j*velikost+i];
matice[j*velikost+i] = val;
}
}
}
@SuppressWarnings("resource")
private String nacteniNazvu() {
Scanner key = new Scanner(System.in);
System.out.print("Vlozte Nazev souboru :");
String jmeno = key.nextLine();
return jmeno; }
private Matice nacteniMatice(String s) {
File NazevSoub = new File(s);
FileReader CteciSoubor=null;
BufferedReader Soubor=null;
int velikost;
try { //Zkousime otevrit pripojeni k souboru
CteciSoubor = new FileReader(NazevSoub);
Soubor = new BufferedReader(CteciSoubor); }
catch (IOException e) {
System.out.println("Nepodarilo se otevri soubor pro cteni");
e.printStackTrace(); }
Matice matice = null;
try { // Zkusime nacist hodnoty
String retezec = Soubor.readLine(); // nacteme prvni radek kde je pouze velikost matice
velikost = Integer.valueOf(retezec).intValue(); // prevedem velikost na integer
matice = new Matice(velikost);
for(int i=0;i<velikost;i++) { // nacitani hodnot do matice z klavesnice
retezec = Soubor.readLine(); // nacteme do stringu cely radek
String [] podretezce = retezec.split(" "); // vytvorime pole hodnot
for(int j=0;j<velikost;j++) {
matice.set(i,j, Integer.valueOf(podretezce[j]).intValue()); } } } // Prevedeme jednotlive prvky pole stringu na integer do jednotlivych casti poli
catch (Exception e) {System.out.println("Nepodarilo se provest zapis matice"); }
try { // Zkusime uzavrit pripojeni k souboru
CteciSoubor.close();
Soubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } // uzavreme soubor
return matice; }
@SuppressWarnings("unused")
private void tiskMatice(Matice matice) {
System.out.println("Zde je vypsana matice");
for (int i = 0; i < matice.velikost; i++) {
for (int j = 0; j < matice.velikost; j++) {
System.out.format("%d ", matice.get(i,j)); }
System.out.println(); } }
private Matice nasobeniMatic(Matice maticeA,Matice maticeB) {
maticeB.trans();
Matice maticeNasob=new Matice(maticeA.velikost); // u vysledne matice rozhoduji sloupce a pak radky
for(int i=0;i<maticeNasob.velikost;i++) { // cyklus pro nasobeni matic
for(int j=0;j<maticeNasob.velikost;j++) {
int val = 0;
for(int k=0;k<maticeNasob.velikost;k++) {
val+= maticeA.get(i,k) * maticeB.get(j,k); }
maticeNasob.set(i,j, val);
} }
return maticeNasob; }
private void ulozeniMatice(String s, Matice matice) {
File NazevSoub = new File(s);
FileWriter ZapisovaciSoubor = null;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
try {
ZapisovaciSoubor = new FileWriter(NazevSoub); }
catch (IOException e) {
System.out.println("Nepodarilo se vytvorit soubor ");
e.printStackTrace(); }
try {
ZapisovaciSoubor.write(matice.velikost+radek);
for(int i=0;i<matice.velikost;i++) { // nacitani hodnot do matice z klavesnice
for(int j=0;j<matice.velikost;j++) {
ZapisovaciSoubor.write(matice.get(i,j)+" "); }
ZapisovaciSoubor.write(radek); } }
catch (Exception e) {System.out.println("Nepodarilo se provest zapis matice"); }
try {
ZapisovaciSoubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } } // uzavreme soubor
@SuppressWarnings("unused")
public static void main(String [] args) {
B06_NasobeniMaticInt objekt = new B06_NasobeniMaticInt();
System.out.println("Program pro nasobeni matic integeru pro nacitani ze souboru");
String jmenoSouboru1,jmenoSouboru2,jmenoSouboru3;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
System.out.println("Vlozte prosim jmeno souboru ze ktereho chcete nacit matici cislo 1");
while(true) { // nekonecna smycka
try {
jmenoSouboru1 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
System.out.println("Vlozte prosim jmeno souboru ze ktereho chcete nacit matici cislo 2");
while(true) { // nekonecna smycka
try {
jmenoSouboru2 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
System.out.println("Provedem nacteni matice do pole :");
Matice MaticeA,MaticeB,MaticeZnasobena;
long nacteni1 = System.currentTimeMillis();
MaticeA = objekt.nacteniMatice(jmenoSouboru1);
//tiskMatice(MaticeA); // pro kontrolu
long nacteni2 = System.currentTimeMillis();
MaticeB = objekt.nacteniMatice(jmenoSouboru2);
long nactenikonec = System.currentTimeMillis();
System.out.println("Nacitani matice prvni :\t"+(nactenikonec-nacteni2)+" milisekund\nNacteni matice druhe :\t"+(nacteni2-nacteni1)+" milisekund");
long zacatekNasobeni = System.currentTimeMillis();
MaticeZnasobena = objekt.nasobeniMatic(MaticeA,MaticeB);
long konecNasobeni = System.currentTimeMillis();
System.out.println("Nasobeni matic trvalo :\t"+(konecNasobeni-zacatekNasobeni)+" milisekund\nVelikost Matice :"+MaticeZnasobena.velikost);
//tiskMatice(MaticeZnasobena); // pro kontrolu
System.out.println("Vlozte prosim jmeno souboru do ktereho chcete ulozit vyslednou matici");
while(true) { // nekonecna smycka
try {
jmenoSouboru3 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) { System.err.print("Nejedna se o retezec");} }
long ulozeni1 = System.currentTimeMillis();
objekt.ulozeniMatice(jmenoSouboru3,MaticeZnasobena);
long ulozeni2 = System.currentTimeMillis();
System.out.println("Ulozeni matice trvalo :\t"+(ulozeni2-ulozeni1)); }
}
-
Za druhé, kecy jenom prolítávám jak jsem říkal chci důkaz a to znamená zdroják který si vložím do Eclipse a spustím a poběží na stejném kusu HW rychleji než v Cčku.
A to bude důkaz čeho? Tvrzení, které tady nikdo nezmínil a nikdo neobhajuje?
Já jsem ty porovnávací zdroje svého tvrzení předvedl. Od oponentů očekávám totéž.
Nepředvedl. Předvedl jste jeden příklad. To jako důkaz všeobecného tvrzení nestačí.
To, co jste předvedl, je spíš názorná ilustrace toho, že špatně lze psát v libovolném jazyce. A že rozdíly mezi špatně a dobře napsaným programem jsou nesrovnatelně větší, než rozdíly plynoucí z použitých nástrojů. Jediný případ, kdy nástroje mohou ten rozdíl srovnat, je tehdy, pokud dokážou ten špatně napsaný program opravit (při optimalizaci).
Tak jsem se na to podíval ještě jednou, opět jsem použil matici 2000x2000. Verze psaná v C/gcc na to potřebovala cca 64 sekund. Ta verze v Javě na to potřebovala 88 sekund. Mnou upravená verze (jedno pole, transpozice před násobením) v Javě to zvládla za 5 sekund. A aby to bylo vtipnější, tak C verze přeložená icc to zvládne za 0.85 sekund.
Verze přeložená s icc byla ta samá, jako s gcc? Tedy ta s dvourozměrným polem a bez transpozice? To by mne tedy zajímaly ty instrukce, co z icc vylezly. To snad muselo provést tu transformaci i transpozici matice také a použít pak vektorové instrukce.
-
Verze přeložená s icc byla ta samá, jako s gcc? Tedy ta s dvourozměrným polem a bez transpozice?
Jo, naprosto ta samá.
To by mne tedy zajímaly ty instrukce, co z icc vylezly.
Těch pět řádků v C, co provádí samotné násobení, to rozvinulo na cca 1100 řádků v assembleru :).
-
Těch pět řádků v C, co provádí samotné násobení, to rozvinulo na cca 1100 řádků v assembleru :).
Aha, takže asi optimalizace způsobem: "Á, násobení matic, a pěkně naivně implementované. Tak proto máme v knihovně daleko lepší algoritmus."
-
Aha, takže asi optimalizace způsobem: "Á, násobení matic, a pěkně naivně implementované. Tak proto máme v knihovně daleko lepší algoritmus."
Spíše jen důsledek loops unrollingu.
-
Za druhé, kecy jenom prolítávám jak jsem říkal chci důkaz a to znamená zdroják který si vložím do Eclipse a spustím a poběží na stejném kusu HW rychleji než v Cčku. Já jsem ty porovnávací zdroje svého tvrzení předvedl. Od oponentů očekávám totéž.
Za třetí evidetně jsem zklamán. Od lidí co se tu skoro prezentují jako Java senioři bych očekával krom mudrování i výsledky.( možná to je ten rozdíl mezi podnikatelským myšlením[orientovaným na praktické výsledky] a lidmi kteří jsou asi geneticky předurčeni k lopatě )
Mimochodem, já tu zdroják vložil (tehdy ještě bez transpozice), dokonce takový, co u mne běží rychleji než tvá verze v C (pokud se použije gcc). Ale pan podnikatel ji asi jaksi přehlédl.
-
Schválně - kolik z vás také napadlo "co dělá Hulán na rootu"?
-
Doufám že si spokojenej Jirsáku, důkaz o tom že Java je pomalá si dostal. Neříkám že je špatná, má své výhody, ale je hold pomalá...
-
public class RAII {
public static void main(String[] args) {
while(true) {
System.out.println("Java je pomala");
}
}
Debata o androide uz tiez bola vycerpana, argumenty zasiahli nerelevantne tvrdenia, tak sa prispevky resetli? generalizacia "java nebezi na maticovom benchmarku rychlejsie nez c (sic!), ergo je pomala"?
srsly? :-)
pan technomaniak, https://gist.github.com/anonymous/9569105
to je ten kod co ide oproti epml, a bezi radovo rychlejsie nez vasa uplne prva verzia.
-
důkaz o tom že Java je pomalá si dostal.
Nedostal. Všeobecné tvrzení nelze dokázat příkladem. Což už píšu potřetí - přesto to, že jste to dvakrát nepochopil, není důkazem toho, že nechápete vůbec nic.
Mimochodem, varianta napsaná v C běžela 64 sekund, varianta v Javě 5 sekund. OK, můžete tvrdit, že Java je pomalá, ale pak je C superpomalé.
Ve skutečnosti se ukázalo, že zvolený jazyk má na rychlost nepatrný vliv. Nesrovnatelně větší vliv má zvolený algoritmus a odstranění úzkých hrdel při zpracování, která závisí na konkrétní implementaci. V tomhle případě se ukázalo, že je úzkým hrdlem dvojí dereferencování, které lze nahradit jedním, a hlavně zbytečné zahazování dat, která už jsou v cache procesoru. Třeba ta druhá optimalizace by před dvaceti lety byla na platformě x86 nesmyslná, protože procesor žádnou cache neměl.
Pro původního tazatele to znamená, ať se vykašle na nesmysly o tom, že je nějaký jazyk pomalý nebo rychlý, ať se naučí efektivně využívat možností platformy, ve které a pro kterou píše, a psát přehledný kód. A pak ať se naučí odhalovat ta místa programu, která jsou úzkým hrdlem, pochopit proč je dané místo problematické a pak program upravit. A také to mimochodem znamená, že i pro některé optimalizace v Javě, která je zdánlivě vysokoúrovňová, je potřeba znát, jak pracují dnešní procesory - že používají keš hlavní paměti, že používají predikci skoků, jak funguje přepínání mezi vlákny nebo mezi uživatelským prostorem a jádrem. Na druhou stranu tohle už jsou optimalizace, které se využijí jen v některých typech programů.
-
Pro původního tazatele to znamená, ...
Já myslím že pro původního tazatele je poučení zcela jiné: že by se měl vykašlat na programování a zvolit si jiný obor, kde bude kolem sebe mít lepší a hezčí společnost. Například zemělství....
-
Doufám že si spokojenej Jirsáku, důkaz o tom že Java je pomalá si dostal. Neříkám že je špatná, má své výhody, ale je hold pomalá...
ano, je pomala, preto je Hadoop vitazom sorting benchmarku :)
-
TO K77: hadoop ... (bylo by špatné kdyby nebyl vítězem...). Na druhou stranu, kdyby byl udělanej v C/C++, byl by ještě rychlejší.
TO JIRSÁK: No, je jedno co napíšeš. JAVA prostě pomalá je (U MAD ? xD). A ten tvůj test je nesmysl (C 60s a Java 5s?...ukaž kód na kterym si to měřil...ať se zasměju amatére).
-
Já jsem zase zklamán, že Pavel Tišnovský se ti nabídl, že se ti na to podívá, a tys mu ani neodpověděl (pokud nejsi NotBeginner).
jsem, technomaniak = NotBeginner = xxx ( různé NICKY ale stejná osoba)
Tak jsem se konečně k tomu dostal. I když reagovat na všechno se mi nechce.
Tvůj zdroják jsem přehledl, moje chyba. I já umím uznat když provedu omyl. Ještě jsem jej nezkoušel a vyzkouším. Nicméně matice 2000x2000 nejsou zase tam velké. Zkus si vyzkoušet větší např. 10000,15000. V každém případě ten tvůj zdroj vyzkouším. Zkusím to i v Cčku. V nějakém tvém příspěvku tvrdíš že v Cčku jsi upravený zdroj s matici 2000 krát 2000 pod sekundu? To chci vidět.
-
Kdybyste uměl číst, přikládali by ostatní vašim názorům větší váhu. Takhle se akorát sám ztrapňujete.
-
V nějakém tvém příspěvku tvrdíš že v Cčku jsi upravený zdroj s matici 2000 krát 2000 pod sekundu? To chci vidět.
Nebyl to upravený zdroják, použil jsem tvůj, jen jsem ho místo gcc přeložil icc (Intel C++ Compiler). Překládal jsem ho s volbami -O3 -march=native a pouštěl na Core i7 (3630QM).
-
TO K77: hadoop ... (bylo by špatné kdyby nebyl vítězem...). Na druhou stranu, kdyby byl udělanej v C/C++, byl by ještě rychlejší.
uz som si myslel, ze budete mat prispevok bez vasej mantry "java je pomala", ktory, aspon to tak vyzera, dodava privatnu spokojnost na dalsi tyzden
jasne, a windows aj linux napisany komplet v asembleri by bol tiez rychlejsi
akurat, ze ocividne na to nie je dovod.
pokojne si mozete prepisat hadoop do c++ (kod inak vyzera rozkosne), ale nezabudnite na to, ze aj tie distribuovane tasky musite v niecom pisat, a medzi nodmi deliverovat. viete o nejakom inom map/reduce frameworku, co je napisany v c/++ a pouziva sa? nasiel som len sector/sphere, s poslednym releasom z 2011, hm.
alebo vase argumenty citate z /dev/troll ako v pripade androidu?
-
Gratuluji, tak tomu se mi nechce věřit. Převedení matice na objekt s parametrem pole sice zvýšilo nároky na RAM(10-15%) ale skutečně značně urychlilo výpočet(doba klesla zhruba na 1/4 času). Dokonce takovým způsobem že jsem si to pro jistotu převedl i do Cčka. ( viz. přiložený zdroj, zkompilované MinGW, zkoušel jsem to na matici 5000x5000). A nepředstavitelné se stalo reálným. Java to prostě zvládla o cca 25-30% rychleji. (PentiumD,Win8-64bit,pořád řeším jenom tu matematiku, to násobení, všechno ostatní neřeším). Pro jistotu jsem to nechal spočítat dvakrát za sebou, protože se mi tomu prostě nechce věřit.
Smekám, konečně někdo kdo nemá plnou hubu keců a má i důkaz.
Závěr: nepaušalizuji, nezobecňuji ale v tomto konkrétním případě Java předběhla Cčko a docela nezanedbatelně, špíše docela drasticky Škoda že neumí Fortran, bylo by fajn srovnat Javu s Fortranem.
C source :
#include<stdio.h>
#include<time.h>
main(){
clock_t startCteni1,konecCteni1,startCteni2,konecCteni2,startNasob,konecNasob,startZapis,konecZapis;
printf("Program na vypocet nasobeni matic - neresime jako matici nybrz jako pole\n");
char nazevSouboru1 [15];
printf("Vlozte jmeno souboru pro matici 1 :");
scanf("%15s",nazevSouboru1); // pozor cteme pouze prvnich 15 znaku --- %15s
char nazevSouboru2 [15];
printf("Vlozte jmeno souboru pro matici 2 :");
scanf("%15s",nazevSouboru2); // pozor cteme pouze prvnich 15 znaku --- %15s
FILE *fr1,*fr2;
fr1 = fopen(nazevSouboru1,"r"); // nacteme soubor 1
int velikost1,velikost2;
fscanf(fr1,"%i",&velikost1); // nacteme velikost matice
printf("Zde je prvni cislo prvni matice : %i\n",velikost1);
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) POLE1 **/
int i;
int *poleA;
poleA=(int*)malloc(velikost1*velikost1*sizeof(int));
/*** Naplnime pole z nacteneho souboru ***/
printf("Nacitame matici 1 a prevedeme do pole \n");
startCteni1=clock();
for(i=0;i<(velikost1*velikost1);i++) {
fscanf(fr1,"%i",&poleA[i]); }
konecCteni1=clock();
printf("Nacitani prvni matice trvalo %6.2f sec\n",(konecCteni1-startCteni1)/(double) CLOCKS_PER_SEC);
/*printf("Zde je nactene PoleA\n");
for(i=0;i<(velikost1*velikost1);i++) {
printf("%i \n",poleA[i]); }*/
fclose(fr1);
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) POLE2 **/
fr2 = fopen(nazevSouboru2,"r"); // nacteme soubor 2
fscanf(fr2,"%i",&velikost2);
printf("Zde je prvni cislo druhe matice: %i\n",velikost2);
int *poleB;
poleB=(int*)malloc(velikost1*velikost1*sizeof(int));
/*** Naplnime pole z nacteneho souboru ***/
printf("Nacitame matici 2 a prevedeme do pole \n");
startCteni2=clock();
for(i=0;i<(velikost2*velikost2);i++) {
fscanf(fr2,"%i",&poleB[i]); }
konecCteni2=clock();
printf("Nacitani druhe matice trvalo %6.2f sec\n",(konecCteni2-startCteni2)/(double) CLOCKS_PER_SEC);
/*printf("Zde je nactene Pole B\n");
for(i=0;i<(velikost2*velikost2);i++) {
printf("%i \n",poleB[i]); }*/
fclose(fr2);
/** Nutne je prevest matici na pole **/
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) MATICI C pointeru na pointer **/
printf("Provadime nasobeni matic \n");
int *poleC;
poleC=(int*)malloc(velikost1*velikost2*sizeof(int));
/************* Nasobime matici A x B = vznik matice C *******************/
startNasob=clock();
int j,k;
for(i=0;i<velikost1;i++) { // cyklus pro nasobeni matic
for(j=0;j<velikost2;j++) {
int hodnota = 0;
for(k=0;k<velikost1;k++) {
hodnota += poleA[i*velikost1+k] * poleB[k*velikost2+j]; }
poleC[i*velikost1+j]=hodnota; } }
konecNasob = clock();
printf("Doba nasobeni matice %6.2f sec\n",(konecNasob-startNasob)/(double) CLOCKS_PER_SEC);
/*printf("Zde je vypoctený vynasobeny vektor\n");
for(i=0;i<(velikost1*velikost1);i++) {
printf("%i \n",poleC[i]); }*/
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) MATICI A pointeru na pointer **/
int **maticeD;
maticeD=(int**)malloc(velikost1*sizeof(int*));
for(i=0;i<velikost1;i++) {
maticeD[i]=(int*)malloc(velikost1*sizeof(int)); }
/****************** Prevedeme pole do matice ***************************/
for(i=0;i<velikost1;i++) {
for(j=0;j<velikost1;j++){
maticeD[i][j]=poleC[velikost1*i+j]; } }
/*******************Vytiskneme matici **********************************/
/*printf("Zde je vypoctena matice\n");
for(i=0;i<velikost1;i++) {
for(j=0;j<velikost2;j++) {
printf("%i ",maticeD[i][j]); }
printf("\n"); }*/
/****************** Ulozime matici do Souboru ***************************/
free(poleA);poleA=NULL; // vymazeme hodnoty a referenci
free(poleB);poleB=NULL; // vymazeme hodnoty a referenci
char nazevSouboru3 [15];
printf("Vlozte jmeno souboru pro matici 3 (vyslednou):");
scanf("%15s",nazevSouboru3); // pozor cteme pouze prvnich 15 znaku --- %15s
FILE *fr3;
fr3 = fopen(nazevSouboru3,"w"); // nacteme soubor 1
fprintf(fr3,"%i\n",velikost1); // ulozime rad matice
startZapis =clock();
for(i=0;i<velikost2;i++) {
for(j=0;j<velikost2;j++) {
fprintf(fr3,"%i ",maticeD[i][j]); }
fprintf(fr3,"\n"); }
konecZapis = clock();
printf("Doba ukladani matice %6.2f sec\n",(konecZapis-startZapis)/(double) CLOCKS_PER_SEC);
fclose(fr3);
free(poleC);poleC=NULL; // vymazeme hodnoty a referenci
free(maticeD);maticeD=NULL; // vymazeme hodnoty a referenci
printf("Program ukoncite stiknutim libovolne klavesy");
getch(); // cekame na stiknuti klavesnice
}
Java source :
import java.io.*;
import java.util.*;
public class B06_NasobeniMaticIntUprav {
class Matice {
final int [] matice;
final int velikost;
public Matice(int v) {
velikost = v;
matice = new int[velikost*velikost]; }
final public int get(int i, int j) {
return matice[i*velikost+j]; }
final public void set(int i, int j, int v) {
matice[i*velikost+j] = v; }
}
private String nacteniNazvu() {
@SuppressWarnings("resource")
Scanner key = new Scanner(System.in);
System.out.print("Vlozte Nazev souboru :");
String jmeno = key.nextLine();
return jmeno; }
private Matice nacteniMatice(String s) {
File NazevSoub = new File(s);
FileReader CteciSoubor=null;
BufferedReader Soubor=null;
int velikost;
try { //Zkousime otevrit pripojeni k souboru
CteciSoubor = new FileReader(NazevSoub);
Soubor = new BufferedReader(CteciSoubor); }
catch (IOException e) {
System.out.println("Nepodarilo se otevri soubor pro cteni");
e.printStackTrace(); }
Matice matice = null;
try { // Zkusime nacist hodnoty
String retezec = Soubor.readLine(); // nacteme prvni radek kde je pouze velikost matice
velikost = Integer.valueOf(retezec).intValue(); // prevedem velikost na integer
matice = new Matice(velikost);
for(int i=0;i<velikost;i++) { // nacitani hodnot do matice z klavesnice
retezec = Soubor.readLine(); // nacteme do stringu cely radek
String [] podretezce = retezec.split(" "); // vytvorime pole hodnot
for(int j=0;j<velikost;j++) {
matice.set(i,j, Integer.valueOf(podretezce[j]).intValue()); } } } // Prevedeme jednotlive prvky pole stringu na integer do jednotlivych casti poli
catch (Exception e) {
System.out.println("Nepodarilo se provest zapis matice"); }
try { // Zkusime uzavrit pripojeni k souboru
CteciSoubor.close();
Soubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } // uzavreme soubor
return matice; }
@SuppressWarnings("unused")
private void tiskMatice(Matice matice) {
System.out.println("Zde je vypsana matice");
for (int i = 0; i < matice.velikost; i++) {
for (int j = 0; j < matice.velikost; j++) {
System.out.format("%d ", matice.get(i,j)); }
System.out.println(); } }
private Matice nasobeniMatic(Matice maticeA,Matice maticeB) {
Matice maticeNasob=new Matice(maticeA.velikost); // u vysledne matice rozhoduji sloupce a pak radky
for(int i=0;i<maticeNasob.velikost;i++) { // cyklus pro nasobeni matic
for(int j=0;j<maticeNasob.velikost;j++) {
int val = 0;
for(int k=0;k<maticeNasob.velikost;k++) {
val+= maticeA.get(i,k) * maticeB.get(k,j); }
System.out.println("Info :"+val);
maticeNasob.set(i,j, val); } }
return maticeNasob; }
private void ulozeniMatice(String s, Matice matice) {
File NazevSoub = new File(s);
FileWriter ZapisovaciSoubor = null;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
try {
ZapisovaciSoubor = new FileWriter(NazevSoub); }
catch (IOException e) {
System.out.println("Nepodarilo se vytvorit soubor ");
e.printStackTrace(); }
try {
ZapisovaciSoubor.write(matice.velikost+radek);
for(int i=0;i<matice.velikost;i++) { // nacitani hodnot do matice z klavesnice
for(int j=0;j<matice.velikost;j++) {
ZapisovaciSoubor.write(matice.get(i,j)+" "); }
ZapisovaciSoubor.write(radek); } }
catch (Exception e) {System.out.println("Nepodarilo se provest zapis matice"); }
try {
ZapisovaciSoubor.close(); }
catch (IOException e) {
System.out.println("Nepodarilo se ukoncit napojeni na soubor ");
e.printStackTrace(); } } // uzavreme soubor
@SuppressWarnings("unused")
public static void main(String [] args) {
B06_NasobeniMaticIntUprav objekt = new B06_NasobeniMaticIntUprav();
System.out.println("Program pro nasobeni matic integeru pro nacitani ze souboru");
String jmenoSouboru1,jmenoSouboru2,jmenoSouboru3;
String radek = System.getProperty("line.separator"); // do promene radek ulozime systemem definovany radek
System.out.println("Vlozte prosim jmeno souboru ze ktereho chcete nacit matici cislo 1");
while(true) { // nekonecna smycka
try {
jmenoSouboru1 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) {
System.err.print("Nejedna se o retezec");} }
System.out.println("Vlozte prosim jmeno souboru ze ktereho chcete nacit matici cislo 2");
while(true) { // nekonecna smycka
try {
jmenoSouboru2 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) {
System.err.print("Nejedna se o retezec");} }
System.out.println("Provedem nacteni matice do pole :");
Matice MaticeA,MaticeB,MaticeZnasobena;
long nacteni1 = System.currentTimeMillis();
MaticeA = objekt.nacteniMatice(jmenoSouboru1);
//tiskMatice(MaticeA); // pro kontrolu
long nacteni2 = System.currentTimeMillis();
MaticeB = objekt.nacteniMatice(jmenoSouboru2);
long nactenikonec = System.currentTimeMillis();
System.out.println("Nacitani matice prvni :\t"+(nactenikonec-nacteni2)+" milisekund\nNacteni matice druhe :\t"+(nacteni2-nacteni1)+" milisekund");
long zacatekNasobeni = System.currentTimeMillis();
MaticeZnasobena = objekt.nasobeniMatic(MaticeA,MaticeB);
long konecNasobeni = System.currentTimeMillis();
System.out.println("Nasobeni matic trvalo :\t"+(konecNasobeni-zacatekNasobeni)+" milisekund\nVelikost Matice :"+MaticeZnasobena.velikost);
//tiskMatice(MaticeZnasobena); // pro kontrolu
System.out.println("Vlozte prosim jmeno souboru do ktereho chcete ulozit vyslednou matici");
while(true) { // nekonecna smycka
try {
jmenoSouboru3 = objekt.nacteniNazvu(); break; }
catch(RuntimeException E) {
System.err.print("Nejedna se o retezec");} }
long ulozeni1 = System.currentTimeMillis();
objekt.ulozeniMatice(jmenoSouboru3,MaticeZnasobena);
long ulozeni2 = System.currentTimeMillis();
System.out.println("Ulozeni matice trvalo :\t"+(ulozeni2-ulozeni1)); }
}
-
Ten kód je v principu špatný. Tohle je největší problém:
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) MATICI A pointeru na pointer **/
int **maticeD;
maticeD=(int**)malloc(velikost1*sizeof(int*));
for(i=0;i<velikost1;i++) {
maticeD[i]=(int*)malloc(velikost1*sizeof(int)); }
Dělat matici jako pole poiterů je hrozný zabiják výkonu. Při přístupu k prvku se musí dereferencovat pointer, není to souvislý blok v paměti, takže fragmentace paměti hrozná, využití cache hrozné a ani ten kód potom nemůže překladač rozumně vektorizovat.
-
Převedení matice na objekt s parametrem pole sice zvýšilo nároky na RAM(10-15%) ale skutečně značně urychlilo výpočet(doba klesla zhruba na 1/4 času).
Zkus si kdyžtak ještě tu verzi s transpozicí, viz: http://forum.root.cz/index.php?topic=8589.msg89009#msg89009.
-
!!!!!!!
poleB=(int*)malloc(velikost1*velikost1*sizeof(int));
...
for(i=0;i<(velikost2*velikost2);i++) {
fscanf(fr2,"%i",&poleB);
...
-
Aha, cely to "funguje" (nasobi to stejne spatne, nekde tam je chyba) jen na shodne ctvercove matice.
Tohle mam o neco rychlejsi.
startNasob=clock();
int * A_old = poleA;
int * B_old = poleB;
int * A_new;
int * C_new = poleC;
int sloupec = velikost1;
while ( sloupec-- ) {
int radek = velikost1;
while ( radek-- ) {
A_new = A_old;
int hodnota = 0;
int * B_new = B_old;
int i = velikost1;
while ( i-- ) {
hodnota += *A_new++ * *B_new;
B_new += velikost1;
}
*C_new++ = hodnota;
}
A_old = A_new;
B_old++;
}
konecNasob = clock();
-
Pokud ta druha matice bude ve tvaru.
[ 1 2 3 ] [ A D G ] [ 1A+2D+3G, 1B+2E+3H, 1C+2F+3I ]
[ 4 5 6 ] * [ B E H ] = [ 4A+5D+6G, 4B+5E+6H, 4C+5F+6I ]
[ 7 8 9 ] [ C F I ] [ 7A+8D+9G, 7B+8E+9H, 7C+8F+9I ]
Tak to mam jeste 4x rychlejsi.
startNasob=clock();
int A_old = 0;
int B_new = 0;
int A_new;
int C_new = 0;
int radek = velikost1;
while ( radek-- ) {
B_new = 0;
int sloupec = velikost1;
while ( sloupec-- ) {
A_new = A_old;
int hodnota = 0;
int i = velikost1;
while ( i-- ) hodnota += poleA[A_new++] * poleB[B_new++];
poleC[C_new++] = hodnota;
}
A_old = A_new;
}
konecNasob = clock();
-
Tohle je ta asi 5x rychlejsi varianta od te puvodni. Osetreny varovne hlasky, pridana knihovna pro malloc a zruseno getch(). Odstranena maticeD a do poleB se rovnou nacita po sloupcich a ne po radcich. Obe matice musi byt ctvercove o shodne velikosti.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define VELIKOST 1000
// #define NACITANI
// #define VYPIS_MATIC
int main(){
clock_t startCteni1,konecCteni1,startCteni2,konecCteni2,startNasob,konecNasob,startZapis,konecZapis;
#ifdef NACITANI
printf("Program na vypocet nasobeni matic - neresime jako matici nybrz jako pole\n");
char nazevSouboru1 [15];
printf("Vlozte jmeno souboru pro matici 1 :");
if ( scanf("%15s",nazevSouboru1) <= 0 ) // pozor cteme pouze prvnich 15 znaku --- %15s
{
fprintf(stderr, "Spatny nazev souboru?\n" );
return -1;
}
char nazevSouboru2 [15];
printf("Vlozte jmeno souboru pro matici 2 :");
if ( scanf("%15s",nazevSouboru2) <= 0 ) // pozor cteme pouze prvnich 15 znaku --- %15s
{
fprintf(stderr, "Spatny nazev souboru?\n" );
return -1;
}
FILE *fr1,*fr2;
fr1 = fopen(nazevSouboru1,"r"); // nacteme soubor 1
#endif
int velikost1,velikost2;
#ifdef NACITANI
if ( fscanf(fr1,"%i",&velikost1) != 1 ) // nacteme velikost matice
{
fprintf(stderr, "Reading error.\n" );
return -1;
}
#else
velikost1 = VELIKOST;
#endif
printf("Zde je prvni cislo prvni matice : %i\n",velikost1);
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) POLE1 **/
int i,j,k;
int *poleA;
if ( ( poleA = (int *) malloc(velikost1*velikost1*sizeof(int))) == NULL ) {
fprintf(stderr, "No free memory.\n" );
return -1;
}
/*** Naplnime pole z nacteneho souboru ***/
printf("Nacitame matici 1 a prevedeme do pole \n");
startCteni1=clock();
for(i=0;i<(velikost1*velikost1);i++) {
#ifdef NACITANI
if ( fscanf(fr1,"%i",&poleA[i]) != 1 ) {
fprintf(stderr, "Nelze nacist cislo matice A.\n" );
return -1;
}
#else
poleA[i] = rand() & 0xffff;
#endif
}
konecCteni1=clock();
printf("Nacitani prvni matice trvalo %6.2f sec\n",(konecCteni1-startCteni1)/(double) CLOCKS_PER_SEC);
#ifdef VYPIS_MATIC
printf("Zde je nactene PoleA\n");
k = 0;
for(i=0;i<velikost1;i++) {
for(j=0;j<velikost1;j++) printf("%i \t",poleA[k++]);
printf("\n");
}
#endif
#ifdef NACITANI
fclose(fr1);
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) POLE2 **/
fr2 = fopen(nazevSouboru2,"r"); // nacteme soubor 2
if ( fscanf(fr2,"%i",&velikost2) != 1 ) {
fprintf(stderr, "Reading error.\n" );
return -1;
}
#else
velikost2 = VELIKOST;
#endif
printf("Zde je prvni cislo druhe matice: %i\n",velikost2);
int *poleB;
if ( (poleB=(int*)malloc(velikost2*velikost2*sizeof(int))) == NULL ) {
fprintf(stderr, "No free memory.\n" );
return -1;
}
/*** Naplnime pole z nacteneho souboru ***/
printf("Nacitame matici 2 a prevedeme do pole \n");
startCteni2=clock();
for(i=0;i<velikost2;i++) {
for(j=0,k=i;j<velikost2;j++,k+=velikost2) {
#ifdef NACITANI
if ( fscanf(fr2,"%i",&poleB[k]) != 1 ) {
fprintf(stderr, "Nelze nacist cislo matice B.\n" );
return -1;
}
#else
poleB[k] = rand() & 0xffff;
#endif
}
}
konecCteni2=clock();
printf("Nacitani druhe matice trvalo %6.2f sec\n",(konecCteni2-startCteni2)/(double) CLOCKS_PER_SEC);
#ifdef VYPIS_MATIC
printf("Zde je nactene PoleB\n");
k = 0;
for(i=0;i<velikost2;i++) {
for(j=0;j<velikost2;j++) printf("%i \t",poleB[k++]);
printf("\n");
}
#endif
#ifdef NACITANI
fclose(fr2);
#endif
/** Nutne je prevest matici na pole **/
/** DEKLARUJEME A INICIALIZUJEM(ALOKUJEME) MATICI C pointeru na pointer **/
printf("Provadime nasobeni matic \n");
int *poleC;
if ( (poleC=(int*)malloc(velikost1*velikost2*sizeof(int))) == NULL ) {
fprintf(stderr, "No free memory.\n" );
return -1;
}
/************* Nasobime matici A x B = vznik matice C *******************/
startNasob=clock();
int A_old = 0;
int B_new = 0;
int A_new;
int C_new = 0;
int radek = velikost1;
while ( radek-- ) {
B_new = 0;
int sloupec = velikost1;
while ( sloupec-- ) {
A_new = A_old;
int hodnota = 0;
int i = velikost1;
while ( i-- ) hodnota += poleA[A_new++] * poleB[B_new++];
poleC[C_new++] = hodnota;
}
A_old = A_new;
}
konecNasob = clock();
printf("Doba nasobeni matice %6.2f sec\n",(konecNasob-startNasob)/(double) CLOCKS_PER_SEC);
#ifdef VYPIS_MATIC
printf("Zde je vypoctený vynasobeny vektor\n");
k = 0;
for(i=0;i<velikost2;i++) {
for(j=0;j<velikost2;j++) printf("%i \t",poleC[k++]);
printf("\n");
}
#endif
/****************** Ulozime matici do Souboru ***************************/
free(poleA);poleA=NULL; // vymazeme hodnoty a referenci
free(poleB);poleB=NULL; // vymazeme hodnoty a referenci
char nazevSouboru3 [15];
printf("Vlozte jmeno souboru pro matici 3 (vyslednou):");
if ( scanf("%15s",nazevSouboru3) <= 0 ) // pozor cteme pouze prvnich 15 znaku --- %15s
{
fprintf(stderr, "Spatny nazev souboru?\n" );
return -1;
}
FILE *fr3;
fr3 = fopen(nazevSouboru3,"w"); // nacteme soubor 1
fprintf(fr3,"%i\n",velikost1); // ulozime rad matice
startZapis =clock();
k = 0;
for(i=0;i<velikost2;i++) {
for(j=0;j<velikost2;j++) {
fprintf(fr3,"%i ",poleC[k++]);
}
fprintf(fr3,"\n");
}
konecZapis = clock();
printf("Doba ukladani matice %6.2f sec\n",(konecZapis-startZapis)/(double) CLOCKS_PER_SEC);
fclose(fr3);
free(poleC);poleC=NULL; // vymazeme hodnoty a referenci
printf("Program ukoncite stiknutim libovolne klavesy\n");
// getch(); // cekame na stiknuti klavesnice
}