并行使用 rJava 和 xlsx
Using parallel alongside rJava and 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)
我是不是遗漏了什么,或者说 foreach
无法与 Java 对象一起使用?考虑到我只是在读取值而不是设置它们。
TLDR: 我认为初始化 wb
inside foreach 循环应该可以解决你的问题。
R 中的并行包以一种相当简单的方式处理并行处理:它启动多个 R 实例,将必要的数据复制到每个实例中,运行您的代码,然后 returns 您的结果。
我怀疑您 运行 遇到的问题是 R 并不真正知道如何将 rJava 对象复制到 R 的新实例中。
我比较熟悉 future
和 future.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]]
由于其他解决方案没有指出这一点,我们不得不声明这是不可能的。
我在 R 邮件列表中找到了 8 年前的相同主题。
https://stat.ethz.ch/pipermail/r-devel/2013-November/067960.html
“这是 Java 运行时的限制 - 你不能派生 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。您可以找出同步和异步处理。不仅如此,每个人都有自己的区别。对我而言,重要的是要记住我们有 multisession
和 multicore
(multithreating
),它们的工作方式截然不同。
我有一个巨大的 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)
我是不是遗漏了什么,或者说 foreach
无法与 Java 对象一起使用?考虑到我只是在读取值而不是设置它们。
TLDR: 我认为初始化 wb
inside foreach 循环应该可以解决你的问题。
R 中的并行包以一种相当简单的方式处理并行处理:它启动多个 R 实例,将必要的数据复制到每个实例中,运行您的代码,然后 returns 您的结果。
我怀疑您 运行 遇到的问题是 R 并不真正知道如何将 rJava 对象复制到 R 的新实例中。
我比较熟悉 future
和 future.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]]
由于其他解决方案没有指出这一点,我们不得不声明这是不可能的。
我在 R 邮件列表中找到了 8 年前的相同主题。
https://stat.ethz.ch/pipermail/r-devel/2013-November/067960.html
“这是 Java 运行时的限制 - 你不能派生 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。您可以找出同步和异步处理。不仅如此,每个人都有自己的区别。对我而言,重要的是要记住我们有 multisession
和 multicore
(multithreating
),它们的工作方式截然不同。