Подтвердить что ты не робот

Ошибка: использование стека C слишком близко к пределу

Я пытаюсь запустить некоторый довольно глубокий рекурсивный код в R, и он продолжает давать мне эту ошибку:

Ошибка: использование стека C слишком близко к пределу

Мой вывод из CStack_info():

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

У меня много памяти на моей машине, я просто пытаюсь понять, как увеличить CStack для R.

EDIT: Кто-то попросил воспроизвести пример. Вот несколько базовых примеров кода, которые вызывают проблему. Запустив f (1,1), вы получите ошибку. Обратите внимание, что я уже установил -max-ppsize = 500000 и параметры (выражения = 500000), поэтому, если вы не установите их, вы можете получить ошибку об одной из этих двух вещей. Как вы можете видеть, рекурсия может пройти довольно глубоко, и я не знаю, как заставить ее работать последовательно. Спасибо.

f <- function(root=1,lambda=1) {
    x <- c(0,1);
    prob <- c(1/(lambda+1),lambda/(lambda+1));
        repeat {
      if(root == 0) {
        break;
      }
      else {
        child <- sample(x,2,replace=TRUE,prob);
        if(child[1] == 0 && child[2] == 0) {
          break;
        }
        if(child[1] == 1) {
          child[1] <- f(root=child[1],lambda);
        }
        if(child[2] == 1 && child[1] == 0) {
          child[2] <- f(root=child[2],lambda);
        }
      }
      if(child[1] == 0 && child[2] == 0) {
        break;
      }
      if(child[1] == 1 || child[2] == 1) {
        root <- sample(x,1,replace=TRUE,prob);
      }
        }
    return(root)
}
4b9b3361

Ответ 1

Размер стека - это параметр операционной системы, настраиваемый для каждого процесса (см. setrlimit(2)). Насколько я могу судить, вы не можете настроить его изнутри R, но вы можете настроить его из оболочки перед запуском R с помощью команды ulimit. Это работает так:

$ ulimit -s # print default
8192
$ R --slave -e 'Cstack_info()["size"]'
   size 
8388608

8388608 = 1024 * 8192; R печатает то же значение, что и ulimit -s, но в байтах, а не в килобайтах.

$ ulimit -s 16384 # enlarge stack limit to 16 megs
$ R --slave -e 'Cstack_info()["size"]'
    size 
16777216 

Чтобы выполнить постоянную настройку этого параметра, добавьте команду ulimit в файл запуска оболочки, чтобы она выполнялась при каждом входе в систему. Я не могу дать более точные указания, чем это, потому что это зависит от того, какая именно оболочка у вас есть, и прочее., Я также не знаю, как это сделать для входа в графическую среду (что будет актуально, если вы не запускаете R внутри окна терминала).

Ответ 2

Я подозреваю, что, несмотря на ограничение стека, вы получите слишком глубокие рекурсии. Например, с lambda = Inf, f (1) приводит к немедленной рекурсии, неопределенно. Глубина рекурсии кажется случайным блужданием, с некоторой вероятностью г углубления, 1 - г завершения текущей рекурсии. К тому времени, когда вы достигли предела стека, вы сделали множество шагов "глубже". Отсюда следует, что r > 1/2, и очень большой раз вы просто продолжаете рекурсивно.

Кроме того, похоже, что почти невозможно получить аналитическое или, по крайней мере, численное решение даже в условиях бесконечной рекурсии. Можно определить p как вероятность того, что f (1) == 1, написать неявные выражения для "дочерних" состояний после одной итерации и приравнять их к p и решить. p можно затем использовать как шанс успеха в одной ничьей из биномиального распределения.

Ответ 3

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

output_table_subset = mutate(big_data_frame,
     combined_table = paste0(first_part, second_part, col = "_"))

вместо

output_table_subset = mutate(big_data_frame,
     combined_table = paste0(first_part, second_part, sep = "_"))

