GOOGLE ADS

domingo, 17 de abril de 2022

Paralelice un bucle for dentro de un R-script usando slurm

Tengo miles de marcos de datos y quiero paralelizar su análisis en slurm. Aquí estoy proporcionando un ejemplo simplificado:

Tengo un Rscript al que llamo: test.R

test.R contains these commands:

library(tidyverse)
df1 <- tibble(col1=c(1,2,3),col2=c(4,5,6))
df2 <- tibble(col1=c(7,8,9),col2=c(10,11,12))
files <- list(df1,df2)
for(i in 1:length(files)){
df3 <- as.data.frame(files[1]) %>%
summarise(across(everything(), list(mean=mean,sd=sd)))

write.table(df3, paste0("df",i))
}

Creado el 2022-04-15 por el paquete reprex (v2.0.1)

Quiero paralelizar el ciclo for y analizar cada marco de datos como un trabajo separado. Cualquier ayuda, orientación y tutoriales son apreciados.

¿Ayudaría el comando de matriz?

#!/bin/bash
### Job name
#SBATCH --job-name=parallel
#SBATCH --ntasks=1
#SBATCH --nodes=1
#SBATCH --time=10:00:00
#SBATCH --mem=16G
#SBATCH --array=1-2
module load R/4.1.3
Rscript test.R $SLURM_ARRAY_TASK_ID


Solución del problema

Si los marcos de datos se almacenan en archivos separados con identificadores numéricos, puede crear una lista de estos archivos como una variable bash y enviar la matriz de números de identificación en su comando sbatch. Se $SLURM_ARRAY_TASK_IDpuede usar como un argumento de entrada para que su código R apunte al archivo de ese marco de datos específico.

Solo para el siguiente ejemplo, supongamos que los marcos de datos se almacenan como archivos.csv con los nombres dataframe_1.csv, dataframe_2.csv,... dataframe_100. Su comando para ejecutar los trabajos paralelos sería algo como esto:

sbatch -a 1-100 jobscript.sh

Y jobscript.shse parecería a su código de muestra en su pregunta:

#!/bin/bash
### Job name
#SBATCH --job-name=parallel
#SBATCH --nodes=1
#SBATCH --time=10:00:00
#SBATCH --mem=16G
module load R/4.1.3
Rscript test.R "dataframe_${SLURM_ARRAY_TASK_ID}.csv"

Note that you may need to break up these sbatch jobs to allow for processing thousands of dataframes. If a file name has four digits in its numeric ID, you can prepend the first digit before the ${SLURM_ARRAY_TASK_ID} in the last line of the jobscript.sh:

Rscript test.R "dataframe_1${SLURM_ARRAY_TASK_ID}.csv"

o si quiere evitar hacer múltiples scripts, pase ese número como argumento a jobscript.sh:

sbatch -a 1-100 jobscript.sh 1

#!/bin/bash
### Job name
#SBATCH --job-name=parallel
#SBATCH --nodes=1
#SBATCH --time=10:00:00
#SBATCH --mem=16G
prepend=$1
module load R/4.1.3
Rscript test.R "dataframe_${prepend}${SLURM_ARRAY_TASK_ID}.csv"

No hay comentarios:

Publicar un comentario

Regla de Firestore para acceder a la generación de subcolección Permisos faltantes o insuficientes

Tengo problemas con las reglas de Firestore para permitir el acceso a algunos recursos en una subcolección. Tengo algunos requests document...