繁体   English   中英

Rcpp R 向量大小限制(不允许负长度向量)

[英]Rcpp R vector size limit (negative length vectors are not allowed)

As per https://stackoverflow.com/a/48676389/3846213 and https://stackoverflow.com/a/5234293/3846213 R vectors are limited 2^31 - 1 items. 但是,我已经能够通过 Rcpp 以该数字的一半触发“不允许负长度向量”错误(这应该是试图分配过大向量的标志)。 这一切都来自我尝试调试基于 Rcpp 的 R package ( https://github.com/tpq/propr/issues )。

library(Rcpp)

cppFunction("
IntegerVector test(int size) {
    int veclen = size * (size - 1) / 2;
    IntegerVector vec(veclen);
    return vec;
}
")

vec <- test(47000)
Error in test(47000) : negative length vectors are not allowed

47000^2 / 2 几乎是 2^31 的一半。 我在纯 R 中没有遇到此类问题,即vec <- 1:(47000*(47000-1)/2)运行良好,因此 Rcpp 应该有一些特别之处。

问题是乘法溢出。 当你这样做

size * (size - 1) / 2

操作顺序会咬你,因为

size * (size - 1)

即使整体表达式没有溢出,也可能溢出。 我们可以通过添加打印语句来看到这一点:

IntegerVector test(int size) {
    int veclen = size * (size - 1) / 2;
    Rcpp::Rcout << veclen << std::endl;
    IntegerVector vec(veclen);
    return vec;
}
vec <- test(47000)
# -1043007148

因此,我们可以通过改变我们执行该操作的方式来修复它:

IntegerVector test(int size) {
    int veclen = (size / 2) * (size - 1);
    Rcpp::Rcout << veclen << std::endl;
    IntegerVector vec(veclen);
    return vec;
}

这没有问题

vec <- test(47000)
# 1104476500
str(vec)
# int [1:1104476500] 0 0 0 0 0 0 0 0 0 0 ...

更新:奇数的问题

Eli Korvigo在关于 integer 奇数除法行为的评论中提出了一个很好的观点。 为了说明,考虑用偶数 4 和奇数 5 调用 function

even <- 4
odd  <- 5

even * (even - 1) / 2
# [1] 6
odd  * (odd  - 1) / 2
# [1] 10

它应该分别创建长度为 6 和 10 的向量。 但是,会发生什么?

test(4)
# 6
# [1] 0 0 0 0 0 0
test(5)
# 8
# [1] 0 0 0 0 0 0 0 0

不好了! integer 除法中的5 / 2是 2,而不是 2.5,所以在奇怪的情况下,这并不能完全满足我们的要求。 然而,幸运的是,我们可以通过简单的流控制轻松解决这个问题:

IntegerVector test2(int size) {
    int veclen;
    if ( size % 2 == 0 ) {
        veclen = (size / 2) * (size - 1);
    } else {
        veclen = size * ((size - 1) / 2);
    }
    Rcpp::Rcout << veclen << std::endl;
    IntegerVector vec(veclen);
    return vec;
}

我们可以看到这可以很好地处理奇数和偶数情况:

test2(4)
# 6
# [1] 0 0 0 0 0 0
test2(5)
# 10
# [1] 0 0 0 0 0 0 0 0 0 0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM