[Rcpp-devel] How to modifying the elements of a list in the global environment?
Dirk Eddelbuettel
edd at debian.org
Fri Oct 19 00:46:52 CEST 2012
Hi Giovanni,
And welcome!
On 18 October 2012 at 22:13, Giovanni Petris wrote:
| Hello!
|
| I am very new to Rcpp and C++, although I have some experience with the C/R interface, so please bear with me...
|
| In the context of a Gibbs sampler for a multivariate normal mixture model, I need to center all the observations by the mean of each component of the mixture. In pure R I have a function similar to the one below.
|
| > ### Small reproducible example
| > K <- 2; N <- 5; M <- 3
| > x <- matrix(rnorm(N * M), N, M)
| > mu <- matrix(rnorm(M * K, mean = 1 : K), M, K, TRUE)
| >
| > ### What I would do in R
| > f_R <- function() {
| + ## center observations in 'x' using columns of 'mu'
| + w <- lapply(1L:K, function(i) x - rep(mu[, i], each = N))
| + ## eventually more stuff here...
| + w
| + }
|
| I am trying to transport the code to Rcpp. However, since K, M, and N may be large and I am running a possibly large number of iterations of a Gibbs sampler, I want to use a list in the global environment as working space so as to avoid creating and destroying large matrices at every Gibbs sampler iteration. So I do the following
|
| > ### For the Rcpp part, set aside working space in the global environment
| > workspace <- lapply(1:K, function(k) matrix(0.0, N, M))
1) See if you can find a gentle C++ tutorial, passing objects by reference
has essentially no cost. Working with global object is really not good
style, and you really don't need it.
2) Similarly, you don;t need to preallocate memory. You can do that at the
C++ level via NumericVector, NumericMatrix, ... and it is just as efficient.
| Then I try to access the matrices in the 'workspace' list and modify them, but so far I have had no success. The first attemp, bolow, does not compile...
I'll may have a chance to look at that later...
Dirk
| > code_f <- '
| + Rcpp::NumericMatrix cpp_x(x);
| + Rcpp::NumericMatrix cpp_mu(mu);
| + int K = cpp_mu.ncol();
| + int M = cpp_mu.nrow();
| + int N = cpp_x.nrow();
| + Environment glob = Environment::global_env();
| + List cpp_work(glob.get("workspace"));
| +
| + for (int k=0; k < K; k++) {
| + cpp_work[k] = clone(cpp_x);
| + for (int i=0; i < M; i++)
| + cpp_work(_, i) = cpp_work(_, i) - cpp_mu(i, k);
| + }
| +
| + return R_NilValue;
| + '
| > ## the following does not compile
| > library(Rcpp); library(inline)
| > f_cpp <- cxxfunction(signature(x = "numeric", mu = "numeric"), code_f, plugin = "Rcpp")
| file70363a0a2d30.cpp: In function ‘SEXPREC* file70363a0a2d30(SEXP, SEXP)’:
| file70363a0a2d30.cpp:42:26: error: invalid conversion from ‘SEXP’ to ‘size_t {aka unsigned int}’ [-fpermissive]
| /usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:403:18: error: initializing argument 1 of ‘Rcpp::Vector<RTYPE>::Proxy Rcpp::Vector<RTYPE>::operator()(const size_t&, const size_t&) [with int RTYPE = 19, Rcpp::Vector<RTYPE>::Proxy = Rcpp::internal::generic_proxy<19>, size_t = unsigned int]’ [-fpermissive]
| file70363a0a2d30.cpp:42:43: error: invalid conversion from ‘SEXP’ to ‘size_t {aka unsigned int}’ [-fpermissive]
| /usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:403:18: error: initializing argument 1 of ‘Rcpp::Vector<RTYPE>::Proxy Rcpp::Vector<RTYPE>::operator()(const size_t&, const size_t&) [with int RTYPE = 19, Rcpp::Vector<RTYPE>::Proxy = Rcpp::internal::generic_proxy<19>, size_t = unsigned int]’ [-fpermissive]
| make: *** [file70363a0a2d30.o] Error 1
|
| ERROR(s) during compilation: source code errors or compiler configuration errors!
|
| Program source:
| 1:
| 2: // includes from the plugin
| 3:
| 4: #include <Rcpp.h>
| 5:
| 6:
| 7: #ifndef BEGIN_RCPP
| 8: #define BEGIN_RCPP
| 9: #endif
| 10:
| 11: #ifndef END_RCPP
| 12: #define END_RCPP
| 13: #endif
| 14:
| 15: using namespace Rcpp;
| 16:
| 17:
| 18: // user includes
| 19:
| 20:
| 21: // declarations
| 22: extern "C" {
| 23: SEXP file70363a0a2d30( SEXP x, SEXP mu) ;
| 24: }
| 25:
| 26: // definition
| 27:
| 28: SEXP file70363a0a2d30( SEXP x, SEXP mu ){
| 29: BEGIN_RCPP
| 30:
| 31: Rcpp::NumericMatrix cpp_x(x);
| 32: Rcpp::NumericMatrix cpp_mu(mu);
| 33: int K = cpp_mu.ncol();
| 34: int M = cpp_mu.nrow();
| 35: int N = cpp_x.nrow();
| 36: Environment glob = Environment::global_env();
| 37: List cpp_work(glob.get("workspace"));
| 38:
| 39: for (int k=0; k < K; k++) {
| 40: cpp_work[k] = clone(cpp_x);
| 41: for (int i=0; i < M; i++)
| 42: cpp_work(_, i) = cpp_work(_, i) - cpp_mu(i, k);
| 43: }
| 44:
| 45: return R_NilValue;
| 46:
| 47: END_RCPP
| 48: }
| 49:
| 50:
| Error in compileCode(f, code, language = language, verbose = verbose) :
| Compilation ERROR, function(s)/method(s) not created! file70363a0a2d30.cpp: In function ‘SEXPREC* file70363a0a2d30(SEXP, SEXP)’:
| file70363a0a2d30.cpp:42:26: error: invalid conversion from ‘SEXP’ to ‘size_t {aka unsigned int}’ [-fpermissive]
| /usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:403:18: error: initializing argument 1 of ‘Rcpp::Vector<RTYPE>::Proxy Rcpp::Vector<RTYPE>::operator()(const size_t&, const size_t&) [with int RTYPE = 19, Rcpp::Vector<RTYPE>::Proxy = Rcpp::internal::generic_proxy<19>, size_t = unsigned int]’ [-fpermissive]
| file70363a0a2d30.cpp:42:43: error: invalid conversion from ‘SEXP’ to ‘size_t {aka unsigned int}’ [-fpermissive]
| /usr/local/lib/R/site-library/Rcpp/include/Rcpp/vector/Vector.h:403:18: error: initializing argument 1 of ‘Rcpp::Vector<RTYPE>::Proxy Rcpp::Vector<RTYPE>::operator()(const size_t&, const size_t&) [with int RTYPE = 19, Rcpp::Vector<RTYPE>::Proxy = Rcpp::internal::generic_proxy<19>, size
| In addition: Warning message:
| running command '/usr/lib/R/bin/R CMD SHLIB file70363a0a2d30.cpp 2> file70363a0a2d30.cpp.err.txt' had status 1
|
| Then I tried to modify my code, which now compiles just fine, but does not give me what I wanted...
|
| > ## try again
| > code_f <- '
| + Rcpp::NumericMatrix cpp_x(x);
| + Rcpp::NumericMatrix cpp_mu(mu);
| + int K = cpp_mu.ncol();
| + int M = cpp_mu.nrow();
| + int N = cpp_x.nrow();
| + Environment glob = Environment::global_env();
| + List cpp_work(glob.get("workspace"));
| +
| + for (int k=0; k < K; k++) {
| + NumericMatrix tmpMatrix(as<SEXP>(cpp_work[k]));
| + tmpMatrix = clone(cpp_x);
| + for (int i=0; i < M; i++)
| + tmpMatrix(_, i) = tmpMatrix(_, i) - cpp_mu(i, k);
| + }
| +
| + return R_NilValue;
| + '
| > ## this time it compiles
| > f_cpp <- cxxfunction(signature(x = "numeric", mu = "numeric"), code_f, plugin = "Rcpp")
| > ## but it does not have the efect I was hoping for, i.e., modifying
| > ## the object 'workspace' in the global environment
| > f_cpp(x, mu)
| NULL
| > all.equal(workspace, f_R())
| [1] "Component 1: Mean absolute difference: 0.72524" "Component 2: Mean absolute difference: 1.7288"
|
| Can anybody help me?
|
| Thank you in advance,
| Giovanni
|
|
|
|
| Giovanni Petris
| Associate Professor
| Department of Mathematical Sciences
| University of Arkansas - Fayetteville, AR 72701
| Ph: (479) 575-6324, 575-8630 (fax)
| http://definetti.uark.edu/~gpetris/
|
| _______________________________________________
| Rcpp-devel mailing list
| Rcpp-devel at lists.r-forge.r-project.org
| https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel
--
Dirk Eddelbuettel | edd at debian.org | http://dirk.eddelbuettel.com
More information about the Rcpp-devel
mailing list