2009-12-29 5 views
4

Je me demandais s'il y avait un moyen d'obtenir le paquet foreach dans R pour utiliser une structure pré-allouée pour mettre les résultats. Fondamentalement, il implique beaucoup de petites opérations Linalg sur de très gros ensembles de données.Utilisation de la mémoire dans la fonction Foreach

Mon non-foreach code original est quelque chose comme

results <- rep(NA,m*l*[big.number]) 
dim(results) <- c(m,l,[big.number]) 
for (i in 1:m){ 
    for (j in 1:l){ 
     results[i,j,] <- function(j,i,data) 
    } 
} 

Je voudrais utiliser foreach et domc pour paralléliser cela, mais fonctionne de test sont vraiment très lent et je pense que ce sont les données continues en mouvement qui rbind et c fais.

+0

Il se produit aussi pour moi que parce que 'doMC' utilise un' fork', 'results' ne sera pas réellement mis dans le processus maître. Vous pouvez uniquement assembler les résultats via la fonction 'combine'. –

Répondre

0

J'ai eu de la chance avec abind() (from library (abind)). Par exemple, disons que j'ai une fonction de simulation retournant des matrices et que je voudrais un grand tableau, je pourrais utiliser abind (, le long de .5) pour obtenir la liste des matrices à lier dans un tableau avec une nouvelle dimension ajoutée . Donc, vous pourriez aimer quelque chose comme:

myfun<-function(arr){abind(arr,along=.5)} 

foreach(1:n.sims,.combine=myfun) .... 
0

Peut-être qu'il me manque quelque chose ici. Le coût de l'appel de fonction unique (i, j, data) doit être invariant pour savoir s'il est appelé dans un for -loop ou via foreach. Pouvez-vous pas essayer foreach en mode série, alors peut-être essayer avec multicore (sauf si vous êtes sur Windows) et aller de là?

+0

Je suppose que je suis confus sur deux aspects de la structure du doMC. Quel est le coût fixe dans la mise en place des travailleurs et quel est le coût de déplacement des données. Dans mon cas, l'exécution d'une seule itération de la fonction (i, j, données) est ~ 200 secondes, mais en cours d'exécution deux en mode multicœur prennent ~ 12 minutes. –

2

Ce n'est pas une réponse, mais je pensais que je posterai des résultats des tests dans l'espoir que quelqu'un d'autre saura ce qui se passe:

> data <- matrix(rnorm(1000 * 10000), nrow=10000) 
> system.time(foreach(j=1:1000, .combine = function(...) NULL, .multicombine=TRUE) %do% { sum(data[,j]) }) 
utilisateur  système  écoulé 
     0.643  0.031  0.674 
> system.time(foreach(j=1:1000, .combine = function(...) NULL, .multicombine=TRUE) %dopar% { sum(data[,j]) }) 
utilisateur  système  écoulé 
     0.613  0.215  0.653 
> system.time(foreach(j=1:1000) %dopar% { sum(data[,j]) }) 
utilisateur  système  écoulé 
     0.537  0.122  0.745 
> system.time(foreach(j=1:1000) %do% { sum(data[,j]) }) 
utilisateur  système  écoulé 
     0.650  0.028  0.681 
> system.time (for (j in 1:1000) { sum(data[,j]) }) 
utilisateur  système  écoulé 
     0.153  0.069  0.222 

En bref, en utilisant la for builtin est encore beaucoup plus rapide que série foreach. Vous ne gagnez pas vraiment en utilisant dopar, et il ne semble pas que tout mettre ensemble est ce qui prend tout le temps (il se peut encore que la transmission des données au maître prenne beaucoup de temps). Vous pouvez également argumenter qu'avec un calcul aussi simple, le surcoût dominera naturellement. Alors, faisons des choses plus compliquées:

> data <- matrix(rnorm(3000 * 10000), nrow=10000) 
> system.time (for(j in 1:6000) { sum(lgamma(exp(data[,(j - 1) %% 3000 + 1]))) }) 
utilisateur  système  écoulé 
    11.215  1.272  12.490 
> system.time (foreach(j=1:6000, .combine=c) %do% { sum(lgamma(exp(data[,(j - 1) %% 3000 + 1]))) }) 
utilisateur  système  écoulé 
    14.304  0.468  15.788 
> system.time (foreach(j=1:6000, .combine=c) %dopar% { sum(lgamma(exp(data[,(j - 1) %% 3000 + 1]))) }) 
utilisateur  système  écoulé 
    14.377  11.839  10.358 

Maintenant dopar commence à gagner sur mais les trois sont encore assez comparables et for est builtin pas si mal, même avec tout le travail supplémentaire. Mais qu'en est-il des frais généraux de communication? Au lieu de prendre des sommes, nous retournerons simplement les données transformées (10 000 nombres par itération).

> system.time (for(j in 1:6000) { lgamma(exp(data[,(j - 1) %% 3000 + 1])) }) 
utilisateur  système  écoulé 
    11.092  1.189  12.302  
> system.time (foreach(j=1:6000, .combine=function (...) NULL, .multicombine=TRUE) %do% { lgamma(exp(data[,(j - 1) %% 3000 + 1])) }) 
utilisateur  système  écoulé 
    14.902  1.867  22.901 
> system.time (foreach(j=1:6000, .combine=function (...) NULL, .multicombine=TRUE) %dopar% { lgamma(exp(data[,(j - 1) %% 3000 + 1])) }) 

^C 

Timing stopped at: 2.155 0.706 241.948 
> 

Ici, la boucle for qui n'a pas à se soucier de garder des résultats prend environ à peu près aussi longtemps qu'auparavant. La version %do% a pris beaucoup plus de temps cette fois. Et le %dopar% qui transfère probablement les résultats à travers la mémoire partagée? J'ai décidé de le tuer après environ 4 minutes.