From edd at debian.org  Sat Jul 10 20:01:39 2010
From: edd at debian.org (Dirk Eddelbuettel)
Date: Sat, 10 Jul 2010 13:01:39 -0500
Subject: [Rd] Set the number of threads using openmp with .C
In-Reply-To: <AANLkTikbNGO9fDEArAl-QgMvYkIwRqNqe7eox0WVsIKN@mail.gmail.com>
References: <AANLkTikbNGO9fDEArAl-QgMvYkIwRqNqe7eox0WVsIKN@mail.gmail.com>
Message-ID: <19512.46467.80330.279994@ron.nulle.part>


Eduardo,

On 10 July 2010 at 19:31, Eduardo Garc?a wrote:
| Hi everybody! Could somebody help me with the following?
| 
| I'm trying to run a simple Hello World code in openmp using .C function. The
| C code i have is:
| 
|  #include <omp.h>
|  #include <stdio.h>
|  #include <R.h>
| 
|  void hello_omp(int *n) {
|    int th_id, nthreads;
|    omp_set_num_threads(*n);
|    #pragma omp parallel private(th_id)
|    {
|      th_id = omp_get_thread_num();
|      Rprintf("Hello World from thread %d\n", th_id);
|      #pragma omp barrier
|      if ( th_id == 0 ) {
|        nthreads = omp_get_num_threads();
|        Rprintf("There are %d threads\n",nthreads);
|      }
|    }
| }
| 
| Where n is the number of threads that i want.
| 
| I compite it with "R CMD SHLIB hello_openmp_R.c -fopenmp" and when I try to
| run it in R using:
| 
| dyn.load("hello_openmp_R.so")
| hello_omp=function(n){.C("hello_omp",as.integer(n))}
| hello_omp(3)
| hello_omp(2)
| 
| Only 1 thread is been used, instead of 3 and 2:
| 
| > hello_omp(3)
| Hello World from thread 0
| There are 1 threads
| [[1]]
| [1] 3
| 
| 
| > hello_omp(2)
| Hello World from thread 0
| There are 1 threads
| [[1]]
| [1] 2
| 
| I also tried to set OMP_NUM_THREADS=3 in the Konsole with "export
| OMP_NUM_THREADS=3", in the .c file directory, but it seems that R don't
| recognize it when calls .C
| 
| I am using R version 2.10.1 in Ubuntu 9.10 - Karmic Koala, but i'm newbie in
| Linux.
| 
| Thanks a lot in advance for your help !*

You were almost there, but your compile instructions were wrong.  You must
pass -fopenmp to gcc. Which you tried, alas wrongly, and then overlooked the
warnings (and I called your file eduardo.c here) :

   gcc -std=gnu99 -I/usr/share/R/include      -fpic  -O3 -Wall -pipe  -c eduardo.c -o eduardo.o
   eduardo.c: In function ?hello_omp?:
   eduardo.c:7: warning: ignoring #pragma omp parallel
   eduardo.c:11: warning: ignoring #pragma omp barrier

One way of passing argument to gcc via 'R CMF foo' is to to use the
PKG_CPPFLAGS and PKG_LIBS arguments.  The following shell script builds and
runs the code:

   #!/bin/sh

   PKG_CPPFLAGS="-fopenmp" \
   PKG_LIBS="-lgomp" \
   R CMD SHLIB eduardo.c 

   cat <<EOF | R --silent --no-save
   dyn.load("eduardo.so")
   hello_omp=function(n){.C("hello_omp",as.integer(n))}
   hello_omp(3)
   hello_omp(2)
   EOF

and this generates the following output:

   edd at max:/tmp$ ./eduardo.sh 
   gcc -std=gnu99 -I/usr/share/R/include -fopenmp     -fpic  -O3 -Wall -pipe  -c eduardo.c -o eduardo.o
   gcc -std=gnu99 -shared -o eduardo.so eduardo.o -lgomp -L/usr/lib64/R/lib -lR
   > dyn.load("eduardo.so")
   > hello_omp=function(n){.C("hello_omp",as.integer(n))}
   > hello_omp(3)
   Hello World from thread 0
   Hello World from thread 2
   Hello World from thread 1
   There are 3 threads
   [[1]]
   [1] 3

   > hello_omp(2)
   Hello World from thread 0
   Hello World from thread 1
   There are 2 threads
   [[1]]
   [1] 2

   > 
   edd at max:/tmp$ 

Have a look at the CRAN package 'inline' which allows you to compile, load,
link such short code snippets much more easily.

Lastly, one word of caution. R is famously single-threaded. You may get
yourself into trouble with OpenMP unless you set locks rather carefully.
There is of course the famous example of Luke Tierney's pnmath (at
http://www.stat.uiowa.edu/~luke/R/experimental/) so there is also some scope
for using this.

Hope this helps.

-- 
  Regards, Dirk



[Rd] Set the number of threads using openmp with .C
Dirk Eddelbuettel