2008-09-17 21 views
5

que tienen una función dentro de un bucle dentro de una función. Adquiere la función interna y almacena una gran vector de datos en la memoria (como una variable global ... que estoy usando "R", que es como "S-Plus"). El bucle recorre una larga lista de datos que se adquirirán. La función externa inicia el proceso y pasa a la lista de conjuntos de datos que se adquirirán.Peor peor: ¿efectos secundarios o pasar objetos masivos?

for (dataset in list_of_datasets) { 
    for (datachunk in dataset) { 
    <process datachunk> 
    <store result? as vector? where?> 
    } 
} 

programé la función interna para almacenar cada conjunto de datos antes de pasar a la siguiente, por lo que todo el trabajo de la función externa se produce como efectos secundarios en las variables globales ... un gran no-no. ¿Es esto mejor o peor que recolectar y devolver un vector gigante de vectores que almacena recuerdos? ¿Hay un tercer acercamiento superior?

¿Cambiaría la respuesta si estuviera almacenando los vectores de datos en una base de datos en lugar de en la memoria? Idealmente, me gustaría poder finalizar la función (o hacer que falle debido a los tiempos de espera de la red) sin perder toda la información procesada antes de la finalización.

+2

Recomiendo la edición de este post para incluir una breve pseudocódigo así que es más fácil ver lo que está tratando de hacer –

+0

Sí, por favor añadir pseudocódigo , es imposible saber a qué te refieres. Cuando dices "procesar ... y almacenar el resultado", ¿te refieres a "almacenar exactamente la misma cadena", o vector (de ints, hacer referencia a palabras), o qué? ¿Lo está almacenando como un registro en una enorme matriz de datos/matriz/matriz? Danos una idea de la cantidad de filas, columnas, archivos, tamaños de fragmentos y vectores, y tu memoria de trabajo? – smci

Respuesta

-1

Es difícil decir definitivamente sin conocer el idioma/compilador utilizado. Sin embargo, si lo único que puede pasar un puntero/referencia al objeto que se va a crear, a continuación, el tamaño del objeto en sí mismo no tiene nada que ver con la velocidad de las llamadas a funciones. Manipular esta información más adelante podría ser una historia diferente.

+1

El lenguaje que está usando es R: http://r-project.org/ – Allen

10

variables de uso en la función externa en lugar de las variables globales. Esto le proporciona lo mejor de ambos enfoques: no está mutando el estado global, y no está copiando una gran cantidad de datos. Si tiene que salir temprano, solo devuelva los resultados parciales.

(Véase la sección "Scope" en el manual de R: http://cran.r-project.org/doc/manuals/R-intro.html#Scope)

0

Tercer enfoque: función interna devuelve una referencia a la gran matriz, que entonces desreferencias y tiendas donde se necesite la siguiente instrucción en el interior del bucle (idealmente con un solo almacén de puntero y no por tener que memcopy toda la matriz).

Esto elimina el efecto secundario y el paso de grandes estructuras de datos.

4

No va a cambiar mucho la utilización de la memoria, por lo que también podría hacer que el código limpio.

Como R tiene copy-on-modify para las variables, la modificación del objeto global tendrá las mismas implicaciones de memoria que pasar algo arriba en los valores de retorno.

Si almacena las salidas en una base de datos (o incluso en un archivo) no tendrá problemas de uso de memoria, y los datos estarán disponibles incrementalmente a medida que se crean, en lugar de solo al final. Si es más rápido con la base de datos depende principalmente de la cantidad de memoria que está utilizando: la reducción es la recolección de basura que va a pagar el costo de escribir en el disco.

Hay perfiles de tiempo y memoria en R, por lo que puede ver empíricamente cuáles son los impactos.

1

No estoy seguro de entender la pregunta, pero tengo un par de soluciones.

  1. Dentro de la función, cree una lista de los vectores y devuélvalo.

  2. Dentro de la función, cree un entorno y almacene todos los vectores dentro de eso. Solo asegúrese de devolver el entorno en caso de errores.

en I:

help(environment) 

# You might do something like this: 

outer <- function(datasets) { 
    # create the return environment 
    ret.env <- new.env() 
    for(set in dataset) { 
    tmp <- inner(set) 
    # check for errors however you like here. You might have inner return a list, and 
    # have the list contain an error component 
    assign(set, tmp, envir=ret.env) 
    } 
    return(ret.env) 
} 

#The inner function might be defined like this 

inner <- function(dataset) { 
    # I don't know what you are doing here, but lets pretend you are reading a data file 
    # that is named by dataset 
    filedata <- read.table(dataset, header=T) 
    return(filedata) 
} 

Leif

6

Recuerde su Knuth. "La optimización prematura es la raíz de toda la programación del mal".

Pruebe la versión gratuita de efectos secundarios. Vea si cumple con sus metas de rendimiento. Si lo hace, genial, no tienes un problema en primer lugar; si no es así, utilice los efectos secundarios y anote al siguiente programador que su mano fue forzada.

1

FYI, he aquí una solución juguete muestra completa que evita efectos secundarios:

outerfunc <- function(names) { 
    templist <- list() 
    for (aname in names) { 
    templist[[aname]] <- innerfunc(aname) 
    } 
    templist 
} 

innerfunc <- function(aname) { 
    retval <- NULL 
    if ("one" %in% aname) retval <- c(1) 
    if ("two" %in% aname) retval <- c(1,2) 
    if ("three" %in% aname) retval <- c(1,2,3) 
    retval 
} 

names <- c("one","two","three") 

name_vals <- outerfunc(names) 

for (name in names) assign(name, name_vals[[name]]) 
Cuestiones relacionadas