как реализовать потокобезопасный способ однократной записи в процесс глобальных общих переменных в openmp? - PullRequest
1 голос
/ 23 декабря 2011

Я хочу написать функцию, которая

1 является поточно-ориентированной, т. Е. Работает правильно, независимо от того, вызывается она из параллельной области openmp или нет,

2 выполняет один раз для процесса( не : один раз на поток) запись в глобальную общую переменную.

Первоначально я думал использовать директивы master или single, но они не работают во вложенном параллелизме,Есть ли отказоустойчивое решение?

Ответы [ 2 ]

1 голос
/ 24 декабря 2011

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

Более тонкий подход заключается в использовании блокировок OpenMP; вы можете просто установить первый поток, установив блокировку, после чего другие потоки не смогут, и использовать это как свой флаг:

#include <stdio.h>
#include <omp.h>

void setonce_thread(omp_lock_t *l, int input, int *sharedvar) {
    if (omp_test_lock(l)) {
        printf("Set lock with %d\n", input);
        *sharedvar = input;
    } else {
        printf("Could not set lock with %d\n", input);
    }
}

void setonce_crit(int input, int *setflag, int *sharedvar) {
#pragma omp critical
    {
        if ((*setflag) == 0) {
            (*setflag)++;
            *sharedvar = input;
            printf("Set in crit with %d\n", input);
        } else {
            printf("Could not set in crit with %d\n", input);
        }
    }
}


int main()
{
    omp_lock_t lck;
    int sharedvar1, sharedvar2;
    int setflag = 0;
    int input = 17;

    omp_set_nested(1);
    omp_set_num_threads(9);
    omp_init_lock(&lck);
#pragma omp parallel shared(lck, sharedvar1, sharedvar2, setflag, input) default(none) num_threads(3)
    {
#pragma omp for
        for (int i=0; i<3; i++) {
#pragma omp parallel shared(lck, sharedvar1, sharedvar2, setflag, input) default(none) 
            {
#pragma omp for
                for (int j=0; j<3; j++) {
                    int id=omp_get_thread_num();
                    setonce_thread(&lck, id, &sharedvar1);
                    setonce_crit(id, &setflag, &sharedvar2);
                }
            }
        }
        omp_unset_lock(&lck);
    }
    omp_destroy_lock(&lck);

    printf("Shared Var 1 = %d\n", sharedvar1);
    printf("Shared Var 2 = %d\n", sharedvar2);
    printf("Set Flag     = %d\n", setflag);
    return 0;
}
0 голосов
/ 23 декабря 2011

Если запись выполняется только один раз для процесса, а не один раз для потока, то вам не нужна синхронизация, потому что синхронизировать ее не с чем.Просто сделайте запись незащищенной.

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