Search code examples
parallel-processingrcpppragma

Pragma directive to get thread number not working Rcpp


I am trying to parallelise a loop using pragma directives in Rcpp. Aside from a warning message during compilation that pragma is not recognised (although this appears to be a non-issue from what I have read), other pragma commands are not working. This is the minimal example I have been using (content of the for-loop is irrelevant):

sourceCpp(code = '
#include <Rcpp.h>
#include <omp.h>
using namespace Rcpp ; 

// [[Rcpp::export]]
int test() {

#pragma omp parallel for
int foo = omp_get_num_threads() ;
for(int i = 0; i < 2; i++) {
  Rcout << i ;
}
return foo ;

}')

Here is my error:

"C:/rtools40/mingw64/bin/"g++ -std=gnu++11  -I"C:/PROGRA~1/R/R-40~1.4/include" -DNDEBUG   -I"C:/Users/User/Documents/R/win-library/4.0/Rcpp/include" -I"C:/Users/User/AppData/Local/Temp/RtmpWW0LXx/sourceCpp-x86_64-w64-mingw32-1.0.4.6"        -O2 -Wall  -mfpmath=sse -msse2 -mstackrealign -c file2fe83fae2189.cpp -o file2fe83fae2189.o
file2fe83fae2189.cpp:9: warning: ignoring #pragma omp parallel [-Wunknown-pragmas]
 #pragma omp parallel for
 
C:/rtools40/mingw64/bin/g++ -std=gnu++11 -shared -s -static-libgcc -o sourceCpp_90.dll tmp.def file2fe83fae2189.o -LC:/PROGRA~1/R/R-40~1.4/bin/x64 -lR
C:/rtools40/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: file2fe83fae2189.o:file2fe83fae2189.cpp:(.text+0x106): undefined reference to `omp_get_num_threads'
collect2.exe: error: ld returned 1 exit status

I am on a Windows machine so the MacOS compiler issue should not apply, and my num_threads call is inside the pragma section. Any ideas on what is going wrong here?


Solution

  • While this stuff can be finicky, you clearly missed the fact that you must inform Rcpp that you want an OpenMP compilation: you do this via the plugin (or in a package, which is what you should probably use anyway, via the src/Makevars or src/Makevars.win variable).

    Anyway, here is a worked example I just derived from an older C++ example I had hanging around.

    Code

    #include <Rcpp.h>
    #include <omp.h>
    
    // [[Rcpp::plugins(openmp)]]
    
    // [[Rcpp::export]]
    int foo() {
        
        int th_id, nthreads;
    
    #pragma omp parallel private(th_id)
        {
            th_id = omp_get_thread_num();
            std::ostringstream ss;  // allow for better synchronization
            ss << "Hello World from thread " << th_id << std::endl;
            Rcpp::Rcout << ss.str();
    #pragma omp barrier
    #pragma omp master
            {
                nthreads = omp_get_num_threads();
                Rcpp::Rcout << "There are " << nthreads << " threads" << std::endl;
            }
        }
        return 0;
    }
    
    /*** R
    foo()
    */
    

    Output

    On my machine with a hyperthreaded six-core cpu:

    > Rcpp::sourceCpp("answer.cpp")
    
    > foo()
    Hello World from thread 0
    Hello World from thread 1
    Hello World from thread 8
    Hello World from thread 10
    Hello World from thread 4
    Hello World from thread 9
    Hello World from thread 11
    Hello World from thread 7
    Hello World from thread 3
    Hello World from thread 5
    Hello World from thread 6
    Hello World from thread 2
    There are 12 threads
    [1] 0
    >