2015-02-16 12 views
14

Oto przykład zabawki ilustrujący mój problem.Używanie source() w równoległych pętlach foreach

library(foreach) 
library(doMC) 
registerDoMC(cores=2) 

foreach(i = 1:2) %dopar%{ 
    i + 2 
} 
[[1]] 
[1] 3 

[[2]] 
[1] 4 

tej pory tak dobrze ...

Ale jeśli kod i + 2 jest zapisany w pliku addition.R a ja nazywam ten plik używając source() następnie

> foreach(i = 1:2) %dopar%{ 
+ source("addition.R") 
+ } 
Error in { : task 1 failed - "object 'i' not found" 
+3

Wypróbuj to 'źródło (" addtition.R ", local = T)' aby ocenić źródło w envronment, w którym nazywa się – NicE

+0

Zauważ, że wywołanie source() w% dopar% bloków znacznie spowalnia obliczenia, ponieważ procesy potomne muszą uzyskać ten plik źródłowy za pośrednictwem sieci –

Odpowiedz

10

nie mogę w pełni odtworzyć swoje zabawkę, ale miałem mały problem, który udało mi się rozwiązać przez:

source(file, local = TRUE) 

, który powinien przeanalizować źródło w lokalnym środowisku, tj. Rozpoznać i.

3

Komentarz NiceE i odpowiedź Sosel już to rozwiązują; przy wywołaniu source(file) domyślnie jest to source(file, local = FALSE), co oznacza, że ​​kod źródłowy pliku jest oceniany w środowisku globalnym ("przestrzeń robocza użytkownika") i istnieje, cf. ?source. Zauważ, że nie ma zmiennej i w środowisku globalnym. Rozwiązaniem jest upewnienie się, że plik pochodzi ze środowiska, które go wywołuje, tj. Do użycia source(file, local = TRUE).

Rozwiązanie:

library("foreach") 

y <- foreach(i = 1:2) %dopar% { 
    i + 2 
} 
str(y) 

doMC::registerDoMC(cores = 2L) 
y <- foreach(i = 1:2) %dopar% { 
    source("addition.R", local = TRUE) 
} 
str(y) 

Przykład tego samego problemu z for() pętli:

Fakt source() oceniano na środowisko globalne, który różni się od środowiska wywołującego gdzie i życia może być również zilustrowane za pomocą zwykłej pętli for, uruchamiając pętlę for w innym środowisku niż globalne, np wewnątrz funkcji lub przez:

local({ 
    for(i in 1:2) { 
    source("addition.R") 
    } 
}) 

co daje:

Error in eval(ei, envir) : object 'i' not found 

Teraz, dlaczego powyższe foreach(i = 1:2) %dopar% { source("addition.R") } współpracuje z registerDoSEQ()wtedy i tylko wtedy nazwie z globalnym środowisku, czy to wtedy iteracja foreach jest oceniana w środowisku wywołującym, które jest środowiskiem globalnym, które jest środowiskiem, z którego korzysta source(). Jednakże, jeśli jeden użył local(foreach(i = 1:2) %dopar% { ... }) również to nie powiedzie się analogicznie do powyższego wywołania local(for(i in 1:2) { ... }).

Podsumowując: nic magicznego się nie dzieje, ale zrozumienie tego jest trochę uciążliwe.

4

W końcu rozwiązałem problem, przekształcając źródło ("addition.R") w funkcję i po prostu przekazując do niej zmienne. Nie wiem dlaczego, ale sugerowane rozwiązania oparte na source(file, local = TRUE) nie działają.

+0

To, że 'source (" add.R ", local = TRUE)' nie zadziałałoby dla ciebie, nie ma dla mnie sensu. Czy możesz powtórzyć błąd za pomocą odtwarzalnego przykładu, który przyjąłem z twojego OP? Czy odnosisz się do bardziej złożonego skryptu R? Jeśli to drugie, mogą istnieć miliony powodów. Ponadto, jakie ustawienie/'sessionInfo()'? – HenrikB

+0

Mówię o dokładnie wspomnianym skrypcie i dokładnym błędzie. – CoderInNetwork

+0

To jest naprawdę dziwne. Czy błąd występuje również w tym przykładzie 'local ({for (i in 1:12) ...})? Jeśli tak, to wyklucza foreach itp. Co ważne, jakie jest twoje 'sessionInfo()' po otrzymaniu błędu? Podejrzewam, że coś w twojej konfiguracji powoduje tę różnicę. Uruchamianie R w terminalu lub w GUI (np. RStudio)? – HenrikB

Powiązane problemy