furrr: parallelle purrr-bewerkingen
Vervang map() rechtstreeks door future_map() om direct te parallelliseren.
furrr: parallelle purrr-bewerkingen is een gratis R Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject R Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus R Academy bevat in totaal 4 lessen.
furrr: parallelle purrr
furrr (future + purrr) biedt directe parallelle vervangers voor alle purrr::map_*()-functies. Vervang eenvoudig map() door future_map() nadat je een plan() hebt ingesteld; je pijplijn wordt dan parallel uitgevoerd zonder structurele wijzigingen.
library(furrr)
library(future)
# Set up parallel workers
plan(multisession, workers = 4)
# Sequential (purrr)
# result <- purrr::map(1:8, ~.x^2)
# Parallel (furrr) — identical API
result <- future_map(1:8, ~.x^2)
cat(unlist(result), '\n') # 1 4 9 16 25 36 49 64
plan(sequential)plan(multisession, workers = 4)
Door workers expliciet in plan() op te geven, beperk je het aantal parallelle R-sessies. Voor taken die de processor intensief gebruiken, is workers = parallel::detectCores() - 1 een gebruikelijke conventie, zodat één processorkern beschikbaar blijft voor het besturingssysteem.
library(furrr)
library(future)
library(parallel)
# Explicit worker count
n_workers <- max(1, detectCores() - 1)
plan(multisession, workers = n_workers)
cat('Active workers:', nbrOfWorkers(), '\n')
cat('Strategy:', class(plan())[1], '\n')
# Run a simple parallel task
results <- future_map_dbl(1:8, ~sqrt(.x))
cat(round(results, 3), '\n')
plan(sequential)future_map_dbl en varianten met een vast type
Net als purrr biedt furrr varianten met een vast type: future_map_dbl(), future_map_int(), future_map_chr() en future_map_lgl(). Ze dwingen het retourtype af en geven een atomair vector terug in plaats van een lijst.
library(furrr)
plan(multisession, workers = 2)
# Returns a numeric vector
square_roots <- future_map_dbl(1:6, ~sqrt(.x))
cat('dbl:', round(square_roots, 3), '\n')
# Returns an integer vector
counts <- future_map_int(list('hello', 'world', 'R'), nchar)
cat('int:', counts, '\n')
# Returns a character vector
formatted <- future_map_chr(c(1.23, 4.56, 7.89), ~sprintf('%.1f', .x))
cat('chr:', formatted, '\n')
# Returns a logical vector
positive <- future_map_lgl(-3:3, ~.x > 0)
cat('lgl:', positive, '\n')
plan(sequential)future_map2: toewijzing met twee invoeren
future_map2(.x, .y, .f) doorloopt twee lijsten of vectoren parallel en geeft overeenkomstige paren door aan de functie. Dit is het parallelle equivalent van purrr::map2().
library(furrr)
plan(multisession, workers = 2)
# Simulate different sample sizes and means
sizes <- c(100, 200, 300, 400)
means <- c(0, 5, -3, 10)
# future_map2 passes each (n, mu) pair to rnorm
samples <- future_map2(sizes, means, ~rnorm(.x, mean = .y))
# Verify: each element has the expected length and approximate mean
for (i in seq_along(samples)) {
cat('n=', sizes[i], 'target_mean=', means[i],
'observed_mean=', round(mean(samples[[i]]), 2), '\n')
}
plan(sequential)furrr_options: gedrag bepalen
furrr_options() wordt als het argument .options doorgegeven aan elke aanroep van future_map_*(). De belangrijkste instelling is seed = TRUE, waarmee de parallelle RNG van L'Ecuyer-CMRG wordt geactiveerd voor reproduceerbare willekeurige getallen op verschillende workers.
library(furrr)
plan(multisession, workers = 2)
# Without seed: results differ each run
r1 <- future_map_dbl(1:4, ~rnorm(1))
r2 <- future_map_dbl(1:4, ~rnorm(1))
cat('Without seed - same?', identical(r1, r2), '\n')
# With seed: reproducible
opts <- furrr_options(seed = 42L)
r3 <- future_map_dbl(1:4, ~rnorm(1), .options = opts)
r4 <- future_map_dbl(1:4, ~rnorm(1), .options = opts)
cat('With seed - same?', identical(r3, r4), '\n')
cat('r3:', round(r3, 4), '\n')
plan(sequential)Voortgang rapporteren met progressr
Het pakket progressr werkt samen met furrr om tijdens parallelle uitvoering voortgangsbalken weer te geven. Wikkel je code in with_progress() en maak binnen de toegepaste functie een progressor().
library(furrr)
library(progressr)
plan(multisession, workers = 2)
# Enable progress reporting
handlers(global = TRUE) # show progress in console
with_progress({
p <- progressor(steps = 8)
results <- future_map(1:8, function(i) {
p() # increment the progress bar
Sys.sleep(0.1)
i^2
})
})
cat('Results:', unlist(results), '\n')
plan(sequential)Globale variabelen in furrr
Net als het pakket future detecteert furrr automatisch globale variabelen waarnaar binnen .f wordt verwezen. Je kunt dit overschrijven met furrr_options(globals = c('var1', 'var2')) om precies op te geven welke globale variabelen moeten worden verzonden. Zo beperk je de overhead voor grote omgevingen.
library(furrr)
plan(multisession, workers = 2)
# Global variables auto-detected
scale_factor <- 10
offset <- 5
result <- future_map_dbl(
1:6,
function(x) x * scale_factor + offset
)
cat(result, '\n') # 15 25 35 45 55 65
# Explicit globals control
opts <- furrr_options(
globals = c('scale_factor', 'offset'),
seed = FALSE
)
result2 <- future_map_dbl(
1:6,
function(x) x * scale_factor + offset,
.options = opts
)
cat('Manual globals:', result2, '\n')
plan(sequential)future_pmap: toewijzing met meerdere argumenten
future_pmap(.l, .f) is de parallelle versie van purrr::pmap(). De functie accepteert een lijst met vectoren/lijsten en geeft overeenkomstige rijen door als benoemde argumenten, zodat parallel rekenen over meerdere parametercombinaties mogelijk wordt.
library(furrr)
plan(multisession, workers = 2)
# Parameter grid
params <- list(
n = c(50, 100, 150, 200),
mean = c(0, 1, 2, 3),
sd = c(1, 2, 1, 0.5)
)
# future_pmap passes each row as arguments to rnorm
samples <- future_pmap(params, function(n, mean, sd) {
x <- rnorm(n, mean = mean, sd = sd)
c(obs_mean = round(mean(x), 3), obs_sd = round(sd(x), 3))
})
for (i in seq_along(samples)) {
cat('n=', params$n[i], ':', samples[[i]], '\n')
}
plan(sequential)furrr vergelijken met purrr
De voordelen van parallellisme groeien mee met de zwaarte van de taak. Bij triviale bewerkingen (x^2) overheerst de overhead en is sequentiële uitvoering sneller. Bij zware taken, zoals het fitten van veel modellen, bespaart parallelle uitvoering aanzienlijk veel tijd.
library(furrr)
library(purrr)
plan(multisession, workers = 4)
# Heavy task: bootstrap a linear model 100 times
heavy <- function(i) {
n <- 200
df <- data.frame(x = rnorm(n), y = rnorm(n))
coef(lm(y ~ x, data = df))[['x']]
}
seq_time <- system.time(map_dbl(1:40, heavy))[['elapsed']]
par_time <- system.time(
future_map_dbl(1:40, heavy, .options = furrr_options(seed = TRUE))
)[['elapsed']]
cat('Sequential:', round(seq_time, 2), 's\n')
cat('Parallel: ', round(par_time, 2), 's\n')
cat('Speedup: ', round(seq_time / max(par_time, 0.001), 2), 'x\n')
plan(sequential)Foutafhandeling in future_map
Als de berekening van een element een fout veroorzaakt, stopt future_map() en gooit de functie de fout opnieuw. Gebruik purrr::safely() of purrr::possibly() als wikkelfunctie rond je functie om ondanks fouten door te gaan.
library(furrr)
library(purrr)
plan(multisession, workers = 2)
# Wrap with safely() to capture errors as results
safe_log <- safely(log, otherwise = NA_real_)
inputs <- list(10, -1, 100, 'text', 0.5)
results <- future_map(inputs, safe_log)
for (i in seq_along(results)) {
if (is.null(results[[i]]$error)) {
cat('Input', i, '-> result:', round(results[[i]]$result, 4), '\n')
} else {
cat('Input', i, '-> error:', conditionMessage(results[[i]]$error), '\n')
}
}
plan(sequential)Praktische furrr-pijplijn
Hier is een complete pijplijn van begin tot eind: gegevens laden, meerdere modellen parallel fitten met reproduceerbare seeds, prestatiemetrieken ophalen en het beste model selecteren — allemaal met de furrr-werkwijze.
library(furrr)
library(purrr)
plan(multisession, workers = 4)
set.seed(1)
n <- 300
df <- data.frame(
x1 = rnorm(n), x2 = rnorm(n), x3 = rnorm(n),
y = rnorm(n)
)
formulas <- list(
y ~ x1,
y ~ x1 + x2,
y ~ x1 + x2 + x3,
y ~ x1 * x2
)
# Fit all models in parallel
models <- future_map(
formulas,
~lm(.x, data = df),
.options = furrr_options(seed = FALSE)
)
# Extract adjusted R-squared
adj_r2 <- map_dbl(models, ~summary(.x)$adj.r.squared)
cat('Adjusted R2 per model:',
paste(round(adj_r2, 4), collapse = ', '), '\n')
cat('Best model:', which.max(adj_r2), '\n')
plan(sequential)Korte controle
Je wilt reproduceerbare willekeurige getallen bij parallelle aanroepen van future_map(). Welke instelling van furrr_options() maakt dit mogelijk?
Samenvatting: het furrr-pakket
Belangrijkste punten:
furrris een directe parallelle vervanger voorpurrr— vervangmapeenvoudig doorfuture_map- Stel eerst een backend in met
plan(multisession, workers = n) - Varianten met een vast type:
future_map_dbl(),future_map_int(),future_map_chr() - Gebruik
future_map2()enfuture_pmap()voor parallelle toewijzing met meerdere invoeren - Gebruik
furrr_options(seed = 42L)voor reproduceerbare parallelle RNG - Integreer
progressrvoor voortgangsbalken tijdens langdurige parallelle taken - Gebruik
purrr::safely()binnenfuture_map()voor pijplijnen die bestand zijn tegen fouten
library(furrr)
plan(multisession, workers = 2)
results <- future_map_dbl(
1:6,
~.x^2 + sqrt(.x),
.options = furrr_options(seed = TRUE)
)
cat(round(results, 3), '\n')
plan(sequential)Leer R met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 43
- Lessen
- 159
Veelgestelde vragen
Is de les “furrr: parallelle purrr-bewerkingen” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad R Academy, waaronder “furrr: parallelle purrr-bewerkingen”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus R Academy bevat in totaal 4 lessen.
Wat leer ik in “furrr: parallelle purrr-bewerkingen”?
Vervang map() rechtstreeks door future_map() om direct te parallelliseren. Je oefent met R Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met R Academy te beginnen?
Ervaring vooraf is niet nodig. R Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.
Hoe lang duurt de les “furrr: parallelle purrr-bewerkingen”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over R Academy?
Ja. Elke les over R Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Pakket parallel en detectCores()
- Het future-framework
- furrr: parallelle purrr-bewerkingen
- Parallelle code debuggen en load balancing