0Pricing
R Academy · Lektion

Das Framework future

Nutzen Sie plan(multisession) und future() für asynchrones, portables paralleles Rechnen

Das Framework future ist eine kostenlose R Academy-Lektion auf CoddyKit. Dies ist Lektion 2 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.

Was ist das Paket future?

Das Paket future stellt eine einheitliche High-Level-API für asynchrone und parallele Programmierung in R bereit. Ein Future ist ein Platzhalter für einen Wert, der später verfügbar sein wird – möglicherweise berechnet auf einem anderen Kern oder Rechner.

library(future)

# A simple future: computation happens asynchronously
f <- future({
  Sys.sleep(0.5)  # simulate slow work
  42
})

cat('Future created, doing other work...\n')

# Retrieve the result (blocks until done)
result <- value(f)
cat('Result:', result, '\n')

plan(): Ein Backend auswählen

plan() legt die Ausführungsstrategie für alle nachfolgenden Futures fest. Die gängigsten Strategien sind sequential (Standard, ein Thread), multisession (mehrere R-Sitzungen, funktioniert überall) und multicore (Forking, nur unter Unix/macOS).

library(future)

# Default: sequential (no parallelism)
plan(sequential)
cat('Strategy:', class(plan())[1], '\n')

# Parallel with separate R sessions (works on Windows too)
plan(multisession, workers = 4)
cat('Strategy:', class(plan())[1], '\n')

# Forking (Unix/macOS only, lower overhead)
if (.Platform$OS.type != 'windows') {
  plan(multicore, workers = 4)
  cat('Strategy:', class(plan())[1], '\n')
}

# Reset to sequential
plan(sequential)

value(): Auf Ergebnisse warten

value(f) blockiert den aktuellen Prozess, bis die Berechnung des Futures abgeschlossen ist, und gibt anschließend das Ergebnis zurück. Wenn der Future einen Fehler ausgelöst hat, löst value() ihn in der aufrufenden Sitzung erneut aus.

library(future)
plan(multisession, workers = 2)

# Launch two slow tasks concurrently
f1 <- future({ Sys.sleep(0.3); sum(1:1000) })
f2 <- future({ Sys.sleep(0.3); prod(1:10) })

# Both run in parallel; total time ~ 0.3s not 0.6s
start <- proc.time()[['elapsed']]
v1 <- value(f1)
v2 <- value(f2)
elapsed <- proc.time()[['elapsed']] - start

cat('v1:', v1, ' v2:', v2, '\n')
cat('Elapsed:', round(elapsed, 2), 's\n')

plan(sequential)

Der Operator %<-%

Der Operator %<-% ist syntaktischer Zucker für future() + verzögertes value(). Er sieht wie eine gewöhnliche Zuweisung aus, aber die rechte Seite wird asynchron ausgeführt. Der Wert wird beim ersten Zugriff auf die Variable abgerufen.

library(future)
plan(multisession, workers = 2)

# %<-% starts the computation immediately in the background
x %<-% {
  Sys.sleep(0.3)
  rnorm(5, mean = 10)
}

y %<-% {
  Sys.sleep(0.3)
  runif(5, min = 1, max = 5)
}

cat('Both running in background...\n')

# Accessing x or y here blocks until ready
cat('x:', round(x, 2), '\n')
cat('y:', round(y, 2), '\n')

plan(sequential)

Automatische Erkennung globaler Variablen

Eine der leistungsfähigsten Funktionen von future ist die Erkennung globaler Variablen: Das Paket findet automatisch Variablen, auf die Ihr Future-Code in der aufrufenden Umgebung zugreift, und überträgt sie an den Worker – ein manuelles clusterExport() ist nicht erforderlich.

library(future)
plan(multisession, workers = 2)

# These globals are auto-detected and sent to the worker
threshold <- 50
multiplier <- 3

f <- future({
  x <- threshold * multiplier  # uses both globals
  x + 1
})

cat('Result:', value(f), '\n')  # 151

# Inspect which globals were identified
future_obj <- future({
  threshold + multiplier
}, lazy = TRUE)
cat('Globals found:', paste(names(future::getGlobalsAndPackages(future_obj)$globals), collapse = ', '), '\n')

plan(sequential)

future_options: Verhalten anpassen

Die future.options (aufgerufen über options() oder als Argumente von future::plan()) steuern globale Einstellungen: den maximal zulässigen Speicher pro Future, die Strategie zur Erkennung globaler Variablen und das Timeout-Verhalten.

library(future)

# Cap memory per future at 500 MB
options(future.globals.maxSize = 500 * 1024^2)  # bytes

# Disable automatic global detection (manual control)
options(future.globals.onReference = 'error')

# Inspect current settings
cat('Max globals size (MB):',
    getOption('future.globals.maxSize') / 1024^2, '\n')

# Restore defaults
options(future.globals.maxSize = 500 * 1024^2)
options(future.globals.onReference = NULL)

plan(multisession, workers = 2)

# Large object: you'd get an error if it exceeds the cap
big_vec <- 1:1e5  # small enough
f <- future(sum(big_vec))
cat('Sum:', value(f), '\n')

plan(sequential)

Verschachtelte Futures

Futures können verschachtelt werden: Ein Future kann selbst innere Futures erstellen. Standardmäßig werden innere Futures sequenziell ausgeführt, sofern Sie keinen verschachtelten Plan mit plan(list(...)) festlegen. Das ist für Parallelität auf zwei Ebenen nützlich.

library(future)

# Two-level parallelism: outer uses multisession, inner sequential
plan(list(multisession, sequential))

