2017-05-19 30 views
8

Tôi có một chức năng có chứa một vòng lặpvòng lặp bên trong một vòng lặp foreach sử dụng 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 là một vector số, z1.d là một sở thú và y cũng là một vector số.

Khi tôi cố gắng để chạy các chức năng bên trong một vòng lặp song song:

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) 

tôi nhận được lỗi sau:

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

Tôi không biết tại sao, nhưng tôi nhận ra nếu tôi lấy lặp lại chức năng của tôi, nó không đưa ra lỗi.

Ngoài ra, nếu tôi chạy cùng mã chính xác với% do% thay vì% dopar% (do đó không chạy song song) nó hoạt động tốt (chậm nhưng không có lỗi).

EDIT: theo yêu cầu ở đây là một mẫu của các thông số:

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 được định nghĩa trong vòng lặp foreach

+1

Đầu vào mẫu của thông số z1.d, rs, r sẽ hữu ích. – TUSHAr

+0

@sbg - Bạn đang chạy hệ điều hành nào. Trong bối cảnh thực hiện song song, điểm này quan trọng. Như Windows, Linux và MacOS có trong một số trường hợp triển khai song song khác nhau tiếp xúc qua R. – Technophobe01

+0

Tôi đang chạy nó trong windows – sbg

Trả lời

2

Lỗi xuất hiện vì bạn không thể khởi tạo zoo trên công nhân của mình. Vì vậy, các công nhân không biết làm thế nào để đối phó với các đối tượng sở thú đúng cách, thay vào đó họ xử lý chúng như là matrizes mà không hành xử theo cùng một cách khi subsetting! Vì vậy, khắc phục nhanh sự cố đã nêu của bạn sẽ là thêm .packages="zoo" vào cuộc gọi foreach của bạn.

Theo ý kiến ​​của tôi, bạn thậm chí không cần thực hiện các phép tính song song.Bạn có thể tăng cường chức năng của bạn một cách đáng kể nếu bạn sử dụng vectơ số thay vì sở thú-vật:

# 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) 
} 

timings đơn giản cho thấy sự cải thiện:

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 

Trong khi các kết quả đều giống nhau (chỉ tên cột khác)

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

Cảm ơn! Đề xuất của bạn là một cách hiệu quả hơn để làm điều đó! – sbg

1

Nó sims như có một lỗi trong mã chức năng của bạn.

Trong dòng 2 bạn tạo một đối tượng 1 chiều

x = z1.d[,r] 

Trong dòng 9 bạn đối xử với nó như 2 chiều một

x[some_logic, r] 

Đó là lý do tại sao bạn có "số không chính xác kích thước" lỗi. Mặc dù, tôi không biết tại sao nó hoạt động trong% do% variant.

Trong mọi trường hợp bạn cần phải thay thế mã bên for vòng lặp với:

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])])} 

Hoặc với:

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])} 

Như bạn đã không cung cấp ví dụ tái sản xuất, tôi đã không kiểm tra nó.

Các vấn đề liên quan