从 foreach 循环赋值

2024-05-08

我想并行化一个循环,例如

td        <- data.frame(cbind(c(rep(1,4),2,rep(1,5)),rep(1:10,2)))
names(td) <- c("val","id")

res <- rep(NA,NROW(td))
for(i in levels(interaction(td$id))){
res[td$id==i] <- mean(td$val[td$id!=i])
}  

在...的帮助下foreach() of the 库(并行)以加快计算速度。不幸的是 foreach 似乎不支持直接赋值,至少

registerDoParallel(4)
res <- rep(NA,NROW(td))
foreach(i=levels(interaction(td$id))) %dopar%{
res[td$id==i] <- mean(td$val[td$id!=i])}

没有做我想要的事情(给出与上面正常循环相同的结果)。任何想法我做错了什么或者我如何以某种方式“破解”.combineforeach 中的选项以便执行我想要的操作?请注意,id 变量的顺序在原始数据集中并不总是相同。任何提示将非常感激!


为了并行高效地执行这些计算,您需要使用分块,因为单个均值计算不需要太多时间。使用时foreach,我经常使用来自itertools用于分块的包。在这种情况下,我使用isplitVector函数以便为每个工作人员生成一个任务。结果是向量,因此只需将它们相加即可将它们组合起来,这就是为什么r向量必须初始化为零向量。

vadd <- function(a, ...) {
  for (v in list(...))
    a <- a + v
  a
}

res <- foreach(ids=isplitVector(unique(td$id), chunks=workers),
               .combine='vadd',
               .multicombine=TRUE,
               .inorder=FALSE) %dopar% {
  r <- rep(0, NROW(td))
  for (i in ids)
    r[td$id == i] <- mean(td$val[td$id != i])
  r
}

这是将原始顺序版本放入foreach循环,但仅对数据的子集进行操作。由于每个工作人员只需要组合一个结果,因此几乎不需要后处理,因此运行效率非常高。

为了了解其执行情况,我使用以下数据集针对顺序版本和 Rolands 数据表版本对其进行了基准测试:

set.seed(107)
n <- 1000000
m <- 10000
td <- data.frame(val=rnorm(n), id=sample(m, n, replace=TRUE))

我之所以将其包括在内,是因为性能非常依赖于数据。您甚至可以通过使用不同的随机种子获得不同的性能结果。

以下是我的 Linux 机器(配备 Xeon CPU X5650 和 12 GB RAM)的一些基准测试结果:

  • 顺序 for 循环 http://pastebin.com/zE8HbiT4:359秒
  • 顺序数据表版本 http://pastebin.com/FbX2zLST:208秒
  • foreach/doParallel/PSOCK 有 4 个工作线程 http://pastebin.com/zQtwb9HH:104秒

因此,对于至少一个数据集,并行执行此计算是值得的。这不是一个完美的加速,但也不算太糟糕。为了在您自己的计算机上或使用不同的数据集运行任何这些基准测试,您可以通过上面的链接从 Pastebin 下载它们。

Update

在完成这些基准测试之后,我有兴趣使用data.table with foreach以获得更快的版本。这是我想到的(根据马修·道尔的建议):

cmean <- function(v, mine) if (mine) mean(v) else 0
nuniq <- length(unique(td$id))
res <- foreach(grps=isplitIndices(nuniq, chunks=workers),
               .combine='vadd',
               .multicombine=TRUE,
               .inorder=FALSE,
               .packages='data.table') %dopar% {
  td[, means := cmean(td$val[-.I], .GRP %in% grps), by=id]
  td$means
}

td现在是一个data.table目的。我用了isplitIndices来自itertools包生成与每个任务块关联的组号向量。这cmean函数是一个包装器mean对于不应在该任务块中计算的组返回零。它使用与非数据表版本相同的组合函数,因为任务结果相同。

在四个工作线程和相同的数据集的情况下,该版本的运行时间为 56.4 秒,与顺序数据表版本相比,加速了 3.7 秒,比顺序 for 循环快了 6.4 倍,成为明显的赢家。基准测试可以从pastebin下载here http://pastebin.com/wax1LyEg.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 foreach 循环赋值 的相关文章

  • 跟踪循环迭代

    抛硬币 成功 你赢100 否则你输50 你会一直玩 直到你口袋里有钱a 的价值如何a在任何迭代中都被存储 a lt 100 while a gt 0 if rbinom 1 1 0 5 1 a lt a 100 else a lt a 50
  • 将 ftransform 与折叠 R 包中的 fgroup_by 一起使用

    我正在尝试重现以下输出dplyr代码与R包裹collapse dplyr Code library tidyverse starwars gt select name mass species gt group by species gt
  • 尝试使用 JRI 将 R 与我的 Java 应用程序集成,但出现错误。谁能解释一下原因和解决办法吗?

    我需要将 Java 与 R 集成来运行一些数学命令并使用 R 的功能进行绘图 以下部分代码给出了错误 public static void main String args HelloRWorld r new HelloRWorld r h
  • 使用officer R导出时如何提高ggplots的分辨率

    我想将图表导出到 PPT 并使用Officer 包来实现相同的目的 但是 图表的默认分辨率较低 我想更改它 我目前正在使用以下电话 ph with gg p1 type chart res 1200 其中 p1 是 ggplot 对象 运行
  • 警告消息 - 来自 dummies 包的 dummy

    我正在使用 dummies 包为分类变量生成虚拟变量 其中一些变量具有两个以上类别 testdf lt data frame A as factor c 1 2 2 3 3 1 B c A B A B C C C c D D E D D E
  • 需要在R中按行绑定列表数据

    我在 R 中按行绑定列表时遇到问题 我的列表数据集是 id 1 data k 1 id k b c 1 1 1 3 data k 2 id k b c 1 2 1 4 id 2 data k 1 id k b c 2 1 1 6 data
  • 如何按时间间隔匹配数据帧?

    这是我从数据记录器导入原始数据时经常出现的问题 温度记录仪设置为每十分钟记录一次温度 单独的气体记录仪设置为记录最后十分钟间隔内使用的气体 我想将这两个记录器的数据合并到一个数据框中进行绘图和分析 但时间并不完全一致 我希望每十分钟的时间段
  • picker输入字体或背景颜色

    我在闪亮的仪表板中使用 pickerInput 这很好 除了一个问题 背景颜色和字体颜色太相似 使得过滤器选择难以阅读 有什么办法可以改变背景或字体颜色吗 如果可能的话 我想继续使用 pickerInput 但如果有一个带有 selectI
  • 将列表中的每个元素转换为数据框中的一列

    假设我有以下列表 d library combinat d permn c a b c 这看起来如下 1 1 a b c 2 1 a c b 3 1 c a b 4 1 c b a 5 1 b c a 6 1 b a c 是否可以将此列表的
  • 为什么 sapply 的缩放速度比样本大小的 for 循环慢?

    假设我想采用向量 X 2 1 N 并将 e 计算为每个元 素的指数 是的 我认识到最好的方法就是通过向量化 exp X 但这样做的目的是将 for 循环与 sapply 进行比较 我通过逐步尝试三种方法 一种使用 for 循环 两种以不同方
  • 我可以使用哪个 R 函数来查找两条线的交点?

    我刚刚研究了 stackoverflow 上所有的 在 R 中寻找交集 问题 它们要么是关于曲线 要么是关于分布像这个 https stackoverflow com questions 20519431 finding point of
  • `dplyr::_join` 函数的命名向量“by”参数[重复]

    这个问题在这里已经有答案了 我正在写一个函数dplyr join两个数据框by不同的列 第一个数据帧的列名称动态指定为函数参数 我相信我需要使用rlang准引用 元编程 但未能找到可行的解决方案 我很感激任何建议 library dplyr
  • sapply - 保留列名称

    我试图总结数据集中许多不同列 变量 的平均值 标准差等 我已经编写了自己的汇总函数 以准确返回我需要和正在使用的内容sapply立即将此函数应用于所有变量 它工作正常 但是返回的数据帧没有列名 我似乎甚至无法使用列号引用重命名它们 也就是说
  • R - 重塑 - 熔化错误

    我正在尝试融化数据框 但出现了这个奇怪的错误 有什么想法吗 str zx7 data frame 519 obs of 5 variables calday new Date format 2011 01 03 2011 01 04 201
  • 在网格中制作一个矩形图例,并标记行和列

    我有一个 ggplot 我将因子映射到填充和 alpha 如下所示 set seed 47 the data lt data frame value rpois 6 lambda 20 cat1 rep c A B each 3 cat2
  • 在包加载之前如何知道 R 中特定函数属于哪个包?

    例如 我知道许多流行的功能 例如tbl df 我通常不记得它属于哪个包 即data table or dplyr 所以我必须始终记住并加载一个包 但我做不到 tbl df除非我加载了正确的包 在 R 控制台本身加载或安装包之前 有没有办法知
  • data.table 抛出“找不到对象”错误[重复]

    这个问题在这里已经有答案了 我有一个数据表 library data table mydt lt data table index 1 10 当我在全局环境中尝试它时 我可以让它工作 但当我在调试器中或在包测试中使用它时却无法工作 问题是我
  • 为什么`Option`支持`IntoIterator`?

    我试图迭代字符串向量的一个子部分 即Vec
  • 如何为自定义 S3 类实现提取/取子集 ([ [<-, [[ [[<-)] 函数?

    我有一个自定义的 S3 类foo 它在正常的基础上添加了一些自定义行为data frame foo object lt data frame class foo object lt c foo data frame 对于这个类 还应该有一个
  • 使用 MPI 的 Allreduce 对 Python 对象求和

    我正在使用使用 Python 中的字典和计数器构建的稀疏张量数组操作 我想让并行使用这个数组操作成为可能 最重要的是 我最终在每个节点上都有计数器 我想使用 MPI Allreduce 或另一个不错的解决方案 将其添加在一起 例如 使用计数

随机推荐