Получение случайной внутренней ошибки selfref в data.table для R

Мне нравится data.table, он быстрый и интуитивно понятный, что может быть лучше? Увы, вот моя проблема: при обращении к data.table внутри цикла foreach() (используя реализацию doMC) я иногда получаю следующую ошибку: ПРИМЕР В ПРИЛОЖЕНИИ

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

Одна из раздражающих проблем здесь заключается в том, что я не могу заставить его воспроизводиться с какой-либо последовательностью, но это произойдет во время некоторых длительных (несколько часов) задач, поэтому я хочу убедиться, что этого никогда не произойдет, если это возможно.

Поскольку я ссылаюсь на одни и те же data.table, DT в каждом цикле, я попытался выполнить следующее в начале каждого цикла:

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

... чтобы удалить недопустимый/поврежденный атрибут самореф. Это работает, и внутренняя ошибка selfref больше не возникает. Однако это обходной путь.

Есть идеи по решению корневой проблемы?

Большое спасибо за любую помощь!

Эрик

Приложение: Сокращенная информация о сеансе R для подтверждения последних версий:

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())

person theEricStone    schedule 11.03.2013    source источник
comment
можете ли вы вставить сюда свою реализацию цикла foreach (даже если она может не воспроизводить проблему, как вы говорите)?   -  person Arun    schedule 11.03.2013
comment
Попытка обходного пути, хорошая идея, но это setattr, а не setattrib. Для правильного решения Arun не нуждается в надежной воспроизводимости, но если вы вставите код, мы, вероятно, сможем правильно провести его стресс-тест, чтобы он не работал.   -  person Matt Dowle    schedule 11.03.2013
comment
И я вижу, что doMC был обновлен до 1.3.0 22 февраля, а data.table до 1.8.8 6 марта. Пожалуйста, не забудьте предоставить номера версий всего, что вы используете, например. sessionInfo().   -  person Matt Dowle    schedule 11.03.2013
comment
И прошу прощения за setattrib - это была моя опечатка в предложении для вас вне списка несколько недель назад!   -  person Matt Dowle    schedule 11.03.2013
comment
цикл довольно сложный, как сейчас, поэтому я буду работать над более сжатой симулированной версией, чтобы поделиться с вами - может пройти день или около того, прежде чем я смогу добраться до него.   -  person theEricStone    schedule 11.03.2013
comment
Звучит неплохо. Тогда обходной путь сработал? Или ему нужно несколько дней, чтобы увидеть, кусает ли он снова, прежде чем быть уверенным? Я не знаю пакет doMC, так что урезанный пример действительно нужен (во всяком случае, мне) для правильного исправления.   -  person Matt Dowle    schedule 11.03.2013
comment
весь процесс занимает около 24 часов, поэтому завтра днем ​​у меня будет обновление вместе с примером для вас.   -  person theEricStone    schedule 12.03.2013
comment
еще раз спасибо за вашу помощь, ребята. мой код работал без проблем, используя обходной путь setattr(), что является отличной новостью. примечание: примера, который я только что опубликовал, должно быть достаточно, чтобы воспроизвести ошибку с достаточным количеством повторений.   -  person theEricStone    schedule 13.03.2013


Ответы (3)


Спасибо за отчет и за помощь в поиске! Теперь исправлено в v1.8.11. Из НОВОСТИ:

При длительных вычислениях, когда data.table вызывается много раз, иногда могла возникать следующая ошибка: #2647 :
Internal error: .internal.selfref prot is not itself an extptr
Исправлено. Спасибо theEricStone, StevieP и JasonB за (сложные) воспроизводимые примеры.

Возможно, это связано с утечкой памяти при группировке, которая теперь также исправлена.

Исправлена ​​давняя (обычно небольшая) утечка памяти в группировке, #2648. Когда последняя группа меньше, чем самая большая группа, разница в этих размерах не выявляется. Также в нетривиальных агрегациях, где каждая группа возвращает разное количество строк. Большинство пользователей запускают запрос группировки один раз и никогда этого не заметят, но любой, кто зацикливает вызовы группировки (например, при параллельном выполнении или тестировании), может пострадать. Добавлены тесты. Спасибо многим, включая vc273 и Y T.
Утечка памяти в data.table сгруппировано по ссылке
Медленная утечка памяти в data.table при возврате именованных списков в j (попытка изменить форму data.table)

person Matt Dowle    schedule 02.01.2014

Аналогичная проблема мучает меня уже несколько месяцев. Возможно, мы сможем увидеть закономерность, объединив наш опыт.

Я ждал публикации, пока не смог создать воспроизводимый пример. Не возможно пока. Ошибка не возникает в том же месте кода. В прошлом мне часто удавалось избежать ошибки, просто повторно запуская тот же самый код. В других случаях я переформулировал выражение и успешно повторил его. В любом случае я почти уверен, что эти ошибки действительно являются внутренними для 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.

надеюсь, это поможет, и спасибо, Джейсон

вот упрощение одного из сегментов кода, который, кажется, генерирует эту ошибку 1 из каждых 50-100 тысяч раз, когда он запускается:

