Al desplegar aplicaciones en Docker que utilizan rpy2 para invocar funciones R con cálculos paralelos, se pueden encontrar bloqueos enesperados. Este artículo detalla un caso específico con la biblioteca WaveICA y proporciona una solución.
En un entorno donde Gradio se usa para construir una interfaz, ciertos algoritmos requieren R. Para mantener la consistencia entre desarrollo y producción, se emplea Docker. Sin embargo, al ejecutar una función R que utiliza mclapply para paralelismo, el proceso se detiene sin consumir CPU y la memoria no se libera. Al interrumpir con Ctrl+C, aparece el error:
*** longjmp causes uninitialized stack frame ***: terminated
Las búsquedas iniciales no arrojarno soluciones. Se probaron variaciones como cambiar imágenes Docker (de r-base a rocker/r-ver o ubuntu:22.04 con configuración manual), actualizar versiones de rpy2 o Gradio, y revisar problemas de kernel del host. Curiosamente, ejecutar el mismo código R directamente fuera de Docker funcionaba sin errores.
El avance llegó al examinar el código fuente de la función WaveICA_2.0. Se aisló un bucle que usa mclapply para ajustar modelos GAM en paralelo:
nivel <- 1
datos_wave_ICA <- list()
for (i in 1:nivel) {
cat(paste("######### ICA", i, "#############\n"))
coef_data <- coeficientes[[i]]
coef_ICA <- unbiased_stICA(X=t(coef_data), k=K, alpha)
B <- coef_ICA$B
A <- coef_ICA$A
B <- as.data.frame(B)
# Ejecución paralela con mclapply
correlaciones <- mclapply(B, function(col) {
modelo <- gam(col ~ s(Orden_Inyeccion))
resumen <- summary(modelo)
r_cuadrado <- resumen$r.sq
return(r_cuadrado)
})
correlaciones <- unlist(correlaciones)
etiquetas <- which(correlaciones >= Corte)
B_nuevo <- B[, etiquetas, drop=FALSE]
A_nuevo <- A[, etiquetas, drop=FALSE]
Xn <- datos_coef - t(A_nuevo %*% t(B_nuevo))
datos_wave_ICA[[i]] <- Xn
}
La sugerencia clave fue reemplazar mclapply por lapply para evitar el paralelismo problemático en el contexto de rpy2 y Docker. La versión corregida del bucle sería:
correlaciones <- lapply(B, function(col) {
modelo <- gam(col ~ s(Orden_Inyeccion))
resumen <- summary(modelo)
r_cuadrado <- resumen$r.sq
return(r_cuadrado)
})
Al modificar directamente la función R para usar lapply en lugar de mclapply, el problema se resolvió. Esto sugiere que la interacción entre rpy2, Docker y el multithreading de R puede causar bloqueos, y que deshabilitar el paralelismo dentro del código R invocado desde Python es una solución viable.