Below is part of a C code I wrote. The function foo
is to be called in R. The code keeps causing R to crash, and I narrowed down the problem to this outer()
function, which is used to compute outer sum or difference. Note the part that is commented out: If I do not comment it out, the function will lead R to crash if each of the arrays contains, say, over 1000 data points. If I comment it out, I can compute outer sum/difference for significantly longer arrays with no problem (e.g, over 100000 data points per array). I wonder what the problem is... Thank you!
#include <R.h>
#include <Rmath.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void outer(double *x1, double *x2, int *n, int operation, double *output){
int i, j;
if(operation==1){
for(i=0; i<*n; i++){
for(j=0; j<*n; j++){
output[(*n)*i+j]=x1[j]+x2[i];
}
}
} else if(operation==2){
for(i=0; i<*n; i++){
for(j=0; j<*n; j++){
output[(*n)*i+j]=x1[j]-x2[i];
//Rprintf("%d ", (*n)*i+j); //<-----------HERE
}
}
}
}
void foo(double *x, double *y, int *npred, int *nsamp){
int oper=2;
double xouter[*nsamp], youter[*nsamp];
double outer_temp_x[(*nsamp)*(*nsamp)], outer_temp_y[(*nsamp)*(*nsamp)];
outer(x, x, nsamp, oper, &outer_temp_x[0]);
outer(y, y, nsamp, oper, &outer_temp_y[0]);
}
//After compiling the code, I use the code below in R to call the function:
dyn.load("foo.so")
x=as.matrix(rnorm(10000))
y=rlnorm(10000)
invisible(.C("foo",
x=as.double(as.vector(x)),
y=as.double(y),
npred=as.integer(ncol(x)),
nsamp=as.integer(length(y))
)
I think it is overunning the stack and causing trouble.
Try this:
void foo(double *x, double *y, int *npred, int *nsamp){
int oper=2;
double xouter[*nsamp], youter[*nsamp];
// The prior code allocated on the stack. Here, we make a pair of calls
// to 'malloc' to allocate memory for the arrays. This gets memory from
// the heap. The stack is fairly limited, but the heap is huge.
// 'malloc' returns a pointer to the allocated memory.
double* outer_temp_x=malloc(sizeof(double)*(*nsamp)*(*nsamp));
double* outer_temp_y=malloc(sizeof(double)*(*nsamp)*(*nsamp));
outer(x, x, nsamp, oper, &outer_temp_x[0]);
outer(y, y, nsamp, oper, &outer_temp_y[0]);
// The downside of allocating on the heap, is that you must release the
// memory at some point. Otherwise you have what's called a "memory leak."
// 'free' is the function to free the memory, and it is called on the
// pointer value returned by 'malloc'.
free(outer_temp_x);
free(outer_temp_y);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With