50% off: Unlimited data and AI learning.
State of Data and AI Literacy Report 2025

Rdsm (version 1.0.0)

Rdsm: Distributed Threads Programming in R

Description

Rdsm provides a threads-like programming environment for R, usable both on a multicore machine and across a network of multiple machines. The package gives the illusion of the shared memory world view that threads systems provide, again even across multiple machines on a network.

The ``dsm'' in ``Rdsm'' stands for distributed shared memory, a term from the parallel processing community in which nodes in a cluster share (real or conceptual) memory. It is based on a similar package I wrote for Perl some years ago (Matloff (2002)).

Arguments

Quick Introduction to <pkg>Rdsm</pkg>

The Rdsm code in MatMul.r in the examples included in this package serves as as a quick introduction, using a matrix-multiply example common in parallel processing packages. There are especially detailed comments in this example.

Advantages of the Shared-Memory Paradigm

Whether or not the platform is a multicore machine or a set of networked computers, a major advantage of Rdsm is that it gives the programmer a shared-memory world view, considered by many in the parallel processing community to be one of the clearest forms of parallel programming (Chandra (2001), Hess et al (2003) etc.).

Suppose for instance we wish to copy x to y. In a message-passing setting such as Rmpi, x and y may reside in processes 2 and 5, say. The programmer would write code (described here in pseudocode)

send x to process 5 to run on process 2, and write code receive data item from process 2

set y to received item to run on process 5. By contrast, in a shared-memory environment, the programmer would merely write y <- x which is vastly simpler. This also means that it is easy to convert sequential Rcode to parallel Rdsm code.

Packages such as snow, arguably in the message-passing realm, do feature more convenient messaging operations, but still shared memory tends to have the simplest code. (It should be noted, though, that in some applications message-passing can yield somewhat better performance.)

Types of Applications

Rdsm should have a wide variety of applications, such as
  • Performance programming, in ``embarrassingly parallel'' settings (such asDisc.Rin the examples included with this package).
  • Parallel I/O applications, e.g. parallel Web data collection (such asWebProbe.Rin the examples included with this package).
  • Collaborative tools (such asAuction.Rin the examples included with this package).

Most of these applications can also be done via non-shared memory paradigms, but the shared-memory paradigm makes the applications easier to develop, maintain and extend.

Communication

Rdsm runs via network sockets.

Data communication is binary in the case of vectors and matrices for speed, but serialize and unserialize are used for lists.

Launching <pkg>Rdsm</pkg>

To run Rdsm manually, run Rin n+1 different terminal (shell) windows, where n is the desired number of clients, i.e. degree of parallelism. One of those windows will be used for the server.

Then:

  • Runsrvr()in your server window. (Or runsrvrinit()and thensrvrloop();srvr()is merely a convenience that calls both.)
  • In each client window, runinit().
  • In each client window, run yourRdsmapplication function.
You may have several application functions to run, or may want to run the same one multiple times. This is fine as long as you don't rerun srvrinit(). You must still rerun srvrloop, but you do not need to rerun init on the client side. Application-program Rdsm variables etc. will be retained from one run to the next.

The script AutoLaunch.R automates the above process. One opens just one window, and the script automatically creates windows for the server and clients. Then each time the user wishes to issue a command to all the clients, he/she merely types the command in the original window, and it will be sent to the client windows, thus saving a lot of typing.

The main functions available in AutoLaunch.R are:

  • alint(nclnt=NULL,nds=NULL)Call this to create the client windows, and start anRprocess in each one. Ifndsis NULL, then this sets upnclntwindows/Rprocesses onlocalhost, i.e. the machine on which the script is run.
  • setldir(libdir)This addslibdirto theRlibrary search path at the server and clients.
  • setdir(cdir=NULL)This changes the working directory tocdirat each client. Ifcdiris NULL, then the client directories are changed to the current working directory of theRprocess runing this script.
  • alinits(nclnt=NULL,nds=NULL)This combinesalinitandsetdir(withcdirNULL), as a convenience.
  • cmdtoclnts(cmd)This sends the commandcmd, single-quoted, to all the clients.
  • loadrdsm()This loadsRdsmat the server and the clients.
  • cmdtosrvr(cmd)This sends the commandcmd, single-quoted, to the server.
  • cmdtoall(cmd)This sends the commandcmd, single-quoted, to the server and all the clients.
  • alquit()This call causes theRprocesses at the server and all the clients to exit, and the corresponding windows to close.

