2017-05-19 41 views
8

mam funkcję zawiera pętlępętli wewnątrz pętli foreach stosując doparallel

myfun = function(z1.d, r, rs){ 
    x = z1.d[,r] 
    or.d = order(as.vector(x), decreasing=TRUE)[rs] 
    zz1.d = as.vector(x) 
    r.l = zz1.d[or.d] 

    y=vector() 
    for (i in 1:9) 
    { 
    if(i<9) y[i]=mean(x[(x[,r] >= r.l[i] & x[,r] < r.l[i+1]),r]) else{ 
     y[i] = mean(z1.d[(x >= r.l[9]),r])} 
    } 
    return(y) 
} 

RS jest wektorem numeryczne z1.d jest zoo i y jest również wektor numeryczne.

Gdy próbuję uruchomić funkcję wewnątrz pętli równoległej:

cls = makePSOCKcluster(8) 
registerDoParallel(cls) 

rlarger.d.1 = foreach(r=1:dim(z1.d)[2], .combine = "cbind") %dopar% {  
    myfun(z1.d, r, rs)} 

stopCluster(cls) 

pojawia się następujący błąd:

Error in { : task 1 failed - "incorrect number of dimensions" 

nie wiem dlaczego, ale zdałem sobie sprawę, jeśli biorę pętla z mojej funkcji nie daje błędu.

Również, jeśli uruchomię dokładnie ten sam kod z% do% zamiast% dopar% (więc nie działa równolegle) działa dobrze (wolno, ale bez błędów).

EDIT: zgodnie z wnioskiem o to próbka z parametrów:

dim(z1.d) 
[1] 8766 107 
> z1.d[1:4,1:6] 
        AU_10092 AU_10622 AU_12038 AU_12046 AU_13017 AU_14015 
1966-01-01 23:00:00  NA  NA  NA 1.816  0 4.573 
1966-01-02 23:00:00  NA  NA  NA 9.614  0 4.064 
1966-01-03 23:00:00  0  NA  NA 0.000  0 0.000 
1966-01-04 23:00:00  0  NA  NA 0.000  0 0.000 

> rs 
[1] 300 250 200 150 100 75 50 30 10 

R jest zdefiniowana w pętli foreach

+1

Pomocne byłoby przykładowe wprowadzenie parametrów z1.d, rs, r. – TUSHAr

+0

@sbg - Jakiego systemu operacyjnego używasz? W kontekście równoległego wykonywania, te punkty mają znaczenie. Ponieważ systemy Windows, Linux i MacOS mają w niektórych przypadkach różne implementacje równoległe udostępniane przez R. – Technophobe01

+0

używam go w oknach – sbg

Odpowiedz

2

Pojawia się błąd, ponieważ nie udało się zainicjować zoo na pracownikach. W związku z tym pracownicy nie wiedzą, jak postępować z obiektami zoo, zamiast tego traktują je jak matrioszki, które nie zachowują się tak samo przy podziale! Szybka korekta podanego problemu polega na dodaniu .packages="zoo" do połączenia foreach.

Moim zdaniem nie trzeba nawet wykonywać obliczeń równoległych.Możesz poprawić swoją funkcję dramatycznie jeśli używasz wektory numeryczne zamiast Zoo-obiektów:

# sample time series to match your object's size 
set.seed(1234) 
z.test <- as.zoo(replicate(107,sample(c(NA,runif(1000,0,10)),size = 8766, replace = TRUE))) 

myfun_new <- function(z, r, rs){ 
    x <- as.numeric(z[,r]) 
    r.l <- x[order(x, decreasing=TRUE)[rs]] 
    res_dim <- length(rs) 
    y=numeric(res_dim) 
    for (i in 1:res_dim){ 
    if(i< res_dim){ 
     y[i] <- mean(x[(x >= r.l[i] & x < r.l[i+1])], na.rm = TRUE) 
    }else{ 
     y[i] <- mean(x[(x >= r.l[res_dim])] , na.rm = TRUE) 
    } 
    } 
    return(y) 
} 

Proste czasy pokazują poprawę:

system.time({ 
    cls = makePSOCKcluster(4) 
    registerDoParallel(cls) 
    rlarger.d.1 = foreach(r=1:dim(z.test)[2],.packages = "zoo", .combine = "cbind") %dopar% { 
    myfun(z.test, r, rs)} 
    stopCluster(cls) 
}) 
## User  System verstrichen 
## 0.08  0.10  10.93 
system.time({ 
    res <-sapply(1:dim(z.test)[2], function(r){myfun_new(z.test, r, rs)}) 
}) 
## User  System verstrichen 
## 0.48  0.21  0.68 

Choć wyniki są takie same (tylko nazwy kolumn różnią)

all.equal(res, rlarger.d.1, check.attributes = FALSE) 
## [1] TRUE 
+0

Dzięki! Twoja sugestia jest o wiele bardziej skutecznym sposobem robienia tego! – sbg

1

To sims jak tam jest błąd w kodzie funkcji.

W wierszu 2 utworzeniu 1-wymiarowy obiekt

x = z1.d[,r] 

W linii 9 można traktować go jak 2-wymiarowej jedna

x[some_logic, r] 

Dlatego trzeba „nieprawidłową liczbę wymiarów” błąd. Chociaż nie wiem, dlaczego działa w wariancie% do%.

W każdym przypadku trzeba wymienić kod wewnątrz pętli z for:

if(i<9) y[i]=mean(x[(x[,r] >= r.l[i] & x[,r] < r.l[i+1])]) else{ 
     y[i] = mean(x[(x >= r.l[9])])} 

Albo z:

if(i<9) y[i]=mean(z1.d[(x[,r] >= r.l[i] & x[,r] < r.l[i+1]),r]) else{ 
     y[i] = mean(z1.d[(x >= r.l[9]),r])} 

Jak można nie zapewnić powtarzalną przykład, nie przetestować.