спасибо @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
person JasonB    schedule 24.03.2013
comment
Очень интересно. Не расстраивайтесь из-за того, что ваш самый первый ответ будет удален! Я думаю, что алмазный мод удалил его по техническим причинам, поскольку вы написали, что это, возможно, не ответ. Во всяком случае, я восстановил его. Спасибо за эту информацию! - person Matt Dowle; 26.03.2013
comment
Я могу начать делать некоторые предположения с этой информацией. Но вам не обязательно приводить воспроизводимый пример. В таких случаях вы можете просто предоставить как можно больше кода. Затем мы можем провести стресс-тест оттуда. Мне просто нужен хотя бы скелет кода, который работает аналогично вашему. Ему не нужно надежно падать. - person Matt Dowle; 26.03.2013
comment
Если вы ответите, пожалуйста, не забудьте начать комментарии с @MatthewDowle, иначе я вряд ли это увижу. - person Matt Dowle; 26.03.2013
comment
Я подал отчет об ошибке, чтобы не забыть: #2647 Периодическая внутренняя ошибка selfref при использовании с doMC::foreach - person Matt Dowle; 28.03.2013
comment
@JasonB: Я испытываю 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, но в простом lapply (без параллельного выполнения), если это может помочь локализовать источник проблемы... - person leodido; 19.04.2013
comment
@MatthewDowle У меня тоже похожие проблемы. У меня есть ошибка в цикле for Error in shallow(x) : Internal error: .internal.selfref prot is not itself an extptr, проблема в том, что когда я пытаюсь его отладить, ошибка исчезает, и цикл завершается правильно. Когда он появился, он испортил весь день расчетов. - person user974514; 19.04.2013
comment
@leodido Просто лапли (без параллели)? Да это полезно. Есть ли шанс что-то воспроизводимое я могу запустить? Это не обязательно должно быть что-то, что надежно дает сбой (хотя это было бы идеально), но что-то, что вы считаете близким, в порядке. - person Matt Dowle; 19.04.2013
comment
@user974514 user974514 Жаль это слышать. Вы используете его с doMC::foreach или, как у леодидо, проблема с чем-то другим? Что-нибудь воспроизводимое (или близкое)? Я повысил приоритет ошибки (#2647). - person Matt Dowle; 19.04.2013
comment
@MatthewDowle, я использую простые циклы for. На самом деле найти матрицу сходства путем слияния разных частей набора данных. Я мог бы предоставить код, но без знания структуры данных было бы проблематично его прочитать. - person user974514; 19.04.2013
comment
@MatthewDowle Насколько я могу понять, проблема возникает с огромными наборами данных (хотя это цель data.table). В моем примере он остановился на 380-й итерации. R версия 2.15.2, таблица данных 1.8.8 - person user974514; 19.04.2013
comment
@ user974514 Если вы можете предоставить код, то это лучше, чем ничего. По крайней мере, это может дать мне подсказку. - person Matt Dowle; 19.04.2013
comment
@MattDowle Я также столкнулся с этим при использовании foreach, попытаюсь использовать обходной путь setattr(DT,.internal.selfref,NULL) и дам вам знать - person Juancentro; 04.11.2013
comment
Исправлено сейчас. Смотрите новый ответ. Спасибо всем за вашу помощь! - person Matt Dowle; 03.01.2014

Чтобы воспроизвести ошибку, у меня есть скрипт для вы, ребята, разберитесь и выясните, откуда эта ошибка. Ошибка гласит:

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

и я использую doParallel для регистрации моего бэкенда для foreach.

Контекст: я тестирую классификаторы на наборе рукописных цифр MNIST. Вы можете получить данные от меня через

wget -nc https://www.dropbox.com/s/xr4i8gy11ed8bsh/digit_id_data_and_benchmarks.zip

просто не забудьте изменить скрипт (выше), чтобы он правильно указывал на load_data .R и load_data.R правильно указывают на данные MNIST — хотя вам может быть проще просто клонировать мой репозиторий, перейти на ветку random_gov, а затем запустить dt_centric_random_gov.R.

Извините, я не смог сделать более минимальный воспроизводимый пример, но, как и в ответе @JasonB, эта ошибка, похоже, не появляется, пока вы не выполните массу вычислений.

изменить: я повторно запустил свой сценарий, используя предложенный выше обходной путь, и он, похоже, прошел без сучка и задоринки.

person StevieP    schedule 19.12.2013
comment
Спасибо. Он работает. Сколько времени должно пройти, прежде чем он выйдет из строя с этой ошибкой? - person Matt Dowle; 28.12.2013
comment
Это заняло несколько часов, используя 8 ядер на кластере. Я не уверен, сколько времени потребуется, чтобы поймать одно ядро ​​​​... - person StevieP; 03.01.2014
comment
Исправлено сейчас. Смотрите отдельный ответ от меня. Спасибо за вашу помощь! - person Matt Dowle; 03.01.2014
comment
Нет, спасибо! data.table не перестает удивлять меня своей скоростью. Я бы хотел, чтобы была лучшая литература, которая помогла бы мне немного разобраться в этом. - person StevieP; 03.01.2014