Pakken parallel og detectCores()
Start fork- eller socket-klynger, og fordel arbejdet på tværs af CPU-kerner.
Pakken parallel og detectCores() er en gratis R Academy-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i R Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. R Academy-kurset indeholder 4 lektioner i alt.
Hvorfor parallel beregning?
Moderne computere har flere CPU-kerner. Som standard kører R på én kerne, mens resten står uvirksomme. Pakken parallel (indbygget i R) lader dig udnytte alle kerner for at gøre gentagne beregninger hurtigere.
# 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 og stopCluster
makeCluster(n) starter n arbejdsprocesser. Kald altid stopCluster(cl), når du er færdig, for at frigive ressourcer. En almindelig konvention er at bruge detectCores() - 1 for at reservere én kerne til operativsystemet.
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: Deling af variabler
Arbejdsprocesser har deres eget hukommelsesområde og kan ikke se dit globale miljø. Brug clusterExport(cl, varlist) til at kopiere navngivne objekter fra masterprocessen til alle arbejdere.
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: Kørsel af opsætningskode
clusterEvalQ(cl, expr) evaluerer et udtryk på hver arbejder – det er nyttigt til at indlæse pakker eller hente hjælpefiler på alle noder, før hovedberegningen begynder.
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: Parallel lapply
parLapply(cl, X, FUN) er den parallelle pendant til lapply(). Den fordeler elementer fra X på arbejderne og samler resultaterne som en liste. Den fungerer på alle platforme (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: Forenklede resultater
parSapply(cl, X, FUN) er den parallelle version af sapply(). Den forenkler automatisk resultatet til en vektor eller matrix, når det er muligt, hvilket gør den praktisk, når din funktion returnerer en skalar.
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: Parallelitet baseret på forgrening
mclapply() bruger forgrening – den kopierer den aktuelle R-proces i stedet for at starte nye, hvilket gør opstarten hurtigere og giver arbejderne implicit adgang til forældremiljøet. Den fungerer dog kun på Unix/macOS, ikke på 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')
}Benchmarking af sekventiel og parallel kørsel
Parallelitet har et overhead: opstart af klyngen, serialisering af data og kommunikation mellem processer tager alt sammen tid. Det kan kun betale sig, når beregningen pr. element er tilstrækkeligt krævende til at opveje dette overhead.
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)Initialisering af RNG i parallel kode
Generering af tilfældige tal parallelt er vanskeligt – hver arbejder skal have en uafhængig, reproducerbar strøm. Brug clusterSetRNGStream(cl, seed) med generatoren L'Ecuyer-CMRG for at få reproducerbar tilfældighed i parallel kode.
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)Fejlhåndtering i klynger
Hvis en arbejder udløser en fejl, kaster parLapply() den videre i masterprocessen. Pak kald ind i tryCatch() i funktionen, eller brug tryCatch() omkring hele kaldet til parLapply() for at håndtere fejl på en kontrolleret måde.
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)Praktisk mønster til parallel kode
Her er en komplet, idiomatisk arbejdsgang til parallel kode: find antallet af kerner, opret en klynge, eksportér afhængigheder, kør beregningen, indsaml resultaterne, og stop altid klyngen – også hvis der opstår en fejl – ved hjælp af 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')Hurtigt tjek
Hvilken funktion skal du bruge for at sikre, at stopCluster(cl) kaldes, selv hvis der opstår en fejl i din parallelle kode?
Opsamling: pakken parallel
Vigtigste pointer:
detectCores()rapporterer tilgængelige kerner; brugdetectCores() - 1som klyngestørrelsemakeCluster(n)/stopCluster(cl)håndterer arbejdernes levetidclusterExport()kopierer objekter, ogclusterEvalQ()kører opsætningskode på arbejderneparLapply()/parSapply()er parallelle iteratorer på tværs af platformemclapply()fungerer kun på Unix, men starter hurtigere på grund af forgrening- Brug
on.exit(stopCluster(cl))for at sikre oprydning - Parallelitet kan kun betale sig ved beregningstunge opgaver
# 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')Lær R med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 43
- Lektioner
- 159
Ofte stillede spørgsmål
Er lektionen “Pakken parallel og detectCores()” gratis?
Ja — alle 3 lektioner i læringssporet R Academy, inklusive “Pakken parallel og detectCores()”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. R Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Pakken parallel og detectCores()”?
Start fork- eller socket-klynger, og fordel arbejdet på tværs af CPU-kerner. Du øver dig i R Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på R Academy?
Der kræves ingen tidligere erfaring. R Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “Pakken parallel og detectCores()”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne R Academy-lektion?
Ja. Alle R Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Pakken parallel og detectCores()
- Fremtid-frameworket
- furrr: Parallelle purrr-operationer
- Debugging og load balancing af parallel kode