2010-10-11 35 views
6

我正在使用RPostgreSQL连接到本地数据库。该设置在我的Linux机器上工作得很好。 R 2.11.1,Postgres 8.4。foreach%dopar%+ RPostgreSQL

我正在玩多核(doMC)并行后端的'foreach'来包装一些重复查询(数字为数千)并将结果附加到数据结构中。奇怪的是,如果我使用%do%,但是在切换到%dopar%时失败,除了只有一次迭代时(如下所示),它会起作用

我想知道它是否与单个操作有关连接对象,所以我创建了10个连接对象,并根据“我”是什么,为该查询提供了一个特定的con对象,具体取决于我的模10(下面仅由2个连接对象指出)。被评估为eval(expr.01)的表达式包含/是依赖于'i'的查询。

我无法理解这些特定的错误信息。我想知道是否有任何方法可以完成这项工作。

谢谢。
维沙尔Belsare

[R片断如下:

> id.qed2.foreach <- foreach(i = 1588:1588, .inorder=FALSE) %dopar% { 
+ if (i %% 2 == 0) {con <- con0}; 
+ if (i %% 2 == 1) {con <- con1}; 
+ fetch(dbSendQuery(con,eval(expr.01)),n=-1)$idreuters}; 
> id.qed2.foreach 
[[1]] 
    [1] 411 414 2140 2406 4490 4507 4519 4570 4571 4572 4703 4731 
[109] 48765 84312 91797 

> id.qed2.foreach <- foreach(i = 1588:1589, .inorder=FALSE) %dopar% { 
+ if (i %% 2 == 0) {con <- con0}; 
+ if (i %% 2 == 1) {con <- con1}; 
+ fetch(dbSendQuery(con,eval(expr.01)),n=-1)$idreuters}; 
Error in stop(paste("expired", class(con))) : 
    no function to return from, jumping to top level 
Error in stop(paste("expired", class(con))) : 
    no function to return from, jumping to top level 
Error in { : 
    task 1 failed - "error in evaluating the argument 'res' in selecting a method for function 'fetch'" 
> 

编辑:我改变了一些东西,(仍然不成功),但有一些事情要轻。在循环中创建的连接对象并不是通过dbDisconnect“断开连接”,导致挂起连接,如Postgres的/ var/log所示。当我这样做时,会出现一些新的错误消息:

> system.time(
+ id.qed2.foreach <- foreach(i = 1588:1590, .inorder=FALSE, 
.packages=c("DBI", "RPostgreSQL")) %dopar% {drv0 <- dbDriver("PostgreSQL"); 
con0 <- dbConnect(drv0, dbname='nseindia'); 
list(idreuters=fetch(dbSendQuery(con0,eval(expr.01)),n=-1)$idreuters); 
dbDisconnect(con0)}) 
Error in postgresqlExecStatement(conn, statement, ...) : 
    no function to return from, jumping to top level 
Error in postgresqlExecStatement(conn, statement, ...) : 
    no function to return from, jumping to top level 
Error in postgresqlExecStatement(conn, statement, ...) : 
    no function to return from, jumping to top level 
Error in { : 
    task 1 failed - "error in evaluating the argument 'res' in selecting a method for function 'fetch'" 
+0

如果您解决了问题,请将您的解决方案作为下面的答案发布,并将其标记为已接受。这对将来的参考很有用。 – BoltClock 2010-10-11 14:40:15

回答

2

以下工作和加速顺序形式上约1.5倍。作为下一步,我想知道是否可以将连接对象附加到由registerDoMC产生的每个工作人员。如果是这样,那么就不需要创建/销毁连接对象,这可以防止连接PostgreSQL服务器。

pgparquery <- function(i) { 
drv <- dbDriver("PostgreSQL"); 
con <- dbConnect(drv, dbname='nsdq'); 
lst <- eval(expr.01); #contains the SQL query which depends on 'i' 
qry <- dbSendQuery(con,lst); 
tmp <- fetch(qry,n=-1); 
dt <- dates.qed2[i] 
dbDisconnect(con); 
result <- list(date=dt, idreuters=tmp$idreuters) 
return(result)} 

id.qed.foreach <- foreach(i = 1588:3638, .inorder=FALSE, .packages=c("DBI", "RPostgreSQL")) %dopar% {pgparquery(i)} 

-
维沙尔Belsare

+1

Vishal,你是否曾经能够弄清楚如何将持久连接对象附加到每个工作人员,如上所述?我也有这个问题。有趣的是,我能够让'dbListTables(conn)'在worker上工作,但'dbgetQuery(conn,...)'-type命令似乎不适用于连接的连接对象。 – Noah 2014-04-18 21:46:45

+0

@Noah你可以尝试使用我在答案中描述的技术。 – 2014-07-08 14:33:19

12

这是更有效的人均一次创建数据库连接,而不是每一次任务。不幸的是,mclapply没有提供在执行任务之前初始化工作人员的机制,因此使用doMC后端很难做到这一点,但是如果您使用doParallel后端,则可以使用clusterEvalQ初始化工作人员。下面是如何转型的代码示例:

library(doParallel) 
cl <- makePSOCKcluster(detectCores()) 
registerDoParallel(cl) 

clusterEvalQ(cl, { 
    library(DBI) 
    library(RPostgreSQL) 
    drv <- dbDriver("PostgreSQL") 
    con <- dbConnect(drv, dbname="nsdq") 
    NULL 
}) 

id.qed.foreach <- foreach(i=1588:3638, .inorder=FALSE, 
          .noexport="con", 
          .packages=c("DBI", "RPostgreSQL")) %dopar% { 
    lst <- eval(expr.01) #contains the SQL query which depends on 'i' 
    qry <- dbSendQuery(con, lst) 
    tmp <- fetch(qry, n=-1) 
    dt <- dates.qed2[i] 
    list(date=dt, idreuters=tmp$idreuters) 
} 

clusterEvalQ(cl, { 
    dbDisconnect(con) 
}) 

由于doParallel和clusterEvalQ都使用相同的群集对象cl,foreach循环将执行任务时,有权访问数据库连接对象con

+0

史蒂夫,这很有帮助。不知道你是如何回到这个相当古老的问题的! – 2014-07-11 05:39:59

+0

有什么办法可以使用foreach将数据库设置代码传递给每个worker?我想尝试使用任意并行后端的代码。 – Zach 2014-08-04 14:33:30

+0

@Zach没有一个后端独立的方式来初始化工作人员,这总是让我感到困扰。我尝试过使用后端特定的机制(例如在doMPI中),但这从来没有变成一个通用功能,部分原因是由于使用doMC的实现可能会非常难看,因为mclapply不支持工作者初始化。 – 2014-08-04 14:44:38

相关问题