2
votes

This is a simple test code:

#include <stdlib.h>

__thread int a = 0;

int main() {

    #pragma omp parallel default(none)
    {
        a = 1;
    }

    return 0;
}

gcc compiles this without any problems with -fopenmp, but icc (ICC) 12.0.2 20110112 with -openmp complains with

test.c(7): error: "a" must be specified in a variable list at enclosing OpenMP parallel pragma #pragma omp parallel default(none)

I have no clue which paradigm (i.e. shared, private, threadprivate) applies to this type of variables. Which one is the correct one to use?

I get the expected behaviour when calling a function that accesses that thread local variable, but I have trouble accessing it from within an explicit parallel section.

Edit:

My best solution so far is to return a pointer to the variable through a function

static inline int * get_a() { return &a; }
1
Mixing different thread models is probably not such a good idea. Semantically threadprivate is probably the closest. Since __thread is a compiler extension, you will probably not find much of documentation that links this and OpenMP. - Jens Gustedt
Which compiler are you using? GCC should not ask you to give a an explicit data-sharing class, even when default(none) is specified. - Hristo Iliev
@HristoIliev I am using icc 12.0.2. And you are right that this seems to be an issue with icc. gcc accepts this. - Sergey L.
Try adding #pragma omp threadprivate(a) on the next line after the declaration of a. It is a bit of tautology since to a great extent both do the same (with some exceptional cases concerning C++ objects). - Hristo Iliev
@HristoIliev This is the one! Getting rid of the __thread specifier and putting #pragma omp threadprivate instead even makes my code compatible with Mach-O since __thread is unsupported in Mach-O executables. If you post this as an answer then I will happily give you credit. - Sergey L.

1 Answers

3
votes

__thread is roughly analogous to the effect that the threadprivate OpenMP directive has. To a great extent (read as when no C++ objects are involved), both are often implemented using the same underlying compiler mechanism and therefore are compatible but this is not guaranteed to always work. Of course, the real world is far from ideal and we have to sometimes sacrifice portability for just having things working within the given development constraints.

threadprivate is a directive and not a clause, therefore you have to do something like:

#include "header_providing_a.h"

#pragma omp threadprivate(a)

void parallel_using_a()
{
   #pragma omp parallel default(none) ...
     ... use 'a' here
}

GCC (at least version 4.7.1) treats __thread as implicit threadprivate declaration and you don't have to do anything.