2011-07-24 13 views
7

Napotkano pewne problemy z używaniem foreach% dopar% podczas ładowania obiektów z dysku do pamięci ... Obiekty nie są ładowane, gdy próbuję je załadować, gdy używam foreach% dopar% (działa, gdy używam tylko% do%) Poniżej znajduje się prosty przykład pokazujący mój problem.load nie działa z foreach i% dopar%

envir = .GlobalEnv 

x <- "X test" 
y <- "Y test" 
z <- "Z test" 

save(x, file="x.RData") 
save(y, file="y.RData") 
save(z, file="z.RData") 

rm(x) 
rm(y) 
rm(z) 

objectsNamesVector <- c("x", "y", "z") 

foreach(i=1:length(objectsNamesVector), .combine=function (...) NULL, .multicombine=TRUE) %do% { 
    print(paste("Loading object ", objectsNamesVector[i]," - ", i, " of ", length(objectsNamesVector), sep="")) 
    load(file=paste(objectsNamesVector[i], ".RData", sep=""), envir=envir) 
} 

print(x) 
print(y) 
print(z) 

rm(x) 
rm(y) 
rm(z) 

foreach(i=1:length(objectsNamesVector), .combine=function (...) NULL, .multicombine=TRUE) %dopar% { 
    print(paste("Loading object ", objectsNamesVector[i]," - ", i, " of ", length(objectsNamesVector), sep="")) 
    load(file=paste(objectsNamesVector[i], ".RData", sep=""), envir=envir) 
} 

print(x) 
print(y) 
print(z) 

wyniku realizacji tego kodu jest (bez „>”):

envir = .GlobalEnv 

x <- "X test" 
y <- "Y test" 
z <- "Z test" 

save(x, file="x.RData") 
save(y, file="y.RData") 
save(z, file="z.RData") 

rm(x) 
rm(y) 
rm(z) 

objectsNamesVector <- c("x", "y", "z") 

foreach(i=1:length(objectsNamesVector), .combine=function (...) NULL, .multicombine=TRUE) %do% { 
+ print(paste("Loading object ", objectsNamesVector[i]," - ", i, " of ", length(objectsNamesVector), sep="")) 
+ load(file=paste(objectsNamesVector[i], ".RData", sep=""), envir=envir) 
+ } 
[1] "Loading object x - 1 of 3" 
[1] "Loading object y - 2 of 3" 
[1] "Loading object z - 3 of 3" 
NULL 

print(x) 
[1] "X test" 
print(y) 
[1] "Y test" 
print(z) 
[1] "Z test" 
rm(x) 
rm(y) 
rm(z) 

foreach(i=1:length(objectsNamesVector), .combine=function (...) NULL, .multicombine=TRUE) %dopar% { 
+ print(paste("Loading object ", objectsNamesVector[i]," - ", i, " of ", length(objectsNamesVector), sep="")) 
+ load(file=paste(objectsNamesVector[i], ".RData", sep=""), envir=envir) 
+ } 
NULL 

print(x) 
Error in print(x) : object 'x' not found 
print(y) 
Error in print(y) : object 'y' not found 
print(z) 
Error in print(z) : object 'z' not found 

Rozumiem, że nie można poprawić z foreach od IO IO jest sekwencyjna na moim architektury. Chciałbym tylko zrozumieć, dlaczego to nie działa ...

Dziękuję za odpowiedź.

Pozdrawiam, Pozdrawiam.

+0

Zgaduję, że to jest to. Czy może ktoś może doradzić, na jakiej liście R-pomocy powinienem zamieścić to pytanie, aby uzyskać odpowiedź? Thnx. – user859821

Odpowiedz

2

Uważam, że problemem jest to, że %do% jest w stanie pisać w środowisku globalnym, podczas gdy %dopar% nie jest. Korzystanie z %do% jest bardzo przydatne, jeśli chcesz składnię i inne dodatki, ale nie potrzebujesz równoległego zaplecza.

Po wykonaniu kolejno %do% utrzymywanie globalnego środowiska w czystości można pozostawić użytkownikowi, ponieważ nie będzie warunków wyścigu. W równoległym przypadku możesz mieć warunki wyścigu (tzn. Niektóre równoległe zadania mogą kończyć się przed innymi i mogą tworzyć losowe, trudne do odtworzenia wyniki).

Ze względu na warunki wyścigu, nie jest dobrym pomysłem, aby tego rodzaju operacja bezpośrednio zapisywać w globalnym środowisku, jeśli można tego uniknąć. Późniejszy użytkownik może wykonać taki sekwencyjny kod i zamienić %do% na , mając nadzieję na uzyskanie szybszych wyników, ale nie uzyskać takich samych wyników. Na swoją korzyść znalazłeś czysty przykład tego, gdzie to może się zdarzyć.

+0

Dzięki. Zacząłem używać% dopar% bez zrozumienia, jak działa równoległy backend w R, stąd moje nieporozumienia. – user859821

2

Trudno powiedzieć dokładnie, co się dzieje, nie wiedząc:

  1. Czym jest system operacyjny.
  2. Co równolegle backend już zarejestrowany% dopar%

Jeśli używasz doMC, to kod w bloku foreach wykonuje w fork() "proces ed. Oznacza to, że ma on własną przestrzeń pamięci i podczas gdy będzie modyfikować lokalnie .GlobalEnv, nie zmieni jej w procesie "master". Oznacza to, że w końcu modyfikujesz kopię pliku .GlobalEnv.

Jeśli wykonasz ten kod bez zarejestrowania backendu, to jest on wykonywany "poprawnie", ponieważ% dopar% kończy się wykonywanie, jak robi% do%.

Jednym ze sposobów radzenia sobie z tą sytuacją może być załadowanie obiektów do nowych środowisk, a następnie użycie parametru .combine foreach() do skopiowania zawartości każdego z nich do .GlobalEnv.

+0

Dziękuję za wyjaśnienia. Teraz rozumiem, co dzieje się za kulisami. – user859821

1

Miałem ten sam problem, gdy próbowałem użyć "foreach" + "doSnow", aby uruchomić równoległy program na komputerze z 32 rdzeniami. "foreach" przestał działać i powiedział: OBIEKT NIE ZNALEZIONO! Użyłem ".export" w "foreach", aby włączyć ten obiekt zewnętrzny, ale nadal powiedział, że OBIEKT NIE ZNALEZIONO! Kiedy próbowałem "doParallel" NOT "doSnow", zadziałało!

external_object < - 1

biblioteka (foreach)
biblioteka (doParallel)
registerDoParallel (rdzenie = 32)
getDoParWorkers()

foreach (I = 1: 32 = .combine c .multicombine = TRUE, .export = c ("external_object"))% dopar% { external_object }

+0

Jest to inny problem niż przedmiot tego pytania, który dotyczy skutków ubocznych globalnego środowiska w pętlach foreach. Twój przykład działa też dla mnie z doSNOW, z wyjątkiem tego, że jest generowane ostrzeżenie, że 'external_object' został już wyeksportowany, co oznacza, że ​​nie musisz używać' .export'. Nie jestem pewien, co było nie tak z twoim przykładem doSNOW, ale doParallel często działa, gdy doSNOW kończy się niepowodzeniem na Linuksie i Mac OS X, ponieważ doParallel używa mclapply zamiast clusterApplyLB. –

Powiązane problemy