outer_futures <- lapply(1:3, function(i) {
  future({
    # Each outer worker runs its own sequential inner work
    inner <- lapply(1:4, function(j) i * j)
    unlist(inner)
  })
})

results <- lapply(outer_futures, value)
for (i in seq_along(results)) {
  cat('Outer', i, ':', results[[i]], '\n')
}

plan(sequential)

Fehlerbehandlung mit Futures

Wenn eine Future-Berechnung einen Fehler auslöst, löst value() ihn erneut aus. Umschließen Sie value() mit tryCatch(), um einzelne Future-Fehler zu behandeln, ohne die gesamte Pipeline anzuhalten.

library(future)
plan(multisession, workers = 2)

# This future will error
bad_future <- future(log(-1, base = 'oops'))  # invalid arg
good_future <- future(sqrt(144))

# Handle errors gracefully
bad_result <- tryCatch(
  value(bad_future),
  error = function(e) {
    cat('Caught error:', conditionMessage(e), '\n')
    NA
  }
)

good_result <- value(good_future)
cat('bad_result:', bad_result, '\n')
cat('good_result:', good_result, '\n')

plan(sequential)

Status eines Futures prüfen

resolved(f) gibt TRUE zurück, wenn ein Future ohne Blockierung abgeschlossen wurde. So können Sie den Abschluss regelmäßig prüfen und während des Wartens nützliche Arbeit erledigen, um eine nicht blockierende Abfrageschleife zu erstellen.

library(future)
plan(multisession, workers = 2)

f <- future({
  Sys.sleep(0.5)
  'done'
})

# Poll without blocking
counter <- 0
while (!resolved(f)) {
  counter <- counter + 1
  Sys.sleep(0.1)
  cat('Polling... (', counter, ')\n')
}

cat('Future resolved! Result:', value(f), '\n')
cat('Polled', counter, 'times\n')

plan(sequential)

future mit lapply kombinieren

Kombinieren Sie lapply() mit future(), um N Aufgaben zu verteilen, und lapply() mit value(), um die Ergebnisse zu sammeln. Dieses Muster gibt Ihnen explizite Kontrolle darüber, wann die einzelnen Futures starten.

library(future)
plan(multisession, workers = 4)

# Fan out: create all futures
params <- list(
  list(n = 1000, mean = 0),
  list(n = 1000, mean = 5),
  list(n = 1000, mean = 10),
  list(n = 1000, mean = -3)
)

futures <- lapply(params, function(p) {
  future({
    x <- rnorm(p$n, mean = p$mean)
    list(mean = mean(x), sd = sd(x))
  })
})

# Fan in: collect results
results <- lapply(futures, value)
for (i in seq_along(results)) {
  cat('Param mean', params[[i]]$mean,
      '-> observed mean:', round(results[[i]]$mean, 3), '\n')
}

plan(sequential)

Praktischer Anwendungsfall: Auswertung von CV-Folds

Die Kreuzvalidierung ist ein triviales Parallelisierungsproblem: Jeder Fold ist unabhängig. Mit Futures können Sie alle K Folds gleichzeitig auswerten und dadurch die verstrichene Zeit für aufwendige Modelle deutlich reduzieren.

library(future)
plan(multisession, workers = 4)

set.seed(42)
data <- data.frame(x = rnorm(200), y = rnorm(200))
fold_ids <- sample(rep(1:4, 50))

# Launch all folds in parallel
fold_futures <- lapply(1:4, function(k) {
  future({
    train <- data[fold_ids != k, ]
    test  <- data[fold_ids == k, ]
    fit   <- lm(y ~ x, data = train)
    preds <- predict(fit, newdata = test)
    rmse  <- sqrt(mean((test$y - preds)^2))
    rmse
  })
})

rmses <- unlist(lapply(fold_futures, value))
cat('Fold RMSEs:', round(rmses, 4), '\n')
cat('Mean RMSE:', round(mean(rmses), 4), '\n')

plan(sequential)

Kurze Überprüfung

Sie möchten parallelen Code ausführen, der sowohl unter Windows als auch unter macOS funktioniert. Welche plan()-Strategie sollten Sie wählen?

Zusammenfassung: future-Framework

Wichtigste Erkenntnisse:

  • future({expr}) führt einen Ausdruck asynchron aus; value(f) ruft das Ergebnis ab
  • %<-% ist syntaktischer Zucker – eine Zuweisung mit verzögerter Future-Auswertung
  • plan(multisession) für plattformübergreifende Nutzung; plan(multicore) für Forking unter Unix/macOS
  • Globale Variablen werden automatisch erkannt und an Worker übertragen – clusterExport() ist nicht erforderlich
  • resolved(f) prüft den Abschluss, ohne zu blockieren
  • Umschließen Sie value() mit tryCatch(), um robuste Pipelines zu erstellen
  • Rufen Sie nach Abschluss immer plan(sequential) oder plan() auf, um den Zustand zurückzusetzen
library(future)
plan(multisession, workers = 2)

# Concise pattern: fan-out then fan-in
task <- function(i) future({ i^2 + i })
results <- lapply(1:6, task)
cat(unlist(lapply(results, value)), '\n')  # 2 6 12 20 30 42

plan(sequential)

Häufig gestellte Fragen

Ist die Lektion „Das Framework future“ kostenlos?

Ja — der vollständige Text von „Das Framework future“ 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 „Das Framework future“?

Nutzen Sie plan(multisession) und future() für asynchrones, portables paralleles Rechnen 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 2 von 4.

Wie lange dauert die Lektion „Das Framework future“?

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

  1. Paket parallel und detectCores()
  2. Das Framework future
  3. furrr: Parallele purrr-Operationen
  4. Parallelen Code debuggen und Lasten verteilen
← Zurück zu R Academy