2013-06-23 14 views
8

Próbuję zrozumieć, dlaczego ten fragment kodu (zaadaptowany z R Benchmark 2.5) staje się wolniejszy i wolniejszy (średnio), gdy zwiększa się liczba iteracji.Pętla R coraz wolniej i wolniej

require(Matrix) 
c <- 0; 
for (i in 1:100) { 
    a <- new("dgeMatrix", x = rnorm(3250 * 3250), Dim = as.integer(c(3250, 3250))) 
    b <- as.double(1:3250) 

    invisible(gc()) 
    timing <- system.time({ 
    c <- solve(crossprod(a), crossprod(a, b)) 
    }) 
    print(timing) 

    rm(a, b, c) 
} 

Oto sample output, który różni się nieznacznie od jednego biegu do następnego.

Jak rozumiem, nic nie powinno być zapisywane od jednej iteracji do następnej, jednak czasy powoli wzrastają od 1 sekundy w pierwszych kilku pętlach do ponad 4 sekund w późniejszych pętlach. Czy masz pojęcie, co jest przyczyną tego i jak mogę to naprawić?

Przełączanie pętli for na * zastosowanie wydaje się dawać podobne wyniki.

Wiem, że kod nie jest zoptymalizowany, ale pochodzi z szeroko stosowanego testu porównawczego iw zależności od tego, co powoduje takie zachowanie, może wskazywać na poważne odchylenie w jego wynikach (które domyślnie są trzykrotnie iterowane domyślnie).

Używam wersji R 3.0.1 (x86_64) na Mac OS 10.8.4 z 16 GB pamięci RAM (z których wiele jest bezpłatne). BLAS to OpenBLAS.

+0

Nie mogę odtworzyć tego przy użyciu bardzo podobnej konfiguracji. Ile iteracji wymaga spowolnienia? – GSee

+0

Na moim komputerze każda iteracja trwa ~ 30 sekund. Zrobiłem 10 i wszystkie miały około 30-35 sekund. –

+0

PC tutaj. Płaskie 9 sekund na iterację. Korzystam z biblioteki ATLAS, o której wiem, że tego typu operacje są znacznie szybsze, przynajmniej w stosunku do biblioteki BLAS, która jest domyślnie dostępna. Mac OS jest wciąż znacznie szybszy ... W każdym razie zaczynamy być dobrym zespołem, który nie jest w stanie odtworzyć problemu. Może OP powinien rozważyć wydrukowanie całego wyjścia 'system.time'. * upływ czasu * ('[3]') nie zawsze mówi całą historię; Może * czas użytkownika * będzie lepszym wyborem. – flodel

Odpowiedz

0

Być może możesz spróbować zrobić kod w pętli for w funkcję. W ten sposób nie ma możliwości, aby jeden bieg mógł wpłynąć na inny. Ponadto usuwa niechlujstwo spowodowane nadmiernym użyciem rm() i gc().

require(Matrix) 

NewFun <- function() { 
    a <- new("dgeMatrix", x = rnorm(3250 * 3250), Dim = as.integer(c(3250, 3250))) 
    b <- as.double(1:3250) 
    timing <- system.time({ 
     c <- solve(crossprod(a), crossprod(a, b)) 
    }) 
    print(timing) 
} 

for (i in 1:100) { 
    NewFun() 
} 
1

Jednym z rozwiązań byłoby użycie kompilatora do skompilowania kodu do kodu bajtowego. Powinno to wyeliminować problemy z synchronizacją czasu, ponieważ będzie wywoływać ten sam skompilowany kod w każdej iteracji. Powinien również przyspieszyć twój kod. Aby włączyć kompilator na kodzie, zawierają dwie linie poniżej:

library(compiler) 
enableJIT(3) 

Jeśli kompilacji kodu nie eliminuje problemu, wówczas zbiór podejrzanych problemów zostanie zawężony.

Powiązane problemy