Поделиться переменной с областью действия в OpenMP - PullRequest
0 голосов
/ 01 августа 2020

Я работаю с OpenMP и хотел бы поделиться переменной, объявленной внутри блока с областью видимости, между потоками. Вот общее представление о том, что я делаю:

#pragma omp parallel
{
    // ...parallel code...
    {
        uint8_t* pixels;
        int pitch;
#pragma omp barrier
#pragma omp master
        {
            // SDL video code must be run in main thread
            SDL_LockTexture(renderTexture.get(), nullptr, (void**)&pixels, &pitch);
        }
#pragma omp barrier
        // parallel code that reads `pixels` and `pitch` and writes to texture
#pragma omp barrier
#pragma omp master
        {
            // Once done, main thread must do SDL call again (this will upload texture to GPU)
            SDL_UnlockTexture(renderTexture.get());
        }
    }
}

При компиляции как есть, pixels и pitch будут приватными для потока и будут устанавливаться только в основном потоке, что приведет к segfault. Есть ли способ поделиться этими переменными, не увеличивая их область действия (объявляя их перед #pragma omp parallel) или без необходимости объединяя и повторно создавая потоки (оставляя распараллеленную часть и вводя другой блок #pragma omp parallel)?

1 Ответ

1 голос
/ 03 августа 2020

Одним из способов решения этой проблемы является использование задач OpenMP . Вот пример:

#pragma omp parallel
{
    // ...parallel code...

    // May not be needed
    #pragma omp barrier

    #pragma omp master
    {
        uint8_t* pixels;
        int pitch;

        // SDL video code must be run in main thread
        SDL_LockTexture(renderTexture.get(), nullptr, (void**)&pixels, &pitch);

        // Note that the variables are firstprivate by default for taskloops  
        // and that shared variables must be explicitly listed as shared here
        // (as opposed to an omp for).
        #pragma omp taskloop collapse(2) firstprivate(pixels, pitch)
        for(int y=0 ; y<height ; ++y)
        {
            for(int x=0 ; x<width ; ++x)
            {
                // Code reading `pixels` and `pitch` and writing into texture
            }
        }

        // Once done, main thread must do SDL call again (this will upload texture to GPU)
        SDL_UnlockTexture(renderTexture.get());
    }

    // May not be needed
    #pragma omp barrier
}

Эта реализация, основанная на задачах, выигрывает от меньшего количества синхронизаций (дорого в многоядерных системах).

Другой возможной альтернативой является используйте указатели, чтобы поделиться значением частной переменной с другими потоками. Однако этот подход требует, чтобы некоторые общие переменные были объявлены вне параллельной секции, что может быть невозможно в вашем случае.

...