On 12/09/12 06:56, Christian Gunning wrote:
On Tue, Sep 11, 2012 at 3:00 AM,
<rcpp-devel-requ...@lists.r-forge.r-project.org> wrote:
It seems to be the casethat when the memory issue occurs, garbage
collection has just been called by R, at least according to gcinfo.In
particular, it is called when bar is called and cleans up the arguments
that bar is about to use, thus causing a problem.
Is there a way to ensure the safety of the arguments that are sent back
to R?
I've gotten in the habit of being very explicit with Rcpp -- limiting
the use of nested functions, doing one step per line. I'm don't
understand the internals enough to understand the exact
metaprogramming/template details, and I've often seen "odd behavior"
disappear when I unpack a long, complicated line into component lines
of code. This is similar to Dirk's comment about limiting use of
temps.
Also, have you looked at Armadillo for submatrix access? You can
easily pull out columns/rows into NumericVectors. Sometimes I find
the logical separation between pure C++ (arma) and chameleon SEXP/Rcpp
conceptually helpful.
Curious to hear your results,
Christian
University of New Mexico
So, in my actual application this hasn't caused any major problems as I
have tried to avoid creating too many temporary vectors, following
Dirk's suggestion.However, the code seems like it should be able to
fail, albeit rarely, which is at least slightly worrying.
Getting rid of the matrices and using lists so to avoid temporaries is
also helpful. See the below code (foo.good), which doesn't seem to fail
for me.
I also discovered that foo.bad actually fails not when the arguments are
passed into R but when the return value is passed back to Rcpp (with an
accompanying garbage collection).
Code:
library(inline)
foo.bad <- cxxfunction(
signature(N_in = "numeric", n_in = "numeric", bar_in = "function"),
body='
BEGIN_RCPP
int N = as<int>(N_in);
int n = as<int>(n_in);
Function bar(bar_in);
IntegerMatrix A(N,n);
A(_,0) = seq_len(N);
IntegerVector temp_out(N);
IntegerVector temp_in(N);
for (int i = 1; i < n; i++) {
// std::cerr << "entering bar" << std::endl;
A(_,i) = as<IntegerVector>(bar(A(_,i-1),N,true));
// std::cerr << "left bar" << std::endl;
}
return wrap(A);
END_RCPP
', plugin = "Rcpp" )
foo.good <- cxxfunction(
signature(N_in = "numeric", n_in = "numeric", bar_in = "function"),
body='
BEGIN_RCPP
int N = as<int>(N_in);
int n = as<int>(n_in);
Function bar(bar_in);
List A(n);
A[0] = seq_len(N);
IntegerVector temp_out(N);
IntegerVector temp_in(N);
for (int i = 1; i < n; i++) {
// std::cerr << "entering bar" << std::endl;
A[i] = bar(A[i-1],N,true);
// std::cerr << "left bar" << std::endl;
}
return wrap(A);
END_RCPP
', plugin = "Rcpp" )
bar <- function(vs,M,cond) {
# print("entered bar")
if (cond) {
ret <- (vs + 1) %% M
} else {
ret <- (vs - 1) %% M
}
# print(mean(ret))
# print("leaving bar")
return(ret)
}
runCode <- function(f,K) {
for (k in 1:K) {
for (i in 1:5) {
for (j in 1:10) {
# print(paste(i,j,sep=" "));
B <- f(i*100,j*100,bar);
}
}
}
}
# gcinfo(TRUE)
print("running foo.good:")
runCode(foo.good,5)
print("running foo.bad:")
runCode(foo.bad,5)
_______________________________________________
Rcpp-devel mailing list
Rcpp-devel@lists.r-forge.r-project.org
https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel