Nested Futures Use More Memory Than They Should
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 35/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Estancado
- Stack tecnológico
- r
Línea de trabajo
No se nombran archivos ni pruebas del repositorio. Empieza reproduciendo los benchmarks del plan secuencial con los ejemplos anidados de future_lapply y future_map; después, sigue los puntos de entrada de future y furrr implicados en la evaluación anidada. El trabajo estará terminado cuando se identifique por qué las llamadas anidadas asignan memoria en exceso y se verifique que el uso de memoria ya no se dispara mientras los resultados siguen siendo idénticos.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
I've been running code with nested loops that keeps running into issues with memory usage and I have been trying to come up with a small example that potentially shows the problem. In the example I am just taking a random square matrix and creating a list of the columns. Obviously you wouldn't use a double loop to do this in R but it is hopefully a simple and clear example that shows when using purrr the double loop doesn't increase memory usage while with furrr and future.apply the memory usage explodes.
library(bench)
library(furrr)
library(future.apply)
library(purrr)
# purrr
single_loop <- function(x, n) {
map(1:n, ~ x[, .x])
}
# future.apply
single_loop_a <- function(x, n) {
future_lapply(1:n, FUN = function(i) x[, i])
}
# furrr
single_loop_f <- function(x, n) {
future_map(1:n, ~ x[, .x])
}
# purrr
inner_loop <- function(i, n, x = x) {
map_dbl(1:n, ~ x[.x, i])
}
outer_loop <- function(x, n) {
map(1:n, ~ inner_loop(.x, n, x = x))
}
# future.apply
inner_loop_a <- function(i, n, x = x) {
future_sapply(1:n, FUN = function(j) x[j, i])
}
outer_loop_a <- function(x, n) {
future_lapply(1:n, FUN = function(i) inner_loop_a(i, n, x))
}
# furrr
inner_loop_f <- function(i, n, x = x) {
future_map_dbl(1:n, ~ x[.x, i])
}
outer_loop_f <- function(x, n) {
future_map(1:n, ~ inner_loop_f(.x, n, x = x))
}
n <- 100
x <- matrix(rnorm(n * n), nrow = n)
identical(single_loop(x, n), single_loop_f(x, n))
identical(single_loop(x, n), single_loop_a(x, n))
identical(single_loop(x, n), outer_loop(x, n))
identical(single_loop(x, n), outer_loop_a(x, n))
identical(single_loop(x, n), outer_loop_f(x, n))
# All return TRUE
plan(sequential)
# With a single loop memory usage is similar
bench::mark(single_loop(x, n))$mem_alloc
# 127KB
bench::mark(single_loop_a(x, n))$mem_alloc
# 243KB
bench::mark(single_loop_f(x, n))$mem_alloc
# 340KB
# With a double loop memory usage remains similar for purrr, but explodes
# on the other two
bench::mark(outer_loop(x, n))$mem_alloc
# 83.6KB
bench::mark(outer_loop_a(x, n))$mem_alloc
# 11.8MB
bench::mark(outer_loop_f(x, n))$mem_alloc
# 21.1MB
# Try again with a larger matrix
n <- 5000
x <- matrix(rnorm(n * n), nrow = n)
bench::mark(single_loop(x, n))$mem_alloc
287MB
bench::mark(single_loop_a(x, n))$mem_alloc
287MB
bench::mark(single_loop_f(x, n))$mem_alloc
287MB
bench::mark(outer_loop(x, n))$mem_alloc
191MB
bench::mark(outer_loop_a(x, n))$mem_alloc
2.88GB
bench::mark(outer_loop_f(x, n))$mem_alloc
1.57GB
As you can see, using the double loop actually decreases memory usage for purrr, although it stays very similar, but causes memory usage to explode for furrr and future.apply. I ran this example on a 2023 MacBook, but the actual code that I am trying to fix has been running on a Linux cluster. I ran this example using furrr and future.apply because yesterday I logged a bug report about nested loops using future.callr and @HenrikBengtsson pointed out that it was only an issue with furrr. Please let me know if there is any additional information I can provide or help I can give in solving this issue and thanks for the wonderful collection of packages!
- Lenguaje dominante
- R
- Estrellas
- 1k
- Forks
- 93
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de futureverse/future
-
The first code example in the README does not workPosiblemente ocupada @sean0407 la tomó hace 3 días. Abiertobug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
futureverse/future#838 · 1 comentario · 1 reacción ·
-
Entire global environment getting passed along with user-defined (global) functions in shinyAbiertobug
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
futureverse/future#833 ·
-
feature/resources RNG
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
futureverse/future#832 ·
-
RNG
Dificultad 5/5 Más de una semana Aptitud para principiantes 38/100
futureverse/future#831 · 1 comentario ·
-
feature request
Dificultad 5/5 Más de una semana Aptitud para principiantes 30/100
futureverse/future#822 · 1 reacción ·
Todos los issues de futureverse/future
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
mlr-org/mlr3cmprsk#42 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 67/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 79/100
tidymodels/orbital#192 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 64/100
mitchelloharawild/ggtime#39 ·