Accessing <pkg>Rdsm</pkg> Variables

The variables in a typical Rdsm application program consist of a few Rdsm variables and many ``ordinary'' variables. Ordinary Rsyntax is used to access the former, just as the latter.

For example, suppose your Rdsm program includes m, a 4x5 matrix variable of class dsmm. If you wished to fill the second column with 1, 2, 3 and 4, you would write m[,2] <- 1:4 just as you would in ordinary R.

Note carefully that you must always use brackets with Rdsm variables. For instance, to copy the Rdsm vector x to an ordinary Rvariable y, write y <- x[]

not y <- x

Built-in Variables

Rdsm's built-in variables are stored in a single global variable myinfo, a list consisting of these components:
  • myid: the ID number of this client, starting with 1
  • nclnt: the total number of clients

Built-in Synchronization Functions

Rdsm includes some built-in synchronization functions similar to those of threaded or other shared-memory programming systems:
  • barr(): barrier operation
  • lock(): lock operation
  • unlock(): unlock operation
  • wait(): wait operation
  • signal(): signal operation
  • fa(): fetch-and-add operation
  • rpc(): remote procedure call operation

Built-in Initialization/Shutdown Functions

  • init(): initializes a client's connection to the server
  • srvrinit(): initializes the server
  • srvrloop(): runs the server
  • srvr(): calls bothsrvrinit()andsrvrloop()
  • dsmexit(): called when a client has finished its work

Internal Structure

Though transparent to the Rdsm programmer, internally Rdsm has the following architecture.

The Rdsm application variables reside on the server. Each read from or write to an Rdsm variable involves a transaction with the server.

Rdsm variables reference vectors, matrices and lists, but have the special Rdsm classes dsmv, dsmm and dsml, respectively. Indexing operations for these classes communicate with the server to read or write the desired objects. Again, all this is transparent to the Rdsm programmer. However, as with any system, a good understanding of the internals can result in your writing much better code.

High-Performance Computing

Rdsm can do quite well in embarrassingly parallel applications, meaning those in which the task at hand can easily be broken in smaller independent tasks to be done by the processes. An additional requirement is that the ``output,'' i.e. Rdsm variables used to contain results of the large task, not be voluminous or frequently written.

It should be noted that this is not just an issue with Rdsm. Indeed, the functional programming nature of R, in which writing to just one element of a vector or array means rewriting the entire data object, essentially rules out good performance in non-embarrassingly parallel problems. On multicore/multiprocessor systems, I recommend interfacing Rwith C/C++ in OpenMP, with OpenMP doing the parallel portion of your work.

Relation to <pkg>bigmemory</pkg>

The other Rpackage providing a shared-memory paradigm (read/write) is bigmemory. That package is restricted to multicore platforms, while Rdsm is much more general, usable on sets of separate but networked machines. Rdsm also offers vector and list types in addition to matrices, while bigmemory has only matrices. On the other hand, on multicore platforms, bigmemory may be faster for some applications.

References

Chandra, Rohit (2001), Parallel Programming in OpenMP, Kaufmann, pp.10ff (especially Table 1.1).

Hess, Matthias et al (2003), Experiences Using OpenMP Based on Compiler Directive Software DSM on a PC Cluster, in OpenMP Shared Memory Parallel Programming: International Workshop on OpenMP Applications and Tools, Michael Voss (ed.), Springer, p.216.

Matloff, Norman (2002), PerlDSM: A Distributed Shared Memory System for Perl. Proceedings of PDPTA 2002, 2002, 63-68.