
[英]CRAN package submission: "Error: C stack usage is too close to the limit"
[英]Error: C stack usage is too close to the limit
我试图在 R 中运行一些相当深的递归代码,但它一直给我这个错误:
错误:C 堆栈使用量太接近限制
我从CStack_info()
输出的是:
Cstack_info()
size current direction eval_depth
67108864 8120 1 2
我的机器上有足够的内存,我只是想弄清楚如何增加 R 的 CStack。
编辑:有人要求提供一个可重现的例子。 下面是导致问题的一些基本示例代码。 运行 f(1,1) 几次你会得到错误。 请注意,我已经设置了 --max-ppsize = 500000 和 options(expressions=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)
}
堆栈大小是一个操作系统参数, setrlimit(2)
进程调整(请参阅setrlimit(2)
)。 据我所知,您无法在 R 中调整它,但是您可以在启动 R 之前使用ulimit
命令从 shell 中调整它。 它是这样工作的:
$ 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
命令添加到您的 shell 启动文件中,以便在您每次登录时执行。我不能给出比这更具体的说明,因为这取决于您拥有的 shell 和内容. 我也不知道如何登录图形环境(如果您不在终端窗口中运行 R,这将是相关的)。
我怀疑,无论堆栈限制如何,您最终都会得到太深的递归。 例如,当 lambda = Inf 时,f(1) 导致无限期的立即递归。 递归的深度似乎是随机游走,有一些概率 r 更深,完成当前递归的概率为 1 - r。 当您达到堆栈限制时,您已经“深入”了大量步骤。 这意味着 r > 1 / 2,并且大部分时间您将继续递归。
此外,即使面对无限递归,似乎也几乎可以推导出解析解或至少是数值解。 可以将 p 定义为 f(1) == 1 的概率,在单次迭代后为“子”状态编写隐式表达式,并将它们与 p 相等,然后求解。 然后可以将 p 用作二项式分布中单次抽奖的成功机会。
这个错误不是由于内存,而是由于递归。 一个函数正在调用自身。 为了说明这一点,以下是两个相互调用的函数的最小示例:
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 太接近限制
这些函数将继续递归地相互调用,理论上永远不会完成。 只有在您的系统内进行检查才能防止这种情况无限期地发生并消耗您机器的所有计算资源。 您需要更改函数以确保它们不会递归调用自身(或相互调用)。
这发生在我身上的原因完全不同。 我在组合两列时不小心创建了一个超长字符串:
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 = "_"))
让我永远弄明白了,因为我从没想到糊状物会导致问题。
我遇到了同样的问题,即收到“C 堆栈使用率太接近限制”错误(尽管是针对另一个应用程序而不是上面 user2045093 所述的应用程序)。 我尝试了 zwol 的建议,但没有成功。
令我惊讶的是,我可以通过为 OS X 安装最新版本的 R(当前:版本 3.2.3)以及用于 OS X 的最新版本的 R Studio(当前:0.99.840)来解决这个问题,因为我我正在与 R Studio 合作。
希望这也可以对您有所帮助。
这里的一个问题可能是你在内部调用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=) ?
对于每个人的信息,我突然在 Windows 7(64 位)上使用 R 3.6.1 遇到了这个问题。 以前这不是问题,现在堆栈限制似乎无处不在,当我尝试“save(.)”数据甚至执行“save.image(.)”时。 这就像序列化正在吹散这些堆栈。
我正在认真考虑回退到 3.6.0。 没有发生在那里。
我的可能是一个更独特的案例,但可能会帮助少数遇到这个问题的人:
我的情况与空间使用完全无关,仍然 R 给出了:
C stack usage is too close to the limit
我有一个定义的函数,它是基本函数的升级:
保存RDS()
但,
偶然地,这个定义的函数被称为saveRDS()
而不是safe_saveRDS()
。
因此,超过该定义,当代码到达实际使用saveRDS(...)
(调用原始基本版本,而不是升级版本saveRDS(...)
,它给出了上述错误并被粉碎。
因此,如果您在调用某个保存函数时遇到该错误,请查看您是不是不小心碰到了它。
我经常在 R 脚本的顶部添加注释掉的source("path/to/file/thefile.R")
行,例如thefile.R
,因此我可以轻松地将其复制粘贴到终端中以运行它。 如果我忘记注释掉该行,我会收到此错误,因为运行该文件会运行该文件,该文件会运行该文件,该文件会运行该文件,...
如果这是原因,解决方案很简单:注释掉该行。
正如 Martin Morgan 所写......问题是你对递归的了解太深了。 如果递归根本不收敛,则需要自行破解。 我希望这段代码可以工作,因为它没有经过测试。 但是,至少在这里应该清楚一点。
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)
}
导致相同问题的另一种方法:
library(debug)
mtrace(lapply)
递归调用在这里并不那么明显。
如果您使用 plot_ly 检查您正在传递哪些列。 似乎对于 POSIXdt/ct 列,您必须在传递给 plotly 之前使用 as.character() 否则您会收到此异常!
不确定我们是否在这里列出问题,但它发生在我的leaflet()
。 我试图映射一个数据POSIXlt
,其中date
列是POSIXlt
类。 改回POSIXct
解决了这个问题。
在 Linux 上,我通过这样做永久增加了堆栈和 memlock 内存的大小:
sudo vi /etc/security/limits.conf
然后,在文件末尾添加以下几行。
* soft memlock unlimited
* hard memlock unlimited
* soft stack unlimited
* hard stack unlimited
这是我遇到此错误消息的方式。 当我尝试在控制台中打印 data.table 时遇到此错误消息。 原来是因为我错误地在列中创建了一个超超长字符串(在不应该使用的 paste() 中使用了折叠)。
package caret
有一个名为createDataPartition
的 function,当要分区的数据集超过 1m 行时,它总是会导致错误。 仅供参考。
我遇到了同样的问题。 无需重新安装 R 或 Rstudio。 这是一个超级简单的解决方案 -
如果您在 bR 内采购 aR,同时在 aR 内采购 bR,那么堆栈将很快填满。
问题
This is the first file a.R where b.R is sourced
#---- a.R File -----
source("/b.R")
...
...
#--------------------
This is the second file b.R, where a.R is sourced
#---- b.R File -----
source("/a.R")
...
...
#--------------------
解决方案
#---- a.R File -----
source("/b.R")
...
...
#--------------------
#---- b.R File -----
...
...
#--------------------
要么
#---- a.R File -----
...
...
...
#--------------------
#---- b.R File -----
source("/a.R")
...
...
#--------------------
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.