Принял меня навсегда, чтобы понять это, поскольку я никогда не ожидал, что паста вызовет эту проблему.

Ответ 4

Эта ошибка не из-за памяти, это из-за рекурсии. Функция вызывает себя. Чтобы проиллюстрировать это, вот минимальный пример двух функций, которые вызывают друг друга:

change_to_factor <- function(x){
  x <- change_to_character(x)
  as.factor(x)
} 

change_to_character <- function(x){
  x <- change_to_factor(x)
  as.character(x)
}

change_to_character("1")

Ошибка: использование стека C 7971600 слишком близко к пределу

Функции будут продолжать вызывать друг друга рекурсивно и теоретически никогда не завершатся. Только проверки в вашей системе предотвращают его бесконечное использование и использование всех вычислительных ресурсов вашего компьютера. Вам нужно изменить функции, чтобы они не вызывали себя (или друг друга) рекурсивно.

Ответ 5

Я столкнулся с одной и той же проблемой получения ошибки "C стека слишком близко к пределу" (хотя и для другого приложения, чем тот, который указан пользователем2045093 выше). Я попробовал предложение zwol, но это не сработало.

К моему собственному удивлению, я мог бы решить эту проблему, установив новейшую версию R для OS X (в настоящее время: версию 3.2.3), а также самую новую версию R Studio для OS X (в настоящее время: 0.99.840), так как я работаю с R Studio.

Надеюсь, это может помочь вам.

Ответ 6

Одна из проблем может заключаться в том, что вы вызываете f внутри себя

plop <- function(a = 2){
  pouet <- sample(a)
  plop(pouet)
}
plop()
Erreur : évaluations trop profondément imbriquées : récursion infinie / options(expressions=) ?
Erreur pendant l'emballage (wrapup) : évaluations trop profondément imbriquées : récursion infinie / options(expressions=) ?

Ответ 7

Для всех, я внезапно сталкиваюсь с этим с R 3.6.1 на Windows 7 (64-разрядная версия). Раньше это не было проблемой, и теперь кажется, что ограничения стека появляются повсюду, когда я пытаюсь "сохранить (.)" Данные или даже сделать "save.image(.)". Это как сериализация уничтожает эти стеки.

Я серьезно подумываю вернуться к 3.6.0. Там не случилось.

Ответ 8

Как писал Мартин Морган... Проблема в том, что вы слишком глубоко внутри рекурсии. Если рекурсия вообще не сходится, вам нужно сломать ее самостоятельно. Надеюсь, этот код будет работать, потому что он не протестирован. Однако, по крайней мере, здесь должно быть ясно.

f <- function(root=1,lambda=1,depth=1) {
 if(depth > 256){
  return(NA)
 }
 x <- c(0,1);
 prob <- c(1/(lambda+1),lambda/(lambda+1));
 repeat {
  if(root == 0) {
    break;
  } else {
   child <- sample(x,2,replace=TRUE,prob);
   if(child[1] == 0 && child[2] == 0) {
     break;
   }
   if(child[1] == 1) {
     child[1] <- f(root=child[1],lambda,depth+1);
   }
   if(child[2] == 1 && child[1] == 0) {
     child[2] <- f(root=child[2],lambda,depth+1);
   }
  }
  if(child[1] == NA | child[2] == NA){
   return NA;
  }
  if(child[1] == 0 && child[2] == 0) {
    break;
  }
  if(child[1] == 1 || child[2] == 1) {
    root <- sample(x,1,replace=TRUE,prob);
  }
 }
 return(root)
}

Ответ 9

Еще один способ вызвать ту же проблему:

library(debug)
mtrace(lapply)

Рекурсивный вызов здесь не так очевиден.

Ответ 10

Если вы используете plot_ly, проверьте, какие столбцы вы передаете. Похоже, что для столбцов POSIXdt/ct вы должны использовать as.character() перед передачей в plotly, или вы получите это исключение!