Recentemente ho iniziato a leggere i benchmark e li scrivo per Android (in Java). Sono a conoscenza di problemi come warmups, garbage collector e ottimizzazioni del compilatore ma non so se il problema che ho di fronte potrebbe essere causato da uno di questi.Perché l'aggiunta di variabili locali causa un ritardo nel metodo?
Nella mia app benchmark creo una matrice di 10.000 variabili float e la inizializzo con valori casuali. Quando si esegue il codice di riferimento:
private void runMinorBenchmarkFloat (float[] array) {
float sum = 0;
long startTime;
long endTime;
/* Fast warm-up */
startTime = System.nanoTime();
for(int i=0; i<SMALL_LOOP_ITERATION_COUNT; i++)
for(int j=0; j<TAB_SIZE; j++)
sum += array[j];
endTime = System.nanoTime() - startTime;
postMessage("Warm-up for FLOAT finished in: " + endTime/1000000 + "ms.\n");
/* Main benchmark loop */
startTime = System.nanoTime();
for(int i=0; i<BIG_LOOP_ITERATION_COUNT; i++)
{
sum = 0;
for(int j=0; j<TAB_SIZE; j++)
sum += array[j];
}
endTime = System.nanoTime() - startTime;
postMessage("Benchmark for FLOAT finished in: " + endTime/1000000 + "ms.\n");
postMessage("Final value: " + sum + "\n\n");
}
sul mio telefono ottengo circa 2 secondi per riscaldamento e 20 secondi per ciclo "reale".
Ora, quando aggiungo altri due variabili float (sum2 e SUM3 - mai usato all'interno del metodo):
private void runMinorBenchmarkFloat (float[] array) {
float sum = 0, sum2 = 0, sum3 = 0; // <------- the only code change here!!!
long startTime;
long endTime;
/* Fast warm-up */
startTime = System.nanoTime();
for(int i=0; i<SMALL_LOOP_ITERATION_COUNT; i++)
for(int j=0; j<TAB_SIZE; j++)
sum += array[j];
endTime = System.nanoTime() - startTime;
postMessage("Warm-up for FLOAT finished in: " + endTime/1000000 + "ms.\n");
/* Main benchmark loop */
startTime = System.nanoTime();
for(int i=0; i<BIG_LOOP_ITERATION_COUNT; i++)
{
sum = 0;
for(int j=0; j<TAB_SIZE; j++)
sum += array[j];
}
endTime = System.nanoTime() - startTime;
postMessage("Benchmark for FLOAT finished in: " + endTime/1000000 + "ms.\n");
postMessage("Final value: " + sum + "\n\n");
}
tempo di esecuzione salta da 2 secondi per riscaldamento a 5 secondi e da 20 secondi per il ciclo vero e proprio a 50 secondi.
Le costanti:
SMALL_LOOP_ITERATION_COUNT = 100,000
BIG_LOOP_ITERATION_COUNT = 1,000,000
Pensi che tale differenza potrebbe essere causato da problemi di allineamento (solo idea sciolto)?
Grazie in anticipo per eventuali risposte.
EDIT:
Sembra che questo errore non viene visualizzato su tutti i dispositivi. Posso riprodurlo su Samsung Galaxy S5. L'obiettivo principale del programma era di fare un piccolo punto di riferimento. Ho eseguito quattro funzioni quasi identiche (runMinorBenchmark____ dove _ era: int, short, float, double) che differivano solo nel tipo di 'somma' variabile. Nella funzione principale di riferimento ho invocato queste funzioni. Poiché si è verificato l'errore menzionato, ho deciso di unire quella funzione in una grande. Ora ... Durante l'esecuzione del test, ho i seguenti orari: 1. 37640 ms. (per int) 2. 46728 ms. (in breve) 3. 60589 ms. (per galleggiante) 4. 34467 ms. (per il doppio)
So che il cortocircuito deve essere più lento a causa del tipo di trasmissione. Ho anche pensato che il float dovrebbe essere più lento in caso di casting per raddoppiare (forse FPU digita casting per raddoppiare ogni volta (?)). Ma quando cambio il tipo di variabile per sumFloat da float a raddoppiare il tempo per float è identico al doppio tempo. Ho anche fatto questo "benchmark" su un altro dispositivo che sembrava non soffrire di questo strano comportamento e i tempi per ogni test erano quasi gli stessi: ~ 45000ms. (davvero nessuna differenza visibile).
errore Dalvik VM (?)
No. L'aggiunta di due campi "non utilizzati" non influirà sul tempo di esecuzione effettivo del ciclo. Qualcos'altro deve essere sbagliato. – TheLostMind
Sono d'accordo con @TheLostMind. L'aggiunta di due variabili float non dovrebbe aumentare significativamente il tempo di esecuzione. Come potete vedere, la CPU può elaborare 10.000 float molto rapidamente, quindi non c'è motivo per cui non dovrebbe essere in grado di elaborare questi due in un modo veloce. – erad
Grazie per le risposte. Sono d'accordo con entrambi, ma è quello che succede davvero. Hai qualche idea su dove guardare oltre? – Waszker