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?
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.
#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()
*/
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
>