[Rcpp-devel] mpi and RInside

Jianping Hua talich at gmail.com
Tue Feb 9 01:13:28 CET 2010


Hello:

I'm quite new to R and I'd like to run some R program inside my C++
code. So I installed Rcpp and RInside recently. Since many of my work
involves mpi, so I'm wondering if RInside works with mpi. It looks mpi
works, although with some glitch. So I think I might post my
experiences here, for anyone who is interested, and possibly, further
discussions and suggestions.

First, some background. I have a MacbookPro running Leopard. To make
Rcpp and RInside work, I have installed it from source (Thanks Dirk
for tipping me out!!!) The mpic++ is Mac's own g++-4.0.1. Here is an
very simple example code which I modified from the example code 0 of
RInside package:

////////////Start of Example///////////////
// Simple example showing in R console information about current node

#include "mpi.h"     // mpi header
#include "RInside.h" // for the embedded R via RInside
#include "Rcpp.h"    // for the R / Cpp interface used for transfer

int main(int argc, char *argv[]) {

    // mpi related
    int myrank, nodesize;                       // node information
    MPI_Init(&argc,&argv);                      // mpi initialization
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);     // obtain current node rank
    MPI_Comm_size(MPI_COMM_WORLD, &nodesize);   // obtain total nodes running.

    RInside R(argc, argv);              // create an embedded R instance

    std::stringstream txt;
    txt << "Hello from node " << myrank       // node information
        << " of " << nodesize << " nodes!" << std::endl;
    R.assign( txt.str(), "txt");              // assign string var to
R variable 'txt'

    std::string evalstr = "cat(txt)"; // show node information
    R.parseEvalQ(evalstr);            // eval the init string,
ignoring any returns


    MPI_Finalize();                   // mpi finalization

    exit(0);
}

/////////////End of Example///////////////

The tricky part is I found I have to put mpi.h before Rinside.h and
Rcpp.h, otherwise the compiler will report syntax error in mpi.h.

For the makefile, I just changed two lines related to CXX in the
example makefile
CXX      := mpic++
CXXFLAGS := $(RCPPFLAGS) $(RCPPINCL) $(RINSIDEINCL) -g -O2

In the first line, I switch compiler from gcc-4.2 to mpic++. In the
second line, I removed mtune=core2 parameter.

I submitted it to 6 slots through mpirun:
mpirun -np 6 rinside_sample0

And the outcome should be something like:
Hello from node 4 of 6 nodes!
Hello from node 3 of 6 nodes!
Hello from node 1 of 6 nodes!
Hello from node 0 of 6 nodes!
Hello from node 2 of 6 nodes!
Hello from node 5 of 6 nodes!

Note that in the above example there is no data passing at all. In the
following example I add data gathering and it also works:

///////Start of example/////////////////
// Simple mpi example: simulate sampling/averaging on multiple nodes
and gathering the results.

#include "mpi.h"     // mpi header file
#include "RInside.h" // for the embedded R via RInside
#include "Rcpp.h"    // for the R / Cpp interface used for transfer

int main(int argc, char *argv[]) {

    // mpi related
    int myrank, nodesize;                       // node information
    int sndcnt = 1, rcvcnt = 1;                 // # of elements in
send/recv buffer
    MPI_Init(&argc,&argv);                      // mpi initialization
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);     // obtain current node rank
    MPI_Comm_size(MPI_COMM_WORLD, &nodesize);   // obtain total nodes running.
    double sendValue;                           // value to be
collected in current node
    double *allvalues = new double( nodesize ); // to save all results

    //simulation info
    // to sample from a uniform distribution
    int rangeMin = 0, rangeMax = 10; // range of uniform distribution
    int sampleSize = 2;              // points in each sample

    try
    {
        RInside R(argc, argv);              // create an embedded R instance
        SEXP ans;                           // return value

        std::stringstream txt;
        txt << "x <- " << rangeMin << std::endl;
        R.parseEvalQ( txt.str() );      // assign x with lower range
of uniform distribution

        txt << "y <- " << rangeMax << std::endl;
        R.parseEvalQ( txt.str() );      // assign y with upper range
of uniform distribution

        txt << "n <- " << sampleSize << std::endl;
        R.parseEvalQ( txt.str() );      // assign n with the size of sample

        std::string evalstr = " mean(runif(n,x,y))";  // sampling,
compute the mean
        if ( R.parseEval(evalstr, ans) )              // eval the
evalstr string, return results
            throw std::runtime_error( "R cannot evalueate '" + evalstr + "'" );

        RcppVector<double> m(ans);      // convert SEXP variable to an
RcppVector

        sendValue = m( 0 );             // assign the return value to
the variable to be gathered

        //gather together values from all processes to allvalues
        MPI_Gather(&sendValue,sndcnt,MPI_DOUBLE,&allvalues[0],rcvcnt,MPI_DOUBLE,0,MPI_COMM_WORLD);

        // show what inidividual node's contribution
        std::cout << "node " << myrank << " has mean " << m(0) << std::endl;

        // show gathered results in node 0
        if ( myrank == 0 )
        {
            std::cout << "values of all " << nodesize << " trials: "
<< std::endl;
            for ( int i = 0; i < nodesize; i++ )
                std::cout << allvalues[ i ] << ", ";
            std::cout << std::endl;
        }

    } catch(std::exception& ex) {
        std::cerr << "Exception caught: " << ex.what() << std::endl;
    } catch(...) {
        std::cerr << "Unknown exception caught" << std::endl;
    }

    // clean up
    delete[] allvalues;

    MPI_Finalize();             // mpi finalization

    exit(0);
}

//////////End of Example////////////////

The running results, again if running on 6 slots, should be something like this:
node 5 has mean 6.13918
node 2 has mean 5.21227
node 1 has mean 0.563234
node 4 has mean 5.41173
node 3 has mean 2.41499
node 0 has mean 0.515025
values of all 6 trials:
0.515025, 0.563234, 5.21227, 2.41499, 5.41173, 6.13918,

I hope this information is useful.

Best wishes,
Jianping


More information about the Rcpp-devel mailing list