Futureverse P2P:
Peer-to-Peer Parallelization in R
- Share compute among friends across the world
Henrik Bengtsson
University of California, San Francisco
R Foundation, R Consortium
@HenrikBengtsson
![The hexlogo of the future package. A left-facing arrow with the text future underneath - both in bold style filled with yellow-to-orange vertical gradient. The background is dark blue with teeny star-shaped symbols in distance resembling looking deep out in the universe. The hexlogo is surrounded by a light-blue border.]()
![Illustration of three people working on laptops, positioned below a large globe with location markers connected by lines, representing global online collaboration.]()
useR! 2025, Durham, NC, USA (2025-08-10)
Future … what?
A future-value assignment:
f <- future({ 1 + 2 })
a <- value(f)
x <- 1:10
b <- slow_sum(x)
x <- 1:10
f <- future({ slow_sum(x) })
b <- value(f)
Future … why? (bc enables parallel processing)
Two calculations:
x_a <- 1:10
x_b <- 11:20
a <- slow_sum(x_a) # 1 min
b <- slow_sum(x_b) # 1 min
c <- a + b
Two futures:
x_a <- 1:10
x_b <- 11:20
f_a <- future( slow_sum(x_a) ) # 0 sec
f_b <- future( slow_sum(x_b) ) # 0 sec
a <- value(f_a) # 1 min
b <- value(f_b)
c <- a + b
=> futures are the core building block for parallel processing
Futureverse allows you to stick with your favorite coding style
Parallel alternatives to traditional, sequential functions:
ys <- lapply(xs, slow_sum) # base R
ys <- future_lapply(xs, slow_sum) # {future.apply}
ys <- map(xs, slow_sum) # {purrr}
ys <- future_map(xs, slow_sum) # {furrr}
plan(multisession)
plan(future.callr::callr)
plan(future.mirai::mirai_multisession)
plan(cluster, workers = c("n1", "desktop", "server.myuniv.org"))
plan(future.batchtools::batchtools_slurm)
Ten-Year Anniversary (future 0.6.0 released June 2015)
![Hexagon-shaped sign with the word 'FUTURE' in bold orange letters and the URL futureverse.org below, surrounded by a background of blue balloons.]()
future logo: Dan LaBar, ggplot2 logo balloon wall: Greg Swinehart & Hadley Wickham
useR! 2016 at Stanford, CA, USA
useR! 2016 at Stanford, CA, USA
useR! 2016 at Stanford, CA, USA
useR! 2016 at Stanford, CA, USA
useR! 2016 at Stanford, CA, USA
future.p2p: sharing compute among friends - it’s easy!
![Illustration of three people working on laptops, positioned below a large globe with location markers connected by lines, representing global online collaboration.]()
A P2P cluster has two components
Message Board
Used to announce futures and offers to do work
(centralized; lightweight - only metadata)
P2P file-transfer protocol
Used to send futures to workers and receive results
(peer-to-peer; full-size data transfers)
To join a P2P cluster you need an account
All P2P cluster users need a pico.sh account to access the message board:
1. ssh-keygen
![Terminal screenshot showing ssh-keygen generating a new ed25519 SSH key pair for user carol, including prompts for file location and passphrase, and displaying the key fingerprint and randomart image.]()
2. ssh pico.sh
=> pick a username
![Terminal interface for pico.sh signup, showing welcome message, account creation instructions, a getting started link, the user's SSH public key fingerprint, and an input field with the username 'carol' entered.]()
That’s it!
Alice hosts a P2P cluster
Alice sets up P2P cluster and gives ‘bob’ and ‘carol’ access:
[alice]> future.p2p::host_cluster("alice/friends", users=c("bob", "carol"))
This is basically setting up a shared message board.
Q. What happens if Bob tries to use the P2P cluster?
[bob]> plan(future.p2p::cluster, cluster = "alice/friends")
[bob]> y <- future_lapply(xs, slow_sum)
Nothing - it will get stuck! Why?
Contributing P2P workers is easy!
[alice]> future.p2p::worker("alice/friends")
[ bob ]> future.p2p::worker("alice/friends")
[carol]> future.p2p::worker("alice/friends")
[bob]> plan(future.p2p::cluster, cluster = "alice/friends")
[bob]> y <- future_lapply(xs, slow_sum)
=> Processed on three P2P workers
You can set it up from the terminal
Setting up a P2P cluster:
{alice}$ Rscript -e future.p2p::host_cluster --cluster=alice/friends \
--users=bob,carol
Starting P2P workers:
{alice}$ Rscript -e future.p2p::worker --cluster=alice/friends &
{alice}$ Rscript -e future.p2p::worker --cluster=alice/friends &
{ bob }$ Rscript -e future.p2p::worker --cluster=alice/friends &
{carol}$ Rscript -e future.p2p::worker --cluster=alice/friends &
{carol}$ Rscript -e future.p2p::worker --cluster=alice/friends &
{carol}$ Rscript -e future.p2p::worker --cluster=alice/friends &
=> A shared P2P cluster with 6 workers. More can be added at any time!
High latency but also high throughput
-
High latency:
round-trip takes time, because p2p file transfers take time
Example: 1+2
takes 2-10 seconds to send, evaluate, and return
Just a prototype, so this will be improved
-
High throughput:
⚠️ P2P computing requires mutual trust ⚠️
What if?
Some technical mitigations:
=> I encourage work on these topics - it’s challenging, but important
The Future is bright
… and fabulous
Stay tuned for exciting Futureverse improvements
On the horizon
In the near future
- If you think furrr and future.apply are neat - just wait!
Thank you and may the future be with you!
![Hexagon-shaped logo with a light blue border, dark blue starry background, and the word 'FUTURIZE' in bold orange gradient letters beneath an upward-pointing arrow symbol.]()