gpt4 book ai didi

c - R、.Call 函数和 SEXP 结构

转载 作者:太空狗 更新时间:2023-10-29 16:41:31 24 4
gpt4 key购买 nike

我正在为我的问题使用非常具体的模拟退火算法在 R 中构建一个程序包,我对我无法解决的 C 代码和 SEXP 有疑问。我不是 R 方面的专家,我只用了 3 个星期......但我必须这样做。

据我所知,R 中的 .Call 函数通过引用将参数作为 SEXP 结构传递给 C(即它们不重复)。我对吗?如果我在 C 中从第一个需要此 SEXP 结构的函数调用 C 中的另一个函数怎么办? (见示例)。我问是因为其中一个参数很大并且占用了大量空间(10^7 ~ 10^18 双倍,虽然我不会在每次迭代中都使用它们)而且我会多次调用这个函数,所以如果我每次调用它时都会重复此参数,我将耗尽内存。

MWE:

R调用

MySimAn <- function(def_energy, i_pos, T0, Tfinal){
ret <- .Call("CMySimAn",def_energy, i_pos, T0, Tfinal, seq0)
ret
}

C 函数

double Energy(SEXP def_energy, SEXP seq0, int i0){
int i;
double res=0;
for(i=0;i<INTEGER(GET_DIM(seq0))[0];i++){
res += NUMERIC(def_energy)[i0+INTEGER(seq0)[i]];
}
return(res);
}

SEXP CmySimAn(SEXP def_energy, SEXP i_pos, SEXP T0, SEXP Tfinal, SEXP seq0){
SEXP = Ene;
PROTECT(Ene = NEW_NUMERIC(1));
REAL(Ene)[0] = Energy(def_energy, seq0, INTEGER(i_pos));
UNPROTECT(1);
return Ene;
}

这样的事情可行吗(Energy 函数中的代码没有被检查,所以可能是错误的)?我每次调用它时都会创建 def_energy 的副本吗,无论是在 R 还是 C 中?非常感谢您的帮助。

最佳答案

代码几乎(语法上)正确,没有内存复制;从 R 传递给 C 的参数应被视为“只读”。

一个常见的范例是编写一个 R/C 接口(interface)层,在纯(非 R)C 中从该层调用任何函数。所以

double Energy(const double *def_energy, const int *seq0, int dim0, int i0)
{
int i;
double res=0;
for(i = 0; i < dim0; i++) {
res += def_energy[i0 + seq0[i]];
}
return(res);
}

使用 const 来强制执行从 R 传递的值不应被写入的隐式契约。用 R/C 包装器

SEXP CmySimAn(SEXP def_energy, SEXP i_pos, SEXP T0, SEXP Tfinal, SEXP seq0){
double Ene = Energy(REAL(def_energy), INTEGER(seq0), INTEGER(GET_DIM(seq0)[0]),
INTEGER(i_pos)[0]);
return ScalarReal(Ene);
}

数字元素的访问器是 REAL()(您在 Energy 中使用了 NUMERIC)。您对 PROTECT(...); 的使用实数(烯)[0] = ...; UNPROTECT(Ene); 是正确的。

关于c - R、.Call 函数和 SEXP 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19049208/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com