[Rd] How to safely using OpenMP pragma inside a .C() function?

Simon Urbanek simon.urbanek at r-project.org
Wed Aug 31 14:37:45 CEST 2011


On Aug 30, 2011, at 12:57 PM, pawelm wrote:

> Simon,
> 
> I found that files R-2.13.1/src/library/stats/src/distance.c and
> R-2.13.1/src/main/array.c have openmp code (example below). I have couple
> questions regarding best practices when using R internals and openmp. 
> 
> Can we use R-2.13.1/src/library/stats/src/distance.c and
> R-2.13.1/src/main/array.c as an example how to interact with R code and R
> internals?
> What are my other options if I want to work with SEXP structures in my
> parallel code?
> 

I forgot to answer this one in my previous response, sorry.

The short answer is none. If you can't access what you need before the omp loop you may be in trouble. For example you can't allocate anything in the parallel code, so you can't create character elements or assign objects. There are some things (very few) you can do like using ISNA() or ISNAN() but the trouble is that without looking at the sources you don't know what you can do (note that the pragma below declares R_NaReal although it actually uses NA_REAL -- in theory that is only possible in internal R code because it knows that NA_REAL is defined as R_NaReal variable and not a fixed constant - which is entirely a matter of implementation and thus not under your control).

Cheers,
Simon


> Thank you
> Regards
> 
> =============
> 
> #ifdef HAVE_OPENMP
>        /* This gives a spurious -Wunused-but-set-variable error */
>        if (R_num_math_threads > 0) 
>            nthreads = R_num_math_threads;
>        else 
>            nthreads = 1; /* for now */
> #pragma omp parallel for num_threads(nthreads) default(none) \
>    private(j, i, ix, rx) \
>    firstprivate(x, ans, n, p, type, cnt, sum, \
>                 NaRm, keepNA, R_NaReal, R_NaInt, OP)
> #endif
>        for (j = 0; j < p; j++) {
>            switch (type) {
>            case REALSXP:
>                rx = REAL(x) + n*j; 
>                if (keepNA)
>                    for (sum = 0., i = 0; i < n; i++) sum += *rx++;
>                else {
>                    for (cnt = 0, sum = 0., i = 0; i < n; i++, rx++)
>                        if (!ISNAN(*rx)) {cnt++; sum += *rx;}
>                        else if (keepNA) {sum = NA_REAL; break;}
>                }    
>                break;
>            case INTSXP:
>                ix = INTEGER(x) + n*j; 
>                for (cnt = 0, sum = 0., i = 0; i < n; i++, ix++)
>                    if (*ix != NA_INTEGER) {cnt++; sum += *ix;}
>                    else if (keepNA) {sum = NA_REAL; break;}
>                break;
>            case LGLSXP:
>                ix = LOGICAL(x) + n*j; 
>                for (cnt = 0, sum = 0., i = 0; i < n; i++, ix++)
>                    if (*ix != NA_LOGICAL) {cnt++; sum += *ix;}
>                    else if (keepNA) {sum = NA_REAL; break;}
>                break;
>            default:
>                /* we checked the type above, but be sure */
>                UNIMPLEMENTED_TYPEt("do_colsum", type);
>            }
>            if (OP == 1) {
>                if (cnt > 0) sum /= cnt; else sum = NA_REAL;
>            }
>            REAL(ans)[j] = sum;
>        }
> 
> 
> --
> View this message in context: http://r.789695.n4.nabble.com/How-to-safely-use-OpenMP-pragma-inside-a-C-function-tp3777036p3779214.html
> Sent from the R devel mailing list archive at Nabble.com.
> 
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
> 
> 



More information about the R-devel mailing list