Kód optimalizálás

Kollégától kaptam, megmutatom neked is:

int[] arr = new int[64 * 1024 * 1024];
// Loop 1
for (int i = 0; i < arr.Length; i++) arr[i] *= 3;
// Loop 2
for (int i = 0; i < arr.Length; i += 16) arr[i] *= 3;

Melyik a gyorsabb? Az implementációs nyelv legyen mondjuk… java.

Megoldás a folytatásban.

A megoldás: egyik sem, a futási idejük 0. A JVM defaultban 64Mb memóriát foglal a heapben, és a kód már az első sorban megpróbál ~130Mb-t foglalni, futásidejű, végzetessel elszáll.

Komolyra fordítva, bár azt hinnéd, a loop 2 fog rövidebb idő alatt végezni (hiszen harmad annyi iterációt végez), a gyakorlat azt mutatja, hogy a két iteráció futási ideje megegyezik. Ez azért van (már, ha jól értettem) mert a matekolás kisebb erőforrás igényű, mint a memória olvasás. Manapság nem byteonként olvassuk a memóriát, hanem cachelve, és emiatt a kérdéses tömbelem kiolvasása ugyanannyiba fog kerülni. Részletesen, meg hasonló okosságok itt. Olvasd, értelmezd.

A fentiek, ahogy kivettem, natív binárisra érvényesek. Írtam egy Java tesztet, aminek a kimenete:

Init in: 615 ms
Round: 1
Loop 1: 267 ms
Loop 2: 176 ms
Round: 2
Loop 1: 260 ms
Loop 2: 177 ms
Round: 3
Loop 1: 263 ms
Loop 2: 180 ms
Round: 4
Loop 1: 261 ms
Loop 2: 181 ms
Round: 5
Loop 1: 316 ms
Loop 2: 181 ms

Tehát, a loop 1 átlag ~ 1,5* tovább tart mint a loop2 2. Node, mi van akkor, ha felcseréljük a kódban az iteráció helyét?

Init in: 424 ms
Round: 1
Loop 2: 182 ms
Loop 1: 181 ms
Round: 2
Loop 2: 226 ms
Loop 1: 202 ms
Round: 3
Loop 2: 183 ms
Loop 1: 184 ms
Round: 4
Loop 2: 179 ms
Loop 1: 182 ms
Round: 5
Loop 2: 178 ms
Loop 1: 188 ms

Akkor bizony közel egyforma hosszan futnak. Jó, mi? És mielőtt bárki is azt mondaná, hogy azért mert csak egyszer inicializáltam a tömböt, kipróbáltam úgy, hogy minden iteráció előtt újra inicializáltam a tömböket, és nincs lényegi különbség az eredmények közt, ugyan ez a tendencia. Tuti, hogy itt is valami cache dolog játszik be, de hogy pontosan mi, ahhoz kevés vagyok.

Post a comment.