Niedawno zacząłem czytać o testach porównawczych i pisać je dla Androida (w Javie). Zdaję sobie sprawę z takich problemów, jak rozgrzewki, garbage collector i optymalizacje kompilatorów, ale nie wiem, czy problem, który napotykam, może być spowodowany przez którykolwiek z tych problemów.Dlaczego dodawanie zmiennych lokalnych powoduje opóźnienie metody?
W mojej aplikacji testowej tworzę tablicę 10 000 zmiennych zmiennoprzecinkowych i inicjalizuję ją losowymi wartościami. Podczas uruchamiania kodu odniesienia:
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");
}
na moim telefonie mam około 2 sekundy do rozgrzewki i 20 sekund do „prawdziwego” pętli.
Teraz, gdy dodam jeszcze dwie zmienne float (sum2 i sum3 - nigdy nie używane wewnątrz metody):
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");
}
czas realizacji skacze z 2 sekund rozgrzewki na 5 sekund i od 20 sekund do realnego pętli do 50 sekund.
Stałe:
SMALL_LOOP_ITERATION_COUNT = 100,000
BIG_LOOP_ITERATION_COUNT = 1,000,000
Myślisz, że taka różnica może być spowodowana przez problemy wyrównania (tylko luźny pomysł)?
Z góry dziękuję za wszelkie odpowiedzi.
EDIT:
Wydaje się, że ten błąd nie pojawia się na każdym urządzeniu. Mogę go odtworzyć na Samsung Galaxy S5. Głównym celem programu było wykonanie małego benchmarku. Zrobiłem cztery prawie te same funkcje (runMinorBenchmark____ gdzie _ było albo: int, short, float, double), które różniły się tylko zmiennym typem "sum". W głównej funkcji testu porównawczego wywołałem te funkcje. Ponieważ wystąpił wspomniany błąd, postanowiłem połączyć te funkcje w jedną dużą. Teraz ... Podczas testu mam takie czasy: 1. 37640ms. (dla int) 2. 46728 ms. (w skrócie) 3. 60589ms. (dla pływaka) 4. 34467ms. (dla podwójnego)
Wiem, że krótki ma być wolniejszy z powodu odlewania typu. Sądziłem również, że pływak powinien być wolniejszy w przypadku rzucania go do podwójnego (być może FPU robi typ castingu za każdym razem dwukrotnie (?)). Ale kiedy zmienię typ zmiennej dla sumFloat z float na podwójny czas dla float jest identyczny z podwójnym czasem. Zrobiłem też ten "benchmark" na innym urządzeniu, które wydawało się nie cierpieć z powodu tego dziwnego zachowania, a czasy każdego testu były prawie takie same: ~ 45000ms. (naprawdę żadnych widocznych różnic).
błąd Dalvik VM (?)
Nie Dodanie dwóch "nieużywanych" pól nie wpłynie na faktyczny czas działania pętli. Coś jeszcze musi być nie tak. – TheLostMind
Zgadzam się z @ TheLostMind. Dodanie dwóch zmiennych zmiennoprzecinkowych nie powinno znacząco wydłużyć czasu wykonania. Jak widać, procesor może przetwarzać 10 000 ruchów bardzo szybko, więc nie ma powodu, dla którego nie byłby w stanie przetworzyć tych dwóch w szybki sposób. – erad
Dzięki za odpowiedzi. Zgadzam się z obojgiem, ale tak właśnie się dzieje. Czy masz jakieś pomysły, gdzie szukać dalej? – Waszker