2014-07-18 13 views
10

Tôi đang sử dụng RStan để lấy mẫu từ một số lượng lớn các quy trình Gaussian (GP), tức là, bằng cách sử dụng hàm stan(). Đối với mỗi GP mà tôi phù hợp, một DLL khác được tải, như có thể thấy bằng cách chạy lệnh RĐã vượt quá số lượng tệp DLL tối đa trong R

getLoadedDLLs() 

Vấn đề tôi đang gặp phải là bởi vì tôi cần phải phù hợp với nhiều GP duy nhất, tôi ' m vượt số lượng tối đa của file DLL có thể được nạp, tại thời điểm đó tôi nhận được lỗi sau:

Error in dyn.load(libLFile) : 
unable to load shared object '/var/folders/8x/n7pqd49j4ybfhrm999z3cwp81814xh/T//RtmpmXCRCy/file80d1219ef10d.so': 
maximal number of DLLs reached... 

theo như tôi có thể nói, điều này được đặt trong Rdynload.c của mã cơ sở R, như sau :

#define MAX_NUM_DLLS 100 

Vì vậy, câu hỏi của tôi là, những gì có thể được thực hiện để sửa lỗi này? Việc xây dựng R từ nguồn có MAX_NUM_DLLS lớn hơn không phải là một tùy chọn vì mã của tôi sẽ được điều hành bởi các cộng tác viên không hài lòng với quy trình đó. Tôi đã thử cách tiếp cận ngây thơ của việc unloading DLLs bằng cách sử dụng dyn.unload() với hy vọng rằng chúng sẽ chỉ được nạp lại khi chúng cần một lần nữa. Các dỡ hoạt động tốt, nhưng khi tôi cố gắng sử dụng phù hợp một lần nữa, R khá gì ngạc nhiên bị treo với một lỗi như:

Tôi cũng đã cố gắng tách RStan với hy vọng rằng các DLL sẽ được tự động bốc dỡ, nhưng họ vẫn tồn tại ngay cả sau khi dỡ gói (như mong đợi, đưa ra sau đây trong trợ giúp cho tách: "tách ra sẽ không nói chung dỡ bỏ bất kỳ mã được biên dịch nạp động nào (DLL)").

Từ câu hỏi này, Can Rcpp package DLLs be unloaded without restarting R?, có vẻ như library.dynam.unload() thể có một số vai trò trong các giải pháp, nhưng tôi đã không có bất kỳ thành công sử dụng nó để dỡ bỏ các DLL, và tôi nghi ngờ rằng sau khi dỡ các DLL tôi muốn chạy vào cùng một segfault như trước.

EDIT: thêm một tối thiểu, ví dụ đầy đủ chức năng:

Mã R:

require(rstan) 

x <- c(1,2) 
N <- length(x) 

fits <- list() 
for(i in 1:100) 
{ 
    fits[i] <- stan(file="gp-sim.stan", data=list(x=x,N=N), iter=1, chains=1) 
} 

Mã này đòi hỏi rằng định nghĩa mô hình sau đây có trong thư mục làm việc trong một tập tin gp-sim. stan (mô hình này là một trong những ví dụ đi kèm với Stan):

// Sample from Gaussian process 
// Fixed covar function: eta_sq=1, rho_sq=1, sigma_sq=0.1 

data { 
    int<lower=1> N; 
    real x[N]; 
} 
transformed data { 
    vector[N] mu; 
    cov_matrix[N] Sigma; 
    for (i in 1:N) 
    mu[i] <- 0; 
    for (i in 1:N) 
    for (j in 1:N) 
     Sigma[i,j] <- exp(-pow(x[i] - x[j],2)) + if_else(i==j, 0.1, 0.0); 
} 
parameters { 
    vector[N] y; 
} 
model { 
    y ~ multi_normal(mu,Sigma); 
} 

Lưu ý: mã này mất khá nhiều thời gian để chạy, vì nó đang tạo ~ 100 mô hình Stan.

+1

Tôi ngạc nhiên rằng một DLL khác được tải cho mọi quá trình. Tôi tự hỏi nếu nó sẽ là dễ nhất để ngăn chặn điều này xảy ra ở nơi đầu tiên. Bạn có thể cung cấp một ví dụ về mã tối thiểu, nhưng đầy đủ chức năng để nắm bắt vấn đề của bạn không? – nograpes

+2

Đó là vấn đề thiết kế (R) Stan và giới hạn. Rcpp chỉ giúp tạo thư viện có khả năng tải động; nó không có quan điểm về việc có nên tải 100 trong số đó hay không. Cuối cùng, bạn sẽ đạt đến giới hạn OS (vượt quá giới hạn R mã hóa mà bạn đã xác định). –

Trả lời

7

Tôi không thể nói về các vấn đề liên quan đến dll, nhưng bạn không cần phải biên dịch mô hình mỗi lần. Bạn có thể biên dịch mô hình một lần và tái sử dụng nó, điều này sẽ không gây ra vấn đề này và nó sẽ tăng tốc mã của bạn.

Chức năng stan là trình bao bọc cho stan_model để biên dịch mô hình và phương pháp sampling lấy mẫu từ mô hình. Bạn nên chạy stan_model một lần để biên dịch mô hình và lưu nó vào một đối tượng, sau đó sử dụng phương thức sampling trên đối tượng đó để vẽ mẫu.

require(rstan) 

x <- c(1,2) 
N <- length(x) 

fits <- list() 
mod <- stan_model("gp-sim.stan") 
for(i in 1:100) 
{ 
    fits[i] <- sampling(mod, data=list(x=x,N=N), iter=1, chains=1) 
} 

Điều này tương tự như vấn đề chạy chuỗi song song, được thảo luận trong Rstan wiki. Mã của bạn có thể được tăng tốc bằng cách thay thế vòng lặp for bằng thứ gì đó xử lý việc lấy mẫu song song.

+3

Để hoàn thành, nếu bạn đã có một lý do hợp lệ để tải 100 DLL trong một phiên R, tôi nghĩ bạn có thể sử dụng hàm 'dyn.unload' để dỡ bỏ một số trong số chúng với' dyn.unload (file.path (tempdir() , paste0 (get_stanmodel (stanfit) @ dso @ dso_filename, .Platform $ dynlib.ext))) ', trong đó' stanfit' là một đối tượng được tạo bởi 'lấy mẫu' hoặc' stan'functions. Hoặc bạn có thể thay thế 'get_stanmodel (stanfit)' bằng đối tượng được tạo ra bởi 'stan_model'. Tuy nhiên, bạn sẽ rất hạn chế như những gì bạn có thể làm sau đó với đối tượng 'stanfit' mà không gặp sự cố R (không có' màn hình', 'in',' log_prob', v.v.) –

0

Đây là những gì tôi sử dụng để chạy nhiều mô hình stan liên tiếp (Win10, R 3.3.0).

Tôi không chỉ cần tải các tệp dll mà còn xóa chúng và các tệp tạm thời khác. Sau đó, tên tập tin cho tôi khác với tìm thấy trong đối tượng stan, như Ben gợi ý.

dso_filenames <- dir(tempdir(), pattern=.Platform$dynlib.ext) 
    filenames <- dir(tempdir()) 
    for (i in seq(dso_filenames)) 
    dyn.unload(file.path(tempdir(), dso_filenames[i])) 
    for (i in seq(filenames)) 
    if (file.exists(file.path(tempdir(), filenames[i])) & nchar(filenames[i]) < 42) # some files w/ long filenames that didn't like to be removeed 
     file.remove(file.path(tempdir(), filenames[i])) 
Các vấn đề liên quan