Skip to content

[Rcpp-devel] RInside constructor calls srand

6 messages · Joseph Xu, Dirk Eddelbuettel

#
Hi:

I'm working on a program that uses RInside and also calls the rand()
function. For the longest time I was trying to figure out why my
program was behaving differently with every run even though I
initialized the random seed to 1. Finally I found the problem was that
the RInside constructor secretly calls srand with the current time.

I noticed a comment explaining that the srand call was needed by
tempfile(), but is this absolutely necessary? How will tempfile()
break if srand was static? It seems like a huge disadvantage to not be
able to deterministically debug a program. At the very least, the call
to srand should be made very obvious to the user.


Thanks for your time.

Joseph
#
On 5 November 2011 at 22:26, Joseph Xu wrote:
Hi Joseph,

Thanks for posting here with questions about Rcpp and RInside.

| Hi:
| 
| I'm working on a program that uses RInside and also calls the rand()
| function. For the longest time I was trying to figure out why my
| program was behaving differently with every run even though I
| initialized the random seed to 1. Finally I found the problem was that
| the RInside constructor secretly calls srand with the current time.
| 
| I noticed a comment explaining that the srand call was needed by
| tempfile(), but is this absolutely necessary? How will tempfile()
| break if srand was static? It seems like a huge disadvantage to not be
| able to deterministically debug a program. At the very least, the call
| to srand should be made very obvious to the user.

Maybe you are missing the discussion about using R's RNG functions from the
'Writing R Extensions' manual, and how to init the state of the RNG?

Also, RInside embeds R. And just as in normal R, if you want reproducibility
from the embedded R provided by RInside, you need set.seed(). Just use it.

| Thanks for your time.

Pleasure. Hope this answers your question.

Dirk
#
Hi Dirk:

Thanks for the quick reply.
On Sat, Nov 5, 2011 at 11:06 PM, Dirk Eddelbuettel <edd at debian.org> wrote:

            
I tried something like this:

#include <stdlib.h>
#include <iostream>
#include <Rcpp.h>
#include <RInside.h>

using namespace std;

int main() {
	srand(1);
	RInside r(0, NULL);
	r.parseEvalQ("set.seed(0)");
	cout << rand() << endl;
	return 0;
}

But every time I run the program, I get a different random number. Am
I missing something?
Love the signature.


Joseph
#
On 6 November 2011 at 01:18, Joseph Xu wrote:
| Hi Dirk:
| 
| Thanks for the quick reply.
|
| On Sat, Nov 5, 2011 at 11:06 PM, Dirk Eddelbuettel <edd at debian.org> wrote:
| 
| > Also, RInside embeds R. And just as in normal R, if you want reproducibility
| > from the embedded R provided by RInside, you need set.seed(). Just use it.
| 
| I tried something like this:
| 
| #include <stdlib.h>
| #include <iostream>
| #include <Rcpp.h>
| #include <RInside.h>
| 
| using namespace std;
| 
| int main() {
| 	srand(1);

That random number generator comes from the OS and has nothing to do with R !

| 	RInside r(0, NULL);
| 	r.parseEvalQ("set.seed(0)");

That sets R's seed.

| 	cout << rand() << endl;

That calls a different RNG.

| 	return 0;
| }
| 
| But every time I run the program, I get a different random number. Am
| I missing something?

I now see where you are coming from. Adding 'RInside' to an existing program
alters the (non-R-generated) random number stream of that program.  Is that
correct?

In that case the sequence 

	RInside r(0, NULL);
	srand(1);
	r.parseEvalQ("set.seed(0)");
	cout << rand() << endl;
	return 0;

may work as you now fix the RNG you care about (from the C library) after
setting up RInside.

In any event, most of us here are concerned about using _R's RNG_ and what we
do with Rcpp and RInside ensures that "yes you can" use those without side
effect.  See the discussesion about RNGScope in the docs and the mailing list
archives. 
 
| > "Outside of a dog, a book is a man's best friend. Inside of a dog, it is too
| > dark to read." -- Groucho Marx
| >
| Love the signature.

:)

Dirk 
 
| Joseph
1 day later
#
Hi Dirk:
On Sun, Nov 6, 2011 at 10:22 AM, Dirk Eddelbuettel <edd at debian.org> wrote:
Yes, this makes my program behave as I want. My main point is that the
srand call in the RInside constructor is sneaky and users like me
won't be aware of it. Maybe it would be better to force the user to
initialize the random seed manually?

Joseph
#
On 7 November 2011 at 13:48, Joseph Xu wrote:
| Hi Dirk:
|
| On Sun, Nov 6, 2011 at 10:22 AM, Dirk Eddelbuettel <edd at debian.org> wrote:
| > I now see where you are coming from. Adding 'RInside' to an existing program
| > alters the (non-R-generated) random number stream of that program. ?Is that
| > correct?
| >
| > In that case the sequence
| >
| > ? ? ? ?RInside r(0, NULL);
| > ? ? ? ?srand(1);
| > ? ? ? ?r.parseEvalQ("set.seed(0)");
| > ? ? ? ?cout << rand() << endl;
| > ? ? ? ?return 0;
| >
| > may work as you now fix the RNG you care about (from the C library) after
| > setting up RInside.
| 
| Yes, this makes my program behave as I want. My main point is that the
| srand call in the RInside constructor is sneaky and users like me
| won't be aware of it. Maybe it would be better to force the user to
| initialize the random seed manually?

No --- RInside behaves just like R, including setting up its own randomized
temporary directory just like R does.

That is a feature, not a bug.

You probably shouldn't use rand() and srand() anyway.  Libc upgraded to
decent RNGs but the ones in R are likely to be of higher quality.

Dirk