Сбросить локальные переменные потока в OpenMP - PullRequest
0 голосов
/ 04 мая 2018

Мне нужен согласованный способ сброса всех локальных переменных потока, создаваемых моей программой. Проблема заключается в том, что локальные данные потока создаются в местах, отличных от того, где они используются.

Моя программа выглядит следующим образом:

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()); 
    }
}

Теперь, моя проблема в том, что мне нужна функция, которая сбрасывает данные, то есть каждый созданный локальный объект потока должен учитываться.

На данный момент мое решение состоит в том, чтобы использовать параллельную область, которая, как мы надеемся, использует равное или большее количество потоков, чем «параллельное для», поэтому каждый объект «повторяется» через:

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

Есть ли более идиоматичный / безопасный способ реализации ClearThreadLocalData()?

1 Ответ

0 голосов
/ 06 мая 2018

Вы можете создать и использовать глобальный номер версии для ваших данных. Увеличивайте его каждый раз, когда вам нужно очистить существующие кэши. Затем измените GetData, чтобы проверить номер версии, если существует существующий объект данных, отбросить существующий и создать новый, если он устарел. (Номер версии для выделенного объекта data_t может быть сохранен в data_t, если вы можете изменить класс, или в локальной переменной второго потока, если нет.) В итоге вы получите что-то вроде

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;
}

Это не зависит от существования метода Clear в data_t, но если он у вас есть, замените delete-and-reset вызовом Clear. Я использую d = nullptr, чтобы избежать дублирования вызова на new data_t().

Глобальный dataVersion может быть статическим членом data_t, если вы хотите избежать глобальной переменной, и он может быть атомарным, если это необходимо, хотя GetData потребуются изменения для его обработки.

Когда придет время для сброса данных, просто измените глобальный номер версии:

++dataVersion;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...