在 R 的 data.table 中获取随机的内部 selfref 错误

Posted

技术标签:

【中文标题】在 R 的 data.table 中获取随机的内部 selfref 错误【英文标题】:Getting a random internal selfref error in data.table for R 【发布时间】:2013-03-11 15:19:18 【问题描述】:

我喜欢 data.table,它既快速又直观,还有什么比这更好的呢? 唉,这是我的问题:当在 foreach() 循环中引用 data.table 时(使用 doMC 实现),我偶尔会收到以下错误: 附录中的示例

Error in  : 
  Internal error: .internal.selfref prot is not itself an extptr

这里一个恼人的问题是我无法让它以任何一致性重现,但它会在一些长时间(几个小时)的任务中发生,所以我想确保它永远不会发生,如果可能的话。

由于我在每个循环中引用相同的data.tableDT,我尝试在每个循环的开头运行以下命令:

setattr(DT,".internal.selfref",NULL)   

...删除无效/损坏的 self ref 属性。这有效,内部 selfref 错误不再发生。不过,这是一种解决方法。

有解决根本问题的想法吗?

非常感谢您的帮助!

埃里克

附录:缩写 R Session Info 以确认最新版本:

R version 2.15.3 (2013-03-01)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)
other attached packages:
 [1] data.table_1.8.8  doMC_1.3.0

使用模拟数据的示例 -- 您可能必须多次运行 history() 函数(例如,数百次)才能得到错误:

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Load packages and Prepare Data
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
require(data.table)
##this is the package we use for multicore
require(doMC)
##register n-2 of your machine's cores
registerDoMC(multicore:::detectCores()-2) 

## Build simulated data
value.a <- runif(500,0,1)
value.b <- 1-value.a
value <- c(value.a,value.b)
answer.opt <- c(rep("a",500),rep("b",500))
answer.id <- rep( 6000:6499 , 2)
question.id <- rep( sample(c(1001,1010,1041,1121,1124),500,replace=TRUE) ,2)
date <- rep( (Sys.Date() - sample.int(150, size=500, replace=TRUE)) , 2)
user.id <- rep( sample(250:350, size=500, replace=TRUE) ,2)
condition <- substr(as.character(user.id),1,1)
condition[which(condition=="2")] <- "x"
condition[which(condition=="3")] <- "y"

##Put everything in a data.table
DT.full <- data.table(user.id = user.id,
                      answer.opt = answer.opt,
                      question.id = question.id,
                      date = date,
                      answer.id = answer.id,
                      condition = condition,
                      value = value)

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Daily Aggregation Function
##
##a basic function that aggregates all the values from
##all users for every question on a given day:
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
each.day <- function(val.date)
  DT <- DT.full[ date < val.date ]

  #count the number of updates per user (for weighting)
  setkey(DT, question.id, user.id)
  DT <- DT[ DT[answer.opt=="a",length(value),by="question.id,user.id"] ]
  setnames(DT, "V1", "freq")

  #retain only the most recent value from each user on each question
  setkey(DT, question.id, user.id, answer.id)
  DT <- DT[ DT[ ,answer.id == max(answer.id), by="question.id,user.id", ][[3]] ]

  #now get a weighted mean (with freq) of the value for each question
  records <- lapply(unique(DT$question.id), function(q.id) 
    DT <- DT[ question.id == q.id ]
    probs <- DT[ ,weighted.mean(value,freq), by="answer.opt" ]
    return(data.table(q.id = rep(q.id,nrow(probs)),
                      ans.opt = probs$answer.opt,
                      date = rep(val.date,nrow(probs)),
                      value = probs$V1))
  )
  return(do.call("rbind",records))


##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## foreach History Function 
##
##to aggregate accross many days quickly
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
history <- function(start, end)
  #define a sequence of dates
  date.seq <- seq(as.Date(start),as.Date(end),by="day")

  #now run a foreach to get the history for each date
  hist <- foreach(day = date.seq,  .combine = "rbind") %dopar% 
    #setattr(DT,".internal.selfref",NULL) #resolves occasional internal selfref error
    each.day(val.date = day)
  


##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Examples
##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

##aggregate only one day
each.day(val.date = "2012-12-13")

##generate a history
hist.example <- history (start = "2012-11-01", end = Sys.Date())

【问题讨论】:

你能在这里粘贴你的 foreach 循环实现吗(即使它可能不会像你说的那样重现问题)? 重新尝试解决方法,好主意,但它是 setattr 而不是 setattrib。对于 Arun 的正确解决方案,它不需要可靠地可重现,但如果您粘贴代码,我们可能会以正确的方式对其进行压力测试以使其失败。 我看到 doMC 已于 2 月 22 日更新为 1.3.0,data.table 于 3 月 6 日更新为 1.8.8。请确保提供您正在使用的所有内容的版本号前面例如sessionInfo(). setattrib 表示歉意——这是我几周前在给你的脱单建议中的错字! 这个循环和现在一样非常复杂,所以我会制作一个更压缩的模拟版本与你分享——我可能需要一天左右的时间才能完成它跨度> 【参考方案1】:

感谢您的报告和寻找它的所有帮助!现在在 v1.8.11 中修复。来自NEWS:

在多次调用 data.table 的长期运行计算中 重复,有时会出现以下错误,#2647 :Internal error: .internal.selfref prot is not itself an extptr 固定的。感谢 EricStone、StevieP 和 JasonB 提供的(困难的)可重现示例。

可能与分组中的内存泄漏有关,现在也已修复。

修复了分组中长期未解决的(通常很小)内存泄漏问题,#2648。当最后一组小于最大组时,这些大小的差异不会被释放。同样在非平凡的聚合中,每个组返回不同数量的行。大多数用户运行一次分组查询并且永远不会注意到这些,但是任何循环调用分组的人(例如并行运行或基准测试时)都可能会受到影响。添加了测试。 感谢许多人,包括 vc273 和 Y T。Memory leak in data.table grouped assignment by referenceSlow memory leak in data.table when returning named lists in j (trying to reshape a data.table)

【讨论】:

【参考方案2】:

几个月来,一个类似的问题一直困扰着我。也许我们可以通过将我们的经验放在一起来看到一个模式。

我一直在等待发布,直到我可以创建一个可重现的示例。到目前为止不可能。 该错误不会发生在相同的代码位置。在过去,我经常通过重新运行完全相同的代码来避免错误。其他时候,我重新制定了一个表达式并成功地重新运行。无论如何,我很确定这些错误确实是 data.table 内部的。

我已保存最后 4 条错误消息以尝试检测模式(粘贴在下方)。

---------------------------------------------------
[1] "err msg: location 1"
Error in selfrefok(x) : 
  Internal error: .internal.selfref prot is not itself an extptr
Calls: my.fun1 ... $<- -> $<-.data.table -> [<-.data.table -> selfrefok
Execution halted


---------------------------------------------------
[1] "err msg: location 1"
Error in alloc.col(newx) : 
  Internal error: .internal.selfref prot is not itself an extptr
Calls: my.fun1 -> $<- -> $<-.data.table -> copy -> alloc.col
Execution halted


---------------------------------------------------
[1] "err msg: location 2"
Error in shallow(x) : 
  Internal error: .internal.selfref prot is not itself an extptr
Calls: print ... do.call -> lapply -> as.list -> as.list.data.table -> shallow
Execution halted

---------------------------------------------------
[1] "err msg: location 3"
Error in shallow(x) : 
  Internal error: .internal.selfref prot is not itself an extptr
Calls: calc.book.summ ... .rbind.data.table -> as.list -> as.list.data.table -> shallow
Execution halted

与上述示例的另一个相似之处:我在并行线程之间传递 data.tables,因此它们正在被序列化/反序列化。

我会尝试上面提到的“setattr”修复。

希望这会有所帮助,谢谢,杰森

这是对似乎每运行 50-100k 次就会产生 1 次错误的代码段之一的简化​​:

谢谢@MatthewDowle。 data.table 是最有用的。这是一段精简的代码:

require(data.table)
require(xts)

book <- data.frame(name='',
                   s=0,
                   Value=0.0,
                   x=0.0,
                   Qty=0)[0, ]

for (thing in list(1,2,3,4,5)) 

  tmp <- xts(1:5, order.by= make.index.unique(rep(Sys.time(), 5)))
  colnames(tmp) <- 'A'
  tmp <- cbind(coredata(tmp[nrow(tmp), 'A']),
               coredata(colSums(tmp[, 'A'])),
               coredata(tmp[nrow(tmp), 'A']))

  book <- rbind(book,
                data.table(name='ALPHA',
                           s=0*NA,
                           Value=tmp[1],
                           x=tmp[2],
                           Qty=tmp[3]))


类似这样的事情似乎是导致此错误的原因:

Error in shallow(x) : 
  Internal error: .internal.selfref prot is not itself an extptr
Calls: my.function ... .rbind.data.table -> as.list -> as.list.data.table -> shallow
Execution halted

【讨论】:

非常有趣。不要因为您的第一个答案被删除而气馁!我认为钻石模型在技术上删除了它,因为你写的可能不是答案。反正我没删。感谢您提供此信息! 我可以开始用这个信息做一些猜测。但是您没有必须提供可重现的示例。在这种情况下,您可以提供尽可能多的代码。然后我们可以从那里对其进行压力测试。我只需要至少一个运行类似于你的代码骨架。它不需要可靠地崩溃。 如果您回信,请确保使用@MatthewDowle 启动 cmets,否则我不太可能看到它。 我已经提交了一个错误报告,以免忘记:#2647 Intermittent internal selfref error when used with doMC::foreach @JasonB:我正在经历Error in shallow(x): Internal error: .internal.selfref prot is not itself an extptr Calls: print ... do.call -&gt; lapply -&gt; as.list -&gt; as.list.data.table -&gt; shallow,但在一个简单的lapply(没有并行执行)中,如果它可以帮助定位问题的根源......【参考方案3】:

为了重现错误,我有一个script 供你们倾诉并找出这个错误来自哪里。错误显示:

Error in  : 
task 96 failed - "Internal error: .internal.selfref prot is not itself an extptr"
Calls: apply ... system.time -> apply -> FUN -> %dopar% -> <Anonymous>
Execution halted

我正在使用doParallelforeach 注册我的后端。

上下文:我正在 MNIST 手写数字数据集上测试分类器。您可以通过

从我这里获取数据
wget -nc https://www.dropbox.com/s/xr4i8gy11ed8bsh/digit_id_data_and_benchmarks.zip

请务必修改脚本(上图),使其正确指向 load_data.R 并且 load_data.R 正确指向 MNIST 数据——尽管克隆我的 repo 可能更容易,请继续random_gov 分支,然后运行 ​​dt_centric_random_gov.R.

抱歉,我无法制作一个更简单的可重现示例,但就像 @JasonB 的回答一样,在您进行大量计算之前似乎不会弹出此错误。

编辑:我使用上面建议的解决方法重新运行了我的脚本,它似乎顺利完成了。

【讨论】:

谢谢。它正在运行。需要多长时间才会因该错误而失败? 花了几个小时,在一个集群上使用了 8 个核心。我不确定要花多长时间才能赶上一个核心...... 现在已修复。请参阅我的单独答案。感谢您的帮助! 不,谢谢data.table 的速度让我惊叹不已。我希望有更好的文献可以帮助我更精通它。

以上是关于在 R 的 data.table 中获取随机的内部 selfref 错误的主要内容,如果未能解决你的问题,请参考以下文章

R语言对dataframe(data.table)数据分层随机抽样实战

对于 data.table 中的每一行,获取另一个 data.table 中匹配行的随机索引

在双错误类型的连接列中使用 NA 的 data.table 内部/外部连接?

在双错误类型的连接列中使用 NA 的 data.table 内部/外部连接?

R语言data.table导入数据实战:data.table使用by函数进行数据分组(aggregate)并获取分组的第一个数值或者最后一个数值

r语言table显示10