2013-06-23 7 views
8

Ich bin schwer zu verstehen, warum dieses Bit des Codes (angepasst von der R Benchmark 2.5) (im Durchschnitt) mit zunehmender Anzahl der Iteration langsamer und langsamer wird.R-Schleife wird langsamer und langsamer

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) 
} 

Hier ist ein sample output, die leicht von einem Durchgang zum nächsten variiert.

Wie ich es verstehe, sollte nichts von einer Iteration zur nächsten gespeichert werden, doch das Timing steigt langsam von 1 Sekunde in den ersten paar Runden auf mehr als 4 Sekunden in den späteren Loops. Hast du eine Ahnung, was das verursacht und wie ich es beheben könnte?

Das Umschalten der for-Schleife auf ein * apply scheint ähnliche Ergebnisse zu liefern.

Ich weiß, dass der Code nicht optimiert ist, aber er stammt aus einem weit verbreiteten Benchmark, und je nachdem, was dieses Verhalten verursacht, könnte dies auf eine schwerwiegende Verzerrung seiner Ergebnisse hinweisen (die standardmäßig nur dreimal iteriert).

Ich starte R-Version 3.0.1 (x86_64) auf Mac OS 10.8.4 mit 16 GB RAM (viele davon ist frei). Das BLAS ist OpenBLAS.

+0

Ich bin nicht in der Lage, dies mit einem sehr ähnlichen Setup zu replizieren. Wie viele Iterationen braucht es, um langsamer zu werden? – GSee

+0

Auf meinem Computer dauert jede Iteration ~ 30 Sekunden. Ich machte 10 und sie waren alle etwa 30-35 Sekunden lang. –

+0

PC hier. Eine flache 9 Sekunden pro Iteration. Ich verwende die ATLAS-Bibliothek, von der ich weiß, dass sie diese Art von Operationen viel schneller macht, zumindest verglichen mit der BLAS-DLL, die standardmäßig kommt. OPs Mac ist immer noch viel schneller ... Wie auch immer, wir fangen an, ein guter Haufen zu sein, der das Problem nicht reproduzieren kann. Vielleicht sollte das OP erwägen, die gesamte 'system.time'-Ausgabe zu drucken. * verstrichene Zeit * ('[3]') sagt nicht immer die ganze Geschichte; Vielleicht * User Time * wird eine bessere Wahl sein. – flodel

Antwort

0

Vielleicht könnten Sie versuchen, den Code innerhalb der for-Schleife zu einer Funktion zu machen. Auf diese Weise gibt es wirklich keine Möglichkeit, dass ein Lauf einen anderen beeinflusst. Es beseitigt auch die Unordnung, die durch übermäßige Verwendung von rm() und gc() verursacht wird.

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

Eine Lösung wäre, das Compiler-Paket zu verwenden, um Ihren Code in Byte-Code zu kompilieren. Dies sollte die ungeraden Timing-Probleme beseitigen, da es in jeder Iteration denselben kompilierten Code aufruft. Es sollte auch Ihren Code schneller machen. Um den Compiler auf dem Code zu ermöglichen, sind die beiden folgenden Zeilen:

library(compiler) 
enableJIT(3) 

Wenn Sie den Code kompilieren das Problem nicht beseitigen, so ist die Menge verdächtiger Probleme werden verengt.