Sziasztok!
Egy text fájlban viszonylag nagy mennyiségű adatom van. Ezek egész számok, és egy sorban két szám helyezkedik el.
Pl. így:
1232 17
635 864
397 3766
... stb. kb. 100000 sorban.
Mi az a leggyorsabb módszer szerintetek, amivel be lehet húzni a memóriába az adatokat?
Jelenleg ezt a módszert használom:
BufferedReader be = new BufferedReader(new FileReader("be.txt"));
for (int i = 0; i < m; i++) {
s = be.readLine();
st = new StringTokenizer(s);
int egyik = Integer.parseInt(st.nextToken());
int masik = Integer.parseInt(st.nextToken());
M[egyik][masik] = 1;
}
- 2786 megtekintés
Hozzászólások
Egyszerre, egy Stringbe nem lehetne behúzni az egészet?
- A hozzászóláshoz be kell jelentkezni
+1, ennyi sorral is még egy MB alatt van, ami semmi, memóriából viszont gyorsabban megy. Először olvass be mindent.
--
The Net is indeed vast and infinite...
http://gablog.eu
- A hozzászóláshoz be kell jelentkezni
amikor ilyen cikluson belul new szerepel, az altalaban nem jo. De indits ra egy profilert!
Amikor utoljara ilyet csinaltunk, ott egy bufferbe ment be a cucc, amibol egy threadpool segitsegevel vegezte a parsolast N db szal. A teljesitmeny 20 MB/sec volt akkori vason, igaz, ott kicsit tobb dolgot kellett parsolni.
- A hozzászóláshoz be kell jelentkezni
Ez SZTE és valamilyen alga vagy más biro-ra beadandó prog?
Ha igen, akkor a feladatkiírásban le van írva, hogy
Java-ban milyen módszerrel célszerű beolvasni a be.txt-t.
Ha nem, akkor bocs. :P
--
A gyors gondolat többet ér, mint a gyors mozdulat.
- A hozzászóláshoz be kell jelentkezni
1) a BufferedReader-nek van olyan konstruktora, aminek megadhatod, hogy mekkora legyen az input buffer. Ergo megadsz egy jó nagy számot és az egész beugrik a BufferedReader memóriájába.
2) Létezik olyan, hogy String.split(String regex).
String[] result = "this is a test".split("\\s");
Ez pl szpészek mentén felbontja és a Tokenizer sem kell.
A kódodat nem írom át és postolom ide, mert /tabletta dolgom van (kávéügyben kell eljárnom).
Bizony, csak javadoc-ot kell olvasni.
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
- A hozzászóláshoz be kell jelentkezni
Azt kérdezte, hogyan a leggyorsabb. Ha már a KV-nál tartasz, fogadok egyben, hogy a .split() legalább 3x lassabb a Tokenizernél (pláne, ha nem new-ol újat minden ciklusban, bár ehhez talán több lefutás kell, hogy számítson)
- A hozzászóláshoz be kell jelentkezni
A Sun mégis inkább a split-et ajánlja:
"StringTokenizer is a legacy class that is retained for compatibility reasons although its use is discouraged in new code. It is recommended that anyone seeking this functionality use the split method of String or the java.util.regex package instead."
- A hozzászóláshoz be kell jelentkezni
Az egy dolog, hogy a Sun mit ajanl, meg hogy mi a gyors. Az biztos, hogy nem is probalkoznek a belso String metodusokkal, ha fontos a teljesitmeny. A legtobb egy rakas uj objektumot hoz letre hivasonkent.
- A hozzászóláshoz be kell jelentkezni
En inkabb bizom a Sun ajanlasaiban :)
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
- A hozzászóláshoz be kell jelentkezni
StringTokenizer-nek stringet csak konstruktorban tudsz megadni, metódusból nem, szóval new StringTokenizer(be.ReadLine()) minden iterációban.
Nem fogadok a kávémba mert már megittam, de sztem a tokenizer is regexp osztályokat használ.
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
- A hozzászóláshoz be kell jelentkezni
Köszönöm a hozzászólásokat!
Nemsokára nekiállok elkészíteni az új verziót. Majd közlöm, ha kész, és meg lehet köpködni, hátha segít rajta.
Addig is üdv mindenkinek!
- A hozzászóláshoz be kell jelentkezni
Na, megvan.
Direkte erre találták ki, a fogorvos is ezt ajánlja. Ezzel elkerülheted a java.io borzalmait.
Scanner sc = new Scanner(new File("myNumbers"));
while (sc.hasNextInt()) {
int egésszám = sc.nextInt();
int másikegésszám = sc.nextInt();
// ide jön a műveleted.
}
Kérdés előtt: a nextInt() az inteket parsolja be, a whitespace-eket átugorja (úgymint \n, , \t).
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
- A hozzászóláshoz be kell jelentkezni
Nagyon biztatónak tűnt a javaslatod, de nem vált be.
Eleddig az egész program futása tartott kb. 1 másodpercig (számításokkal együtt.)
A scanner használatával megnőtt a futásidő kb. 2 másodpercre.
- A hozzászóláshoz be kell jelentkezni
Egyelőre ezt csináltam. A scanner-ezést még nem tudtam figyelembe venni.
File inFile = new File("be.txt");
int fileSize = (int) inFile.length();
char [] buff = new char [fileSize];
BufferedReader be = new BufferedReader(new FileReader(inFile));
be.read(buff, 0, fileSize);
be.close();
int indexBuff = fileSize - 1;
int [] szam = new int [2];
int hatvany;
for (int i = 0; i < m; i++) {
szam[0] = 0;
szam[1] = 0;
for (int j = 1; j >= 0; j--) {
while (buff[indexBuff] < '0' || buff[indexBuff] > '9') {
indexBuff--;
}
hatvany = 1;
while (buff[indexBuff] >= '0' && buff[indexBuff] <= '9') {
szam[j] += hatvany * (buff[indexBuff] - '0');
indexBuff--;
hatvany *= 10;
}
indexBuff--;
}
M[szam[0]][szam[1]] = 1;
}
Erről mi a véleményetek?
- A hozzászóláshoz be kell jelentkezni
futási idő?
--
"SzAM-7 -es, tudjátok amivel a Mirage-okat szokták lelőni" - Robi.
- A hozzászóláshoz be kell jelentkezni
Így a reader fogja elvinni az egész időt. Ráadásul így leírva a működés platformfüggő, mert az alapértelmezett kódolással olvassa a fájlt, ami akármi lehet. Ne char bufferbe töltsd be, hanem byte tömbbe a karaktereket, hiszen sima ascii fájlod van. Legalábbis ha csak számok vannak benne akkor a UTF-8 is ASCII.
egy rikta bináris mátrix van a fájlban? a számok kézzel parszolását akartam én is javasolni. Így a fordító C-ben írt kód szintű optimalitásra lehet képes.
Mondjuk a szam[0] és szam[1] helyett jobb lenne szam0 és szam1, persze akkor a kódot kétszer kell leírni, de elvileg hatékonyabb lehet mert nincs indirekt címzés. Bár az egész úgyis cache-n belül marad, lehet hogy nem lesz mérhető a javulás.
buff[indexBuff]-ból nem tudom hogy a fordító csinál-e lokális átmeneti változót. Ha nem akkor ha kihozod lokálba az első lekérdezés előtt lehet hogy gyorsabb lesz. akkor nem fordul 4x a memóriához, hanem csak egyszer.
Ha valami modern hw platformon dolgozol akkor érdemes annyi szálat indítani ahány magod van (X2 ha van hyperthreading). Azért ez nem mindig jön be (mármint a hyperthreading). Egy haverom mért ilyeneket és voltak ellentmondó eredmények.
Utolsó vicces lehetőség a ciklus kihajtogatása. Ez is hozhat javulást Javában. Ennél az algoritmusnál sajnos nem nagyon lehet beleálmodni ennek a lehetőségét, ha az input fix méretűsítése nem megoldható.
Ja, és mindenképp a legújabb Javával próbálkozz, mert ilyen int műveletekre optimalizációban nagyon sokat fejlődött a JIT compiler.
- A hozzászóláshoz be kell jelentkezni
Jókat mondasz, de ez nem C :) És ne is tegyünk már úgy, mintha az lenne. Egy ekkora programnál halál mindegy a szam[0], a lokális változót meg egyébként is hagyjuk. Ez a fordító dolga, pláne Java esetén. Legalábbis szerintem rohadtul nem vezet semmi jóra, ha az ember C-ben kezd Java kódot írni. Majd ahol kell az a 3%... De egyébként továbbra is: profiler.
Inkább koncentráljunk az algoritmusra: véleményem szerint ennyi adatnál a startup/rampup jóval több idő lesz, mint a feldolgozás.
- A hozzászóláshoz be kell jelentkezni
Inkább nézd meg ezt:
http://hup.pastebin.com/f3e90435c
Fogalmam sincs, hogy mennyivel gyorsabb, vagy lassabb, de legalább hasonlít Java kódra.
- A hozzászóláshoz be kell jelentkezni
- A hozzászóláshoz be kell jelentkezni
Ezt a grafikonos kimutatást, mivel csinálod?
Érdekelne a téma.
- A hozzászóláshoz be kell jelentkezni