重复调用 C 函数会导致 R 崩溃 - 如何分配内存?
Repeated call to C function crashes R - how to allocate memory?
如果我重复调用 C 函数(从 R),我会遇到 R 崩溃。
我是编写 C 函数的新手,我认为我遇到的 R 崩溃问题是 C 中的内存分配。我知道可以释放 C 中的内存,但我不知道如何确切地以及在哪些参数上。有人可以帮我吗?
我将在这里 post 一个工作示例,并在最后再次 issue/question。
这是 C 代码(致谢:该代码基于 Marteen Speeklenbrink (https://github.com/rforge/mcplr) 的 mcplr 包的代码。
#include <Rmath.h>
void gcmval(int *y, int *ny, double *x, int *nx, double *v, double *p, int *bt, int *et, double *w, double *r, double *q, double *lambda, double *theta, double *dist, double *sim, double *val, double *vpred, double *ypred)
{
double syp = 0.0;
double svp = 0.0;
for(int t=*bt; t < *et; t++) {
for(int j=0; j < *ny; j++) sim[j] = 0.0;
svp = 0.0;
for(int tt=*bt-1; tt < t; tt++) {
dist[tt] = 0.0;
for(int i=0; i < *nx; i++) {
dist[tt] += w[i] * pow( fabs(x[i + tt * *nx] - x[i + t * *nx ]), *r);
}
dist[tt] = pow(dist[tt], *q / *r);
val[tt] = exp(-1 * *lambda *dist[tt]) * v[tt];
for(int j=0; j < *ny; j++) {
if(y[j + tt * *ny] == 1) sim[j] += exp(-1 * *lambda * dist[tt]);
}
svp += val[tt];
}
syp = 0.0;
for(int j=0; j < *ny; j++) {
syp += sim[j];
}
vpred[t] = svp / syp;
ypred[t] = 1.0 / (1.0 + exp(-1 * *theta * (vpred[t] - p[t])));
}
}
R代码
这是一个工作示例,它使用我们刚刚在 R 中的 C 中定义的函数。如果我反复调用对 .C 的调用,R 将崩溃(在 Windows 10 上)。需要反复调用,不知道内存怎么分配。
if(.Platform$OS.type == "windows"){
dyn.load("gcmval.dll")
} else if(.Platform$OS.type %in% c("mac","unix")){
dyn.load("gcmval.so")
}
# Some fake input data
dt <- data.table(f1 = c(1,1,0,0,1,0),
f2 = c(1,1,0,0,1,0),
f3 = c(1,1,0,0,0,1),
choices = c(0,0,1,1,0,1),
prices = c(1,1,3,3,2,2),
values = c(.9,.9,3.1,3.1,1.5,2.5))
# Next lines just prepare the variables for the C-function
y <- rbind(t(dt$choices), 1-t(dt$choices))
x <- t(dt[,1:3])
w <- rep(1/3,3)
v <- dt$values
p <- dt$prices
nx <- nrow(x)
ny <- nrow(y)
nt <- ncol(x)
bt <- 1
et <- nt
lambda <- 1
theta <- 1
r <- 1
q <- 1
pv <- vector("double", length = nt)
py <- vector("double", length = nt)
val <- vector("double",length=nt)
dist <- vector("double",length=nt)
sim <- vector("double",length=ny)
val <- vector("double",length=ny)
# Run this code repeatedly, it crashes R
tmp <- .C("gcmval",
y=as.integer(y),
ny=as.integer(ny),
x=as.double(x),
nx=as.integer(nx),
v=as.double(v),
p=as.double(p),
bt=as.integer(bt),
et=as.integer(et),
w=as.double(w),
r=as.double(r),
q=as.double(q),
lambda=as.double(lambda),
theta=as.double(theta),
dist=as.double(dist),
sim=as.double(sim),
val=as.double(val),
vpred=as.double(pv),
ypred=as.double(py)
)
我认为R_alloc是我的朋友,但我无法应用它。
如果有人能帮助我大致了解 introduction/explanation 如何准确使用 R_alloc 函数,我将非常高兴(编写 r 扩展教程中有一些神秘的示例,但我可以不解析它们),或内存分配如何工作的任何一般解释(对于熟悉 R 但自学成才的程序员)。
提前感谢您的帮助
/贾娜
问题是您将向量 val
定义了两次:
val <- vector("double",length=nt)
dist <- vector("double",length=nt)
sim <- vector("double",length=ny)
val <- vector("double",length=ny)
在第二个定义中,长度不正确,因为 val
必须与 dist
具有相同的长度,而不是 sim
。如果我删除第二个定义,崩溃就会消失。
我觉得很有意思,就是重复调用才触发崩溃。我可以通过调用 tmp
或 gc()
.
立即触发它
如果我重复调用 C 函数(从 R),我会遇到 R 崩溃。
我是编写 C 函数的新手,我认为我遇到的 R 崩溃问题是 C 中的内存分配。我知道可以释放 C 中的内存,但我不知道如何确切地以及在哪些参数上。有人可以帮我吗?
我将在这里 post 一个工作示例,并在最后再次 issue/question。
这是 C 代码(致谢:该代码基于 Marteen Speeklenbrink (https://github.com/rforge/mcplr) 的 mcplr 包的代码。
#include <Rmath.h>
void gcmval(int *y, int *ny, double *x, int *nx, double *v, double *p, int *bt, int *et, double *w, double *r, double *q, double *lambda, double *theta, double *dist, double *sim, double *val, double *vpred, double *ypred)
{
double syp = 0.0;
double svp = 0.0;
for(int t=*bt; t < *et; t++) {
for(int j=0; j < *ny; j++) sim[j] = 0.0;
svp = 0.0;
for(int tt=*bt-1; tt < t; tt++) {
dist[tt] = 0.0;
for(int i=0; i < *nx; i++) {
dist[tt] += w[i] * pow( fabs(x[i + tt * *nx] - x[i + t * *nx ]), *r);
}
dist[tt] = pow(dist[tt], *q / *r);
val[tt] = exp(-1 * *lambda *dist[tt]) * v[tt];
for(int j=0; j < *ny; j++) {
if(y[j + tt * *ny] == 1) sim[j] += exp(-1 * *lambda * dist[tt]);
}
svp += val[tt];
}
syp = 0.0;
for(int j=0; j < *ny; j++) {
syp += sim[j];
}
vpred[t] = svp / syp;
ypred[t] = 1.0 / (1.0 + exp(-1 * *theta * (vpred[t] - p[t])));
}
}
R代码 这是一个工作示例,它使用我们刚刚在 R 中的 C 中定义的函数。如果我反复调用对 .C 的调用,R 将崩溃(在 Windows 10 上)。需要反复调用,不知道内存怎么分配。
if(.Platform$OS.type == "windows"){
dyn.load("gcmval.dll")
} else if(.Platform$OS.type %in% c("mac","unix")){
dyn.load("gcmval.so")
}
# Some fake input data
dt <- data.table(f1 = c(1,1,0,0,1,0),
f2 = c(1,1,0,0,1,0),
f3 = c(1,1,0,0,0,1),
choices = c(0,0,1,1,0,1),
prices = c(1,1,3,3,2,2),
values = c(.9,.9,3.1,3.1,1.5,2.5))
# Next lines just prepare the variables for the C-function
y <- rbind(t(dt$choices), 1-t(dt$choices))
x <- t(dt[,1:3])
w <- rep(1/3,3)
v <- dt$values
p <- dt$prices
nx <- nrow(x)
ny <- nrow(y)
nt <- ncol(x)
bt <- 1
et <- nt
lambda <- 1
theta <- 1
r <- 1
q <- 1
pv <- vector("double", length = nt)
py <- vector("double", length = nt)
val <- vector("double",length=nt)
dist <- vector("double",length=nt)
sim <- vector("double",length=ny)
val <- vector("double",length=ny)
# Run this code repeatedly, it crashes R
tmp <- .C("gcmval",
y=as.integer(y),
ny=as.integer(ny),
x=as.double(x),
nx=as.integer(nx),
v=as.double(v),
p=as.double(p),
bt=as.integer(bt),
et=as.integer(et),
w=as.double(w),
r=as.double(r),
q=as.double(q),
lambda=as.double(lambda),
theta=as.double(theta),
dist=as.double(dist),
sim=as.double(sim),
val=as.double(val),
vpred=as.double(pv),
ypred=as.double(py)
)
我认为R_alloc是我的朋友,但我无法应用它。
如果有人能帮助我大致了解 introduction/explanation 如何准确使用 R_alloc 函数,我将非常高兴(编写 r 扩展教程中有一些神秘的示例,但我可以不解析它们),或内存分配如何工作的任何一般解释(对于熟悉 R 但自学成才的程序员)。
提前感谢您的帮助 /贾娜
问题是您将向量 val
定义了两次:
val <- vector("double",length=nt)
dist <- vector("double",length=nt)
sim <- vector("double",length=ny)
val <- vector("double",length=ny)
在第二个定义中,长度不正确,因为 val
必须与 dist
具有相同的长度,而不是 sim
。如果我删除第二个定义,崩溃就会消失。
我觉得很有意思,就是重复调用才触发崩溃。我可以通过调用 tmp
或 gc()
.