Paket parallel und detectCores()
Starten Sie Fork- oder Socket-Cluster und verteilen Sie Aufgaben auf CPU-Kerne
Paket parallel und detectCores() ist eine kostenlose R Academy-Lektion auf CoddyKit. Dies ist Lektion 1 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 paralleles Rechnen?
Moderne Computer verfügen über mehrere CPU-Kerne. Standardmäßig läuft R auf einem einzigen Kern, während die übrigen ungenutzt bleiben. Mit dem Paket parallel (in R integriert) können Sie alle Kerne nutzen, um wiederholte Berechnungen zu beschleunigen.
# Check how many cores your machine has
library(parallel)
total_cores <- detectCores()
logical_cores <- detectCores(logical = TRUE)
physical_cores <- detectCores(logical = FALSE)
cat('Total logical cores:', total_cores, '
')
cat('Physical cores:', physical_cores, '
')makeCluster und stopCluster
makeCluster(n) startet n Worker-Prozesse. Rufen Sie nach Abschluss immer stopCluster(cl) auf, um Ressourcen freizugeben. Üblicherweise wird detectCores() - 1 verwendet, damit ein Kern für das Betriebssystem frei bleibt.
library(parallel)
# Spawn workers (leave 1 core for system)
n_cores <- detectCores() - 1
cl <- makeCluster(n_cores)
cat('Cluster created with', n_cores, 'workers\n')
# Always clean up!
stopCluster(cl)
cat('Cluster stopped.\n')clusterExport: Variablen teilen
Worker-Prozesse verfügen über einen eigenen Speicherbereich und können Ihre globale Umgebung nicht sehen. Verwenden Sie clusterExport(cl, varlist), um benannte Objekte vom Master an alle Worker zu kopieren.
library(parallel)
cl <- makeCluster(2)
# Define a variable and a function in the master
base_value <- 100
add_base <- function(x) x + base_value
# Export them to workers
clusterExport(cl, varlist = c('base_value', 'add_base'))
# Now workers can use them
result <- parLapply(cl, 1:4, function(x) add_base(x))
cat(unlist(result), '\n') # 101 102 103 104
stopCluster(cl)clusterEvalQ: Setup-Code ausführen
clusterEvalQ(cl, expr) wertet einen Ausdruck auf jedem Worker aus – nützlich, um Pakete zu laden oder Hilfsdateien auf allen Knoten einzubinden, bevor die Hauptberechnung beginnt.
library(parallel)
cl <- makeCluster(2)
# Load a package on every worker
clusterEvalQ(cl, {
library(stats)
set.seed(42) # set seed per worker
})
# Each worker can now use stats functions
result <- parLapply(cl, 1:4, function(n) rnorm(n, mean = 0, sd = 1))
result[[1]] # one random normal value
stopCluster(cl)parLapply: Paralleles lapply
parLapply(cl, X, FUN) ist das parallele Gegenstück zu lapply(). Die Elemente von X werden auf die Worker verteilt und die Ergebnisse als Liste gesammelt. Die Funktion funktioniert auf allen Plattformen (Windows, macOS, Linux).
library(parallel)
cl <- makeCluster(2)
# Simulate slow computation: sleep 0.1s per item
clusterEvalQ(cl, Sys.sleep)
slow_square <- function(x) {
Sys.sleep(0.05)
x^2
}
clusterExport(cl, 'slow_square')
system.time(
result <- parLapply(cl, 1:8, slow_square)
)
cat(unlist(result), '\n') # 1 4 9 16 25 36 49 64
stopCluster(cl)parSapply: Vereinfachte Ergebnisse
parSapply(cl, X, FUN) ist die parallele Version von sapply(). Das Ergebnis wird, sofern möglich, automatisch zu einem Vektor oder einer Matrix vereinfacht. Das ist praktisch, wenn Ihre Funktion einen Skalar zurückgibt.
library(parallel)
cl <- makeCluster(2)
# parSapply returns a simplified vector
squares <- parSapply(cl, 1:10, function(x) x^2)
cat(squares, '\n') # 1 4 9 16 25 36 49 64 81 100
# Returns a matrix if FUN returns a vector of same length
stats_result <- parSapply(cl, 1:4, function(n) {
x <- rnorm(100)
c(mean = mean(x), sd = sd(x))
})
print(stats_result) # 2x4 matrix
stopCluster(cl)mclapply: Paralle Verarbeitung per Fork
mclapply() verwendet Forking – es kopiert den aktuellen R-Prozess, anstatt neue Prozesse zu starten. Dadurch ist der Start schneller und die Worker haben implizit Zugriff auf die übergeordnete Umgebung. Es funktioniert jedoch nur unter Unix/macOS, nicht unter Windows.
library(parallel)
# mclapply: Unix/macOS only
# Workers inherit the parent environment automatically
base_value <- 42
if (.Platform$OS.type != 'windows') {
result <- mclapply(
1:8,
function(x) x * base_value, # base_value visible without export
mc.cores = 4
)
cat(unlist(result), '\n')
} else {
cat('mclapply not supported on Windows. Use parLapply instead.\n')
}Sequenzielle und parallele Ausführung vergleichen
Parallele Verarbeitung verursacht einen Overhead: Der Clusterstart, die Serialisierung von Daten und die Kommunikation zwischen Prozessen benötigen jeweils Zeit. Sie lohnt sich nur, wenn die Berechnung pro Element aufwendig genug ist, um diesen Overhead auszugleichen.
library(parallel)
cl <- makeCluster(2)
# Task: compute 100 iterations of matrix multiply
heavy_task <- function(n) {
m <- matrix(rnorm(200), nrow = 100)
sum(m %*% t(m))
}
clusterExport(cl, 'heavy_task')
seq_time <- system.time(lapply(1:20, heavy_task))[['elapsed']]
par_time <- system.time(parLapply(cl, 1:20, heavy_task))[['elapsed']]
cat('Sequential:', round(seq_time, 3), 's\n')
cat('Parallel: ', round(par_time, 3), 's\n')
cat('Speedup: ', round(seq_time / par_time, 2), 'x\n')
stopCluster(cl)RNG bei paralleler Ausführung initialisieren
Die Erzeugung von Zufallszahlen bei paralleler Ausführung ist anspruchsvoll – jeder Worker benötigt einen unabhängigen, reproduzierbaren Zufallszahlenstrom. Verwenden Sie clusterSetRNGStream(cl, seed) mit dem Generator L'Ecuyer-CMRG, um reproduzierbare Zufallszahlen bei paralleler Ausführung zu erhalten.
library(parallel)
cl <- makeCluster(2)
# Set reproducible RNG streams across workers
clusterSetRNGStream(cl, iseed = 123)
# Each worker uses its own independent random stream
results1 <- parSapply(cl, 1:6, function(i) rnorm(1))
# Reset and repeat — same results
clusterSetRNGStream(cl, iseed = 123)
results2 <- parSapply(cl, 1:6, function(i) rnorm(1))
cat('Run 1:', round(results1, 4), '\n')
cat('Run 2:', round(results2, 4), '\n')
cat('Identical:', identical(results1, results2), '\n')
stopCluster(cl)Fehlerbehandlung in Clustern
Wenn ein Worker einen Fehler auslöst, gibt parLapply() diesen im Master-Prozess erneut aus. Umschließen Sie Aufrufe innerhalb der Funktion mit tryCatch() oder den gesamten Aufruf von parLapply() mit tryCatch(), um Fehler kontrolliert zu behandeln.
library(parallel)
cl <- makeCluster(2)
# Wrap risky code inside the worker function
safe_log <- function(x) {
tryCatch(
log(x),
warning = function(w) NA_real_,
error = function(e) NA_real_
)
}
clusterExport(cl, 'safe_log')
# -1 produces NaN warning, 'a' produces an error
input <- list(4, 9, -1, 'a', 16)
result <- parLapply(cl, input, safe_log)
cat(unlist(result), '\n') # 1.386 2.197 NaN NA 2.773
stopCluster(cl)Praktisches Muster für parallele Verarbeitung
Hier ist ein vollständiger, idiomatischer Ablauf für parallele Verarbeitung: Kerne erkennen, Cluster erstellen, Abhängigkeiten exportieren, Berechnung ausführen, Ergebnisse sammeln und den Cluster immer beenden – auch wenn ein Fehler auftritt – mithilfe von on.exit().
library(parallel)
run_parallel <- function(data, fn, n_workers = detectCores() - 1) {
cl <- makeCluster(n_workers)
on.exit(stopCluster(cl)) # guaranteed cleanup
clusterExport(cl, 'fn', envir = environment())
result <- parLapply(cl, data, fn)
result
}
# Example: bootstrap mean estimation
samples <- lapply(1:100, function(i) rnorm(50, mean = 5, sd = 2))
means <- run_parallel(samples, mean)
cat('Grand mean:', round(mean(unlist(means)), 3), '\n')
cat('95% CI: [',
round(quantile(unlist(means), 0.025), 3), ',',
round(quantile(unlist(means), 0.975), 3), ']\n')Schnelltest
Welche Funktion sollten Sie verwenden, um sicherzustellen, dass stopCluster(cl) auch dann aufgerufen wird, wenn in Ihrem parallelen Code ein Fehler auftritt?
Zusammenfassung: Paket parallel
Wichtigste Erkenntnisse:
detectCores()meldet die verfügbaren Kerne; verwenden SiedetectCores() - 1für die ClustergrößemakeCluster(n)/stopCluster(cl)verwalten den Lebenszyklus der WorkerclusterExport()kopiert Objekte;clusterEvalQ()führt Setup-Code auf den Workern ausparLapply()/parSapply()sind plattformübergreifende parallele Iterationsfunktionenmclapply()ist nur für Unix verfügbar, startet aber dank Forking schneller- Verwenden Sie
on.exit(stopCluster(cl)), um die Bereinigung zu garantieren - Parallele Verarbeitung lohnt sich nur bei rechenintensiven Aufgaben
# Minimal reproducible parallel pattern
library(parallel)
cl <- makeCluster(max(1, detectCores() - 1))
on.exit(stopCluster(cl))
clusterSetRNGStream(cl, iseed = 42)
result <- parSapply(cl, 1:8, function(x) x^2 + rnorm(1, 0, 0.1))
cat(round(result, 2), '\n')Häufig gestellte Fragen
Ist die Lektion „Paket parallel und detectCores()“ kostenlos?
Ja — der vollständige Text von „Paket parallel und detectCores()“ 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 „Paket parallel und detectCores()“?
Starten Sie Fork- oder Socket-Cluster und verteilen Sie Aufgaben auf CPU-Kerne 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 1 von 4.
Wie lange dauert die Lektion „Paket parallel und detectCores()“?
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
- Paket parallel und detectCores()
- Das Framework future
- furrr: Parallele purrr-Operationen
- Parallelen Code debuggen und Lasten verteilen