Skip to content

[Rcpp-devel] RInside and multi-threading

6 messages · Darren Cook, Dirk Eddelbuettel

#
I think the correct approach for R is to have a single global instance
(or on the stack in main()) (e.g. [1]).

If your application is multi-threaded, what extra steps do you need to
take? Does every call to the RInside object have to be protected by a
mutex? Or, I wonder if some read-only accesses could be done in
parallel? E.g. a data.frame has been created. Could 2+ threads access
parts of that data.frame in parallel (as long as I'm sure no thread will
update it)?

I found [2], suggesting that this is okay for RServe. Implying it would
be okay for RInside too?

Darren

[1]:
http://stackoverflow.com/questions/5357765/passing-rinsides-r-instance-as-a-parameter-between-classes-methods

[2]: http://www.rosuda.org/Rserve/
"Rserve is thread safe across connections, but eval methods are not
thread safe within one connection. This means that multiple threads
should not use the same connection unless they guarantee that no eval
calls are run in parallel."
#
On 12 February 2012 at 11:47, Darren Cook wrote:
| I think the correct approach for R is to have a single global instance
| (or on the stack in main()) (e.g. [1]).
| 
| If your application is multi-threaded, what extra steps do you need to
| take? Does every call to the RInside object have to be protected by a
| mutex? Or, I wonder if some read-only accesses could be done in
| parallel? E.g. a data.frame has been created. Could 2+ threads access
| parts of that data.frame in parallel (as long as I'm sure no thread will
| update it)?
| 
| I found [2], suggesting that this is okay for RServe. Implying it would
| be okay for RInside too?

"In theory, theory and practice are the same. In practice, they are not."

At present, Rserve is set up to fork (on OS X and Linux). Whereas RInside is
not (yet). Patches are always welcome.

Dirk
 
| Darren
| 
| [1]:
| http://stackoverflow.com/questions/5357765/passing-rinsides-r-instance-as-a-parameter-between-classes-methods
| 
| [2]: http://www.rosuda.org/Rserve/
| "Rserve is thread safe across connections, but eval methods are not
| thread safe within one connection. This means that multiple threads
| should not use the same connection unless they guarantee that no eval
| calls are run in parallel."
| 
| -- 
| Darren Cook, Software Researcher/Developer
| 
| http://dcook.org/work/ (About me and my work)
| http://dcook.org/blogs.html (My blogs and articles)
| _______________________________________________
| 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
#
I took it to mean it forks per connection. The quote below is talking
about threads in a client application sharing a connection to an Rserve
server. Assuming I didn't misunderstood that much, it implies R can
handle non-eval commands in parallel, (which in turn would imply that
RInside would also be okay).
(That may not be the case if Rserve is serializing the incoming requests
on each connection... but in that case there would be no need for them
to have written the "don't eval in parallel" warning.)

A chain of assumptions... it be nice if someone had actually tried it.
(If no one else has, then I will get to it; eventually.)

Darren

  
    
#
Hi Darren,
On 12 February 2012 at 18:13, Darren Cook wrote:
| > | I found [2], suggesting that this is okay for RServe. Implying it would
| > | be okay for RInside too?
| > 
| > At present, Rserve is set up to fork (on OS X and Linux)...
| 
| I took it to mean it forks per connection. The quote below is talking
| about threads in a client application sharing a connection to an Rserve
| server. Assuming I didn't misunderstood that much, it implies R can
| handle non-eval commands in parallel, (which in turn would imply that

Yes, but only via fork() which creates separate R instances.  R itself is
single-threaded (and will mopst likely remain that way).  So in multi-
threaded apps using RInside you have to be careful---with a mutex lock before
and after a single-threaded R segment, things can work fine.

| RInside would also be okay).

As I was trying to say: RInside does not do any forking (yet).

It could conceivably fork each time an app instantiates an RInside object,
but then at the end that does not buy you much as you still need to
coordinate the results from the main program.  Rserve, running similar to a
webserver, has many distinct and unrelated clients---whereas RInside would
presumably be called from one larger program.  It's just different.

| (That may not be the case if Rserve is serializing the incoming requests
| on each connection... but in that case there would be no need for them
| to have written the "don't eval in parallel" warning.)
| 
| A chain of assumptions... it be nice if someone had actually tried it.
| (If no one else has, then I will get to it; eventually.)

Rserve has been out for many years and has been well documented. You can read
up on it over at the rosuda.org site.

Hope this helps.  We're getting a little off-topic here.

Dirk

 
| Darren
| 
| > | [2]: http://www.rosuda.org/Rserve/
| > | "Rserve is thread safe across connections, but eval methods are not
| > | thread safe within one connection. This means that multiple threads
| > | should not use the same connection unless they guarantee that no eval
| > | calls are run in parallel."
| 
| 
| 
| -- 
| Darren Cook, Software Researcher/Developer
| 
| http://dcook.org/work/ (About me and my work)
| http://dcook.org/blogs.html (My blogs and articles)
| _______________________________________________
| 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
#
Ah, I see my misunderstanding: eval() also covers simple read-only
commands. I.e. there is no such thing as a non-eval command :-).

Darren
#
On 13 February 2012 at 11:09, Darren Cook wrote:
| > I took it to mean it forks per connection. The quote below is talking
| > about threads in a client application sharing a connection to an Rserve
| > server. Assuming I didn't misunderstood that much, it implies R can
| > handle non-eval commands in parallel, ...
| 
| Ah, I see my misunderstanding: eval() also covers simple read-only
| commands. I.e. there is no such thing as a non-eval command :-).

Indeed, there is no REPL without the E :-)

Dirk