2017-06-16 4 views
0

J'utilise sfApply dans R paquet de chutes de neige pour le calcul parallèle. Il y a 32000 tests à exécuter. Le code fonctionne correctement au démarrage de l'ordinateur, il créera 46 processus Rscript.exe et chaque Rscript.exe aura une utilisation de 2%. L'utilisation globale du processeur est d'environ 100% et les résultats sont continuellement écrit sur le disque. L'informatique prendra habituellement des dizaines d'heures. La chose étrange est que le processus Rscript.exe devient progressivement inactif (cpu usage = 0) un par un, et le cpu correspondant est également inactif. Après deux jours, il n'y a que la moitié du nombre de Rscript.exe qui sont actifs en regardant l'utilisation du processeur, et l'utilisation globale du processeur réduit à 50%. Cependant, le travail est loin de finir. Au fil du temps, de plus en plus de Rscript.exe deviennent inactifs, ce qui rend le travail très long. Je me demande ce qui rend le processus et les noyaux de cpu inactifs?R chute de neige parallèle, Rscript.exe devient inactif un par un avec le temps

Mon ordinateur possède 46 cœurs logiques. J'utilise R-3.4.0 de Rstudio dans Windows 7 64 bits. La variable 'test' suivante est une matrice 32000 * 2. myfunction est la résolution de plusieurs équations différentielles.

Merci.

library(snowfall) 
    sfInit(parallel=TRUE, cpus=46) 
    Sys.time() 
    sfLibrary(deSolve) 
    sfExport("myfunction","test") 
    res<-sfApply(test,1,function(x){myfunction(x[1],x[2])}) 
    sfStop() 
    Sys.time() 
+0

Qu'en est-il de l'utilisation de la mémoire? Est-ce que suffisamment de RAM est disponible? Il n'y a pas grand-chose à faire ici, mais vous pourriez essayer d'exécuter seulement quelques tâches à la fois et voir si elles passent. Commencez à augmenter le nombre de tâches jusqu'à ce que vous atteigniez le goulot d'étranglement. –

+0

Merci. La RAM est disponible, seulement 10G (64G au total) est utilisé. Je pourrais essayer cela, mais le problème est que les processus sont progressivement inactifs. Les tâches se poursuivent, avec de moins en moins de cpus. C'est comme si quelque chose pendant le calcul faisait dormir les noyaux un par un. – yan

+0

Désolé, je n'ai plus d'idées.Peut-être pourriez-vous utiliser un autre outil parallèle, comme 'parallel' ou' foreach'? –

Répondre

0

Qu'est-ce que vous décrivez semble raisonnable puisque snowfall::sfApply() utilise snow::parApply() en interne, qui MORCEAUX vos données (test) en (ici) 46 morceaux et envoie chaque morceau à l'un des 46 travailleurs R. Quand un ouvrier termine son morceau, il n'y a plus de travail pour cela et il va juste rester inactif tandis que les morceaux restants sont traités par les autres ouvriers. Ce que vous voulez faire est de diviser vos données en plus petits morceaux qui conduiront chaque travailleur à traiter plus d'un morceau en moyenne. Je ne sais pas si (pensez?) C'est possible avec des chutes de neige. Le paquet parallèle, qui fait partie de R lui-même et qui remplace le paquet de neige (sur lequel repose la neige), fournit parApply() et parApplyLB() où ce dernier divise vos blocs en tailles minimales, à savoir un par élément de données (de test). Voir help("parApply", package = "parallel") pour plus de détails.

Le package future (dont je suis l'auteur) vous offre la possibilité de mettre à l'échelle la quantité de données que vous souhaitez diviser. Il ne fournit pas une version apply(), mais une version lapply() que vous pouvez utiliser (et comment fonctionne parApply() en interne). Par exemple, votre exemple qui utilise un morceau par travailleur serait:

library("future") 
plan(multisession, workers = 46L) 

## Coerce matrix into list with one element per matrix row 
test_rows <- lapply(seq_len(nrow(test)), FUN = function(row) test[row,]) 

res <- future_lapply(test_rows, FUN = function(x) { 
    myfunction(x[1],x[2]) 
}) 

qui est par défaut

res <- future_lapply(test_rows, FUN = function(x) { 
    myfunction(x[1],x[2]) 
}, future.scheduling = 1.0) 

Si vous voulez partager les données afin que chaque travailleur traite une ligne au moment (voir parallel::parApplyLB()), vous le faites comme:

res <- future_lapply(test_rows, FUN = function(x) { 
    myfunction(x[1],x[2]) 
}, future.scheduling = Inf) 

en définissant future.scheduling dans [1, Inf], vous pouvez contrôler la taille de la taille du morceau est en moyenne. Par exemple, future.scheduling = 2.0 aura chaque travailleur de traiter en moyenne deux morceaux de données avant les retours future_lapply().