简体   繁体   中英

Reset thread-local variables in OpenMP

I need a consistent way of resetting all thread-local variables my program creates. The problem lies in that the thread-local data is created in places different from where they are used.

My program outline is the following:

struct data_t { /* ... */ };

// 1. Function that fetches the "global" thread-local data
data_t& GetData()
{
    static data_t *d = NULL;
    #pragma omp threadprivate(d); // !!!

    if (!d) { d = new data_t(); }

    return *d;
}

// 2 example function that uses the data
void user(int *elements, int num, int *output)
{
    #pragma omp parallel for shared(elements, output) if (num > 1000)
    for (int i = 0; i < num; ++i)
    {
        // computation is a heavy calculation, on memoized data
        computation(GetData()); 
    }
}

Now, my problem is I need a function that resets data, ie every thread-local object created must be accounted for.

For now, my solution, is to use a parallel region, that hopefully uses equal or more threads than the "parallel for" so every object is "iterated" through:

void ClearThreadLocalData()
{
    #pragma omp parallel
    {
        // assuming data_t has a "clear()" method
        GetData().clear();
    }
}

Is there a more idiomatic / safe way to implement ClearThreadLocalData() ?

You can create and use a global version number for your data. Increment it every time you need to clear the existing caches. Then modify GetData to check the version number if there is an existing data object, discarding the existing one and creating a new one if it is out of date. (The version number for the allocated data_t object can be stored within data_t if you can modify the class, or in a second thread local variable if not.) You'd end up with something like

static int dataVersion;

data_t& GetData()
{
    static data_t *d = NULL;
    #pragma omp threadprivate(d); // !!!

    if (d && d->myDataVersion != dataVersion) {
        delete d;
        d = nullptr;
    }
    if (!d) { 
        d = new data_t();
        d->myDataVersion = dataVersion;
    }

    return *d;
}

This doesn't depend on the existence of a Clear method in data_t , but if you have one replace the delete-and-reset with a call to Clear . I'm using d = nullptr to avoid duplicating the call to new data_t() .

The global dataVersion could be a static member of data_t if you want to avoid the global variable, and it can be atomic if necessary although GetData would need changes to handle that.

When it comes time to reset the data, just change the global version number:

++dataVersion;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM