Vektorisierung für mehr Geschwindigkeit
Ersetzen Sie explizite Schleifen durch vektorisierte Operationen und beschleunigen Sie Ihren Code deutlich
Vektorisierung für mehr Geschwindigkeit ist eine kostenlose R Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des R Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der R Academy-Kurs umfasst insgesamt 4 Lektionen.
Warum Vektorisierung wichtig ist
R ist eine interpretierte Sprache, daher verursachen for-Schleifen bei jeder Iteration zusätzlichen Aufwand – etwa beim Verteilen von Funktionsaufrufen, bei der Bereichsprüfung und bei der Typumwandlung. Vektorisierte Operationen verlagern diese Arbeit in kompilierten C-Code, der um Größenordnungen schneller ausgeführt wird.
Vektorisierung ist die wirkungsvollste Optimierung, die Ihnen in Base R zur Verfügung steht.
Beispiel: Schleife im Vergleich zu cumsum()
Die Berechnung einer laufenden Summe mit einer for-Schleife im Vergleich zur integrierten Funktion cumsum() zeigt den Unterschied deutlich. cumsum() ruft kompilierten Code auf C-Ebene auf und verarbeitet den gesamten Vektor in einem Durchlauf.
n <- 500000
x <- rnorm(n)
t_loop <- system.time({
result <- numeric(n)
result[1] <- x[1]
for (i in 2:n) result[i] <- result[i-1] + x[i]
})['elapsed']
t_vec <- system.time({
result2 <- cumsum(x)
})['elapsed']
cat('Loop :', t_loop, 's
')
cat('cumsum:', t_vec, 's
')ifelse() im Vergleich zu for + if
ifelse(condition, yes, no) ist eine vektorisierte Bedingung, die die Bedingung gleichzeitig auf einen gesamten Vektor anwendet. Dadurch werden Schleifen mit for + if, die Element für Element arbeiten, durch einen einzigen Durchlauf auf C-Ebene ersetzt.
n <- 300000
x <- rnorm(n)
t_loop <- system.time({
result <- numeric(n)
for (i in seq_len(n)) result[i] <- if (x[i] > 0) x[i] else -x[i]
})['elapsed']
t_vec <- system.time({
result2 <- ifelse(x > 0, x, -x)
})['elapsed']
cat('for+if :', t_loop, 's
')
cat('ifelse :', t_vec, 's
')Ergebnisvektoren vorab reservieren
Wenn eine Schleife unvermeidbar ist, reservieren Sie den Ergebnisvektor vorab. Wenn Sie innerhalb einer Schleife mit c(result, new_val) einen Vektor vergrößern, wird der gesamte Vektor bei jeder Iteration kopiert – insgesamt O(n^2) Speicheroperationen.
n <- 20000
t_grow <- system.time({
result <- c()
for (i in seq_len(n)) result <- c(result, i^2)
})['elapsed']
t_prealloc <- system.time({
result2 <- numeric(n)
for (i in seq_len(n)) result2[i] <- i^2
})['elapsed']
cat('Growing vector:', t_grow, 's
')
cat('Pre-allocated :', t_prealloc, 's
')Die richtigen Typen für die Vorabreservierung
Verwenden Sie den typisierten Konstruktor, der zu Ihren Daten passt, um eine implizite Typumwandlung bei der Vorabreservierung zu vermeiden:
numeric(n)– Gleitkommazahlen mit doppelter Genauigkeitinteger(n)– Ganzzahlencharacter(n)– leere Zeichenkettenlogical(n)– FALSE-Wertevector('list', n)– Liste mit NULL-Werten
n <- 5
cat('numeric :', numeric(n), '
')
cat('integer :', integer(n), '
')
cat('logical :', logical(n), '
')
cat('character:', character(n), '
')
cat('list len :', length(vector('list', n)), '
')colSums() und rowSums() im Vergleich zu apply()
Für Matrixoperationen sind colSums(m), rowSums(m), colMeans(m) und rowMeans(m) stark optimierte C-Routinen. Sie sind durchgehend schneller als apply(m, 1, sum), das die R-Funktion sum einmal pro Zeile aufruft.
m <- matrix(rnorm(1000 * 2000), nrow = 1000)
t_apply <- system.time(apply(m, 2, sum))['elapsed']
t_colsums <- system.time(colSums(m))['elapsed']
cat('apply(m,2,sum):', t_apply, 's
')
cat('colSums(m) :', t_colsums, 's
')Vektorisierte Arithmetik ist immer schnell
Grundlegende Arithmetik mit Vektoren – +, -, *, /, ^, sqrt(), log(), exp() – ist vollständig vektorisiert. Die Operationen werden elementweise für einen gesamten Vektor in einem einzigen C-Aufruf ausgeführt. Bevorzugen Sie sie immer gegenüber Schleifen.
x <- 1:1000000
t1 <- system.time(y <- x^2 + 2*x + 1)['elapsed']
t2 <- system.time({
y2 <- numeric(length(x))
for (i in seq_along(x)) y2[i] <- x[i]^2 + 2*x[i] + 1
})['elapsed']
cat('Vectorized:', t1, 's
')
cat('Loop :', t2, 's
')Logische Teilmengenauswahl statt Schleifen
Das Filtern eines Vektors mit einer logischen Bedingung ist vektorisiert. Statt eine Schleife zu verwenden und Elemente bedingt anzuhängen, erstellen Sie einen logischen Index und wählen die Teilmenge einmal aus – der zugrunde liegende C-Code durchläuft die Daten in einem einzigen Durchgang.
x <- rnorm(500000)
t_loop <- system.time({
pos <- c()
for (v in x) if (v > 0) pos <- c(pos, v)
})['elapsed']
t_vec <- system.time({
pos2 <- x[x > 0]
})['elapsed']
cat('Loop filter:', t_loop, 's
')
cat('Logical idx:', t_vec, 's
')which() und tabulate() für Indexoperationen
Wenn Sie die Positionen der TRUE-Werte benötigen, ist which(condition) vektorisiert und schnell. tabulate(bin_vector) zählt ganzzahlige Vorkommen bei dichten Ganzzahlbereichen schneller als table().
x <- sample(1:10, 100000, replace = TRUE)
t_table <- system.time(table(x))['elapsed']
t_tabulate <- system.time(tabulate(x, nbins = 10))['elapsed']
cat('table() :', t_table, 's
')
cat('tabulate():', t_tabulate, 's
')
idx <- which(x == 5)
cat('Positions of 5: first 5 =', head(idx, 5), '
')Wann Schleifen noch vertretbar sind
Nicht jede Schleife ist schlecht. Schleifen sind vertretbar, wenn:
- jede Iteration vom vorherigen Ergebnis abhängt (sequentielle Abhängigkeit)
- die Anzahl der Iterationen klein ist (< 1000)
- der Schleifenkörper eine komplexe Funktion ohne vektorisiertes Gegenstück aufruft
Konzentrieren Sie sich in diesen Fällen auf die Vorallokation und vermeiden Sie es, Strukturen innerhalb der Schleife zu vergrößern.
# Sequential dependency -- loop is correct here
fib <- function(n) {
result <- integer(n)
result[1] <- 1L
if (n >= 2) result[2] <- 1L
for (i in seq_len(n)[-c(1,2)]) result[i] <- result[i-1] + result[i-2]
result
}
cat('Fibonacci:', fib(10), '
')Zusammenfassung der Vektorisierung
Wichtige Regeln für schnellen R-Code:
- Verwenden Sie
cumsum/cumprod/difffür sequenzielle Akkumulationen - Verwenden Sie
ifelse()für elementweise Bedingungen - Allokieren Sie Speicher vorab mit
numeric(n)/vector('list',n) - Verwenden Sie
colSums/rowSums/colMeans/rowMeansanstelle vonapply() - Logische Teilmengenauswahl ist besser als Filterscheifen
Schnelltest: Vorallokation
Warum ist es bei großem n so langsam, einen Vektor innerhalb einer Schleife mit result <- c(result, new_val) zu vergrößern?
Rückblick: Vektorisierung
Die Vektorisierung ist der wichtigste Performance-Hebel von R:
- Vektorisierte Funktionen (
cumsum,ifelse, arithmetische Operatoren) rufen kompilierten C-Code auf – sie sind 10- bis 100-mal schneller als entsprechende R-Schleifen - Allokieren Sie Ergebniscontainer vor jeder unvermeidbaren Schleife vorab, um Kopiervorgänge mit O(n^2) zu vermeiden
colSums/rowSumssind bei Matrixaggregation schneller alsapply()- Logische Teilmengenauswahl ersetzt Filterscheifen sauber und schnell
Häufig gestellte Fragen
Ist die Lektion „Vektorisierung für mehr Geschwindigkeit“ kostenlos?
Ja — der vollständige Text von „Vektorisierung für mehr Geschwindigkeit“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des R Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der R Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Vektorisierung für mehr Geschwindigkeit“?
Ersetzen Sie explizite Schleifen durch vektorisierte Operationen und beschleunigen Sie Ihren Code deutlich Du übst R Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um R Academy zu starten?
Keine Vorkenntnisse erforderlich. R Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Vektorisierung für mehr Geschwindigkeit“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser R Academy-Lektion Code schreiben und ausführen?
Ja. Jede R Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- system.time() und proc.time()
- Code mit Rprof und profvis profilieren
- Vektorisierung für mehr Geschwindigkeit
- Benchmarking mit microbenchmark