Pregunta aplicar con objetos grandes: "la serialización es demasiado grande para almacenarla en un vector sin formato"


Sigo golpeando un problema con el multicore paquete y objetos grandes. La idea básica es que estoy usando una función de Bioconductor (readBamGappedAlignments) para leer en objetos grandes. Tengo un vector de caracteres de nombres de archivos, y he estado usando mclapply para recorrer los archivos y leerlos en una lista. La función se ve más o menos así:

objects <- mclapply(files, function(x) {
  on.exit(message(sprintf("Completed: %s", x)))
  message(sprintf("Started: '%s'", x))
  readBamGappedAlignments(x)
}, mc.cores=10)

Sin embargo, sigo recibiendo el siguiente error: Error: serialization is too large to store in a raw vector. Sin embargo, parece que puedo leer los mismos archivos solos sin este error. He encontrado mención de este problema aquísin resolución

Se agradecerá cualquier sugerencia de solución paralela; esto tiene que hacerse en paralelo. Podría mirar hacia la nieve, pero tengo un servidor muy potente con 15 procesadores, 8 núcleos cada uno y 256 GB de memoria en los que puedo hacer esto. Prefiero simplemente hacerlo en esta máquina a través de núcleos, en lugar de usar uno de nuestros clusters.


13
2018-04-25 04:04


origen


Respuestas:


Se rumorea que el límite entero se abordará muy pronto en R. En mi experiencia, ese límite puede bloquear conjuntos de datos con menos de 2 mil millones de células (alrededor del entero máximo), y funciones de bajo nivel como sendMaster en el multicore paquete confía en pasar vectores crudos. Tenía alrededor de 1 millón de procesos que representaban aproximadamente 400 millones de filas de datos y 800 millones de celdas en el formato data.table, y cuando mclapply estaba enviando los resultados, se encontró con este límite.

Una estrategia de dividir y conquistar no es tan difícil y funciona. Me doy cuenta de que esto es un truco y uno debería poder confiar en mclapply.

En lugar de una gran lista, cree una lista de listas. Cada sublista es más pequeña que la versión rota, y luego las alimenta en mclapply split by split. Llama esto file_map. Los resultados son una lista de listas, por lo que podría usar el doble concatenario especial do.call función. Como resultado, cada vez que mclapply termina el tamaño del vector en bruto serializado es de un tamaño manejable.

Simplemente recorra las piezas más pequeñas:

collector = vector("list", length(file_map)) # more complex than normal for speed 

for(index in 1:length(file_map)) {
reduced_set <- mclapply(file_map[[index]], function(x) {
      on.exit(message(sprintf("Completed: %s", x)))
      message(sprintf("Started: '%s'", x))
      readBamGappedAlignments(x)
    }, mc.cores=10)
collector[[index]]= reduced_set

}

output = do.call("c",do.call('c', collector)) # double concatenate of the list of lists

Alternativamente, guarde el resultado en una base de datos a medida que avanza, como SQLite.


3
2017-08-03 17:50