微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

与 rJava 和 xlsx 并行使用

如何解决与 rJava 和 xlsx 并行使用

我有一个巨大的 excel 文件要操作。我需要读取大量单元格的颜色和样式,并认为通过并行化任务来加速计算。我依靠 xlsx 包及其函数 getCellStyle 逐个单元地获取样式。反过来,该包依赖于 rJava。看起来,出于某种原因,涉及 java 对象的任务无法并行化。这是一个可重现的示例:

require(xlsx)
require(writexl)
require(doParallel)
require(foreach)
require(parallel)

#We create an excel file with the iris dataset
filename <- "iris.xlsx"
write_xlsx(iris,filename)
#Read the workbook and the first (and only) sheet
wb <- loadWorkbook(filename)
sheet <- getSheets(wb)[[1]]
#With the next two rows we grab all the cells as Java objects
rows  <- getRows(sheet)
allcells <- getCells(rows)
#This works: grabbing the style
styles <- lapply(allcells,getCellStyle)
styles[[1]]
#[1] "Java-Object{org.apache.poi.xssf.usermodel.XSSFCellStyle@abd07bb0}"

#Now we try to go parallel: we create a cluster and make
#use of foreach and dopar
registerDoParallel(6)
stylePar<-foreach(i = seq_along(allcells)) %dopar% getCellStyle(allcells[[i]])
#Unfortunately,every Java object looks null
stylePar[[1]]
#[1] "Java-Object<null>"
#For the record,even mclapply returns all Java null objects
#mclapply(allcells,getCellStyle,mc.cores = 6,mc.preschedule = FALSE)

我是否遗漏了某些东西,或者对 Java 对象使用 foreach 本质上是不可能的?考虑到我只是在读取值而不是设置它们。

解决方法

由于其他解决方案没有指出这一点,我们必须声明这是不可能的。
我在 R 邮件列表中找到了 8 年前的相同主题。

https://stat.ethz.ch/pipermail/r-devel/2013-November/067960.html

“这是 Java 运行时的限制 - 你不能 fork JVM。”

其他来源:how to fork JVM?

所以这不是 R 的限制,更多的是 JVM。

library(future.apply) 下的解决方案正在运行,因为任何计划都已激活,因此使用了基础 lapply。应该像这样调用:

library(future)
library(future.apply)
plan(multisession)

最后要评论的是,多处理不是那么简单,可以在不同的范式下工作。请查看未来的小插曲 https://cran.r-project.org/web/packages/future/vignettes/future-1-overview.html。您可以找到同步和异步处理。不仅如此,每个人都有自己的区别。对我来说,重要的是要记住我们有 multisessionmulticore (multithreating),它们的工作方式大不相同。

,

TLDR:我认为初始化 wb inside foreach 循环应该可以解决您的问题。

R 中的并行包以一种相当简单的方式处理并行处理:它启动多个 R 实例,将必要的数据复制到每个实例中,运行您的代码,然后返回您的结果。

我怀疑您遇到的问题是 R 并不真正知道如何将 rJava 对象复制到 R 的新实例中。

,

我更熟悉 futurefuture.apply。将 foreach 替换为 future.apply 似乎有效。对象匹配 base::lapply

require(xlsx)
require(writexl)
#require(doParallel)
#require(foreach)

library(future.apply)

#We create an excel file with the iris dataset
filename <- "iris.xlsx"
write_xlsx(iris,filename)
#Read the workbook and the first (and only) sheet
wb <- loadWorkbook(filename)
sheet <- getSheets(wb)[[1]]
#With the next two rows we grab all the cells as Java objects
rows  <- getRows(sheet)
allcells <- getCells(rows)
#This works: grabbing the style
styles <- lapply(allcells,getCellStyle)
styles[[1]]
#[1] "Java-Object{org.apache.poi.xssf.usermodel.XSSFCellStyle@abd07bb0}"

# Specify how to parallize
plan(multisession)

# Apply getCellStyle to every object in allcells
stylePar <- future_lapply(allcells,getCellStyle)
stylePar[[1]]

styles[[1]] == stylePar[[1]]
#Now we try to go parallel: we create a cluster and make
#use of foreach and dopar
# registerDoParallel(6)
# stylePar<-foreach(i = seq_along(allcells)) %dopar% xlsx::getCellStyle(allcells[[i]])
# #Unfortunately,every Java object looks null
# stylePar[[1]]



版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。