[Rcpp-devel] Delayed usage of auxiliary memory in RcppArmadillo

Simon Zehnder szehnder at uni-bonn.de
Fri Jun 14 11:17:17 CEST 2013


Hi Rcpp::Devels and Rcpp::Users,

I would like to close my post with a solution I found after some days of experiencing:

If you want to create an Armadillo matrix conditional on a statement and that matrix should reuse R storage you can work with a pointer,

1. Create an R list object:
	rlist <- list(par = array(1, dim = c(2,1)), cond = TRUE, par2 = array(1, dim = c(2,1)))

2. Define the function in C++ using RcppArmadillo plugin:
	cfunction <- cxxfunction(signature(List_R = "list"), body='
		Rcpp::List rList(List_R); 
		Rcpp::NumericMatrix parM((SEXP) rList["par"]); 
		bool cond = Rcpp::as<bool>(rList["cond"]); 
		arma::mat parAM(parM.begin(), 2, 1, false, true); 
		Rcpp::NumericMatrix par2M((SEXP) rList["par2"]); 
		arma::mat *par2Ptr; 
		if(cond) {
			par2Ptr = new arma::mat(par2M.begin(), 2, 1, false, true);
		} else {
			par2Ptr = NULL;
		} 
		parAM.fill(2); 
		if(cond) {
			par2Ptr->fill(2);
		} 
		delete par2Ptr; 
		return Rcpp::wrap(rList);', 
		plugin = "RcppArmadillo")

3. Run the function with the R list object:
	cfunction(rlist)
	$par 
		[,1] 
	[1,] 	2 
	[2,] 	2 

	 $cond 
	[1] TRUE 
	 
	$par2 
		[,1] 
	[1,] 	2 
	[2,] 	2

4. Create a new R list object and set the condition to FALSE, then run again the C++ function:
	rlist <- list(par = array(1, dim = c(2,1)), cond = FALSE, par2 = array(1, dim = c(2,1)))
	cfunction(rlist)
	$par 
		[,1] 
	[1,] 	2 
	[2,] 	2 

	 $cond 
	[1] FALSE 
	 
	$par2 
		[,1] 
	[1,] 	1 
	[2,] 	1

We see, that working with an arma::mat pointer makes the conditional creation of the Armadillo matrix working. Even if it usually gives only a warning if you don't, set the pointer
always to NULL if it is not used. Also do not forget to delete the pointer at the end of the program. I do not know yet, how the deletion of arma::mat objects works, when
auxiliary memory is used (so maybe it does not matter if we delete the pointer or not), but it is always a good idea to delete a pointer, when it is not used anymore. There are 
of course also safer pointers in C++, e.g. unique_ptr, but the main pattern to use a pointer is shown above. 

Enjoy Rcpp/RcppArmadillo, possibilities are great! 

Thanks to everyone for his comments. 

Simon

On Jun 11, 2013, at 12:56 PM, Simon Zehnder <szehnder at uni-bonn.de> wrote:

> 
> Hi Romain,
> 
> thanks for refreshing my C++ basics
> 
> As I am regrettably not privileged to spare the amount of time on C++
> skill improvement I would like to, but have the assignment to
> construct stochastic models and implement them, I focus here on a
> solution and maybe someone can help me, with his experience in C++
> (at this point I'd like to apologize for maybe confusing list members with my wrong statements below).
> 
> Back to the origin of my problem I intend to solve:
> 
> I have a variable STOREPOST, that indicates, if additional
> information should be stored during the processing of my algorithm. In
> the case
> STOREPOST is not true I would like to avoid the construction of an
> arma::mat object and in the case that STOREPOST is true an arma::mat
> object should be constructed with auxiliary memory from R.
> 
> From your corrections below I understand, that the way I showed is
> not appropriate to solve my problem, as the temporary object in the
> if-clause is not known anymore to the compiler
> from the line on I close the bracket ('}') of the if-condition. I
> also assume, that using a pointer '*arma::mat maybeM' does not change
> this,
> as the object inside the if-clause is still a temporary rvalue
> (please correct me here if I am wrong).
> 
> I would like to ask, if a list member has maybe an advice for me? Should I construct two
> different algorithms (that would be a very easy solution - maybe not
> the
> way a C++ programmer would use). Or would you construct a base class
> and one that inherits from the base class containing additional
> members? I think there are a lot
> of pitfalls I do not see yet.
> 
> 
> Best
> 
> Simon
> 
> On 06/11/2013 12:02 AM, romain at r-enthusiasts.com wrote:
>> Some C++ 101 insights below.
>> 
>> Le 2013-06-10 23:07, Simon Zehnder a écrit :
>>> Dear Rcpp::Devels and Rcpp::Users,
>>> 
>>> I am temporarily experiencing with a delayed assignment of auxiliary
>>> memory in RcppArmadillo:
>>> 
>>> Declare a matrix from which you know you may need it
>>> 
>>> arma::mat maybeM;
>>> 
>>> (In C++ a declaration makes only known the type and name but allocates
>>> no storage yet).
>> 
>> SO WRONG.
>> here the default constructor or arma::mat is called. What it does is entirely up to the implementation of the class.
>> 
>>> Now you check a condition and if it is true, you will need the matrix,
>>> so you initialize it
>>> 
>>> if(mycondition) {
>>> maybeM = arma::mat(aux_mem*, n_rows, n_cols, copy_aux_mem = false,
>>> strict = true)
>>> }
>>> 
>>> (for simplicity I only printed here the default constructor for using
>>> auxiliary memory; please assume that all values are presented)
>> 
>> wrong again.
>> 
>> what happens here is in two steps.
>> 
>> - first, an arma::mat is constructed, using the so called advanced constructor. this does use the auxiliary memory to create a temporary.
>> - second, the assignment operator is used to copy the temporary into "maybeM"
>> 
>> So indeed maybeM does not use the auxiliary memory, I hope now you understand why.
>> 
>>> The resulting matrix maybeM does not use the auxiliary memory. I tried
>>> to access in some way the 'mem' member in the Armadillo class, but
>>> this member is constant and can not be
>>> manipulated after first construction. A primer declaration and later
>>> initialization is a very common pattern in C++, but it seems not be
>>> possible in case of reusing memory.
>> 
>> Everything is possible, it is a decision made by the implementation. e.g. for Rcpp classes copy construction means just cheap pointer copies, not data copies.
>> armadillo is implemented with more traditional copy semantics.
>> 
>>> I conclude, that a delayed assignment of auxiliary memory is not
>>> possible.
>> 
>> wrong conclusion. what you demonstrated here is that you need to study basic c++ (assignment operators, copy construction, ...) :)
>> 
>> now, things would be different with move semantics in c++11. Not sure armadillo has implemented them already, but I'm pretty sure that is not what you were talking about.
>> 
>> Romain
>> 
>>> Best
>>> 
>>> Simon
>> _______________________________________________
>> 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
> 
> _______________________________________________
> 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



More information about the Rcpp-devel mailing list