Предоставить потоку частный предварительно выделенный буфер для параллельного цикла for ()? - PullRequest
1 голос
/ 20 октября 2011

Моя программа содержит цикл for (), который построчно обрабатывает некоторые необработанные данные изображения, которые я хочу распараллелить с помощью OpenMP следующим образом:

...
#if defined(_OPENMP)
        int const  threads = 8;
        omp_set_num_threads( threads );
        omp_set_dynamic( threads );
#endif
        int line = 0;
#pragma omp parallel private( line )
        {
            // tell the compiler to parallelize the next for() loop using static
            // scheduling (i.e. balance workload evenly among threads),
            // while letting each thread process exactly one line in a single run
#pragma omp for schedule( static, 1 )
            for( line = 0 ; line < max; ++line ) {
                // some processing-heavy code in need of a buffer
            }
        } // end of parallel section
....

Вопрос такой:

Можно ли предоставить отдельный (предварительно выделенный) буфер (указатель) для каждого потока команды, выполняющей мой цикл, используя стандартную прагму / функцию OpenMP (таким образом устраняя необходимость выделять новый буфер с помощью каждый цикл)?

Заранее спасибо.

Бьорн

Ответы [ 2 ]

2 голосов
/ 21 октября 2011

Есть threadprivate: http://msdn.microsoft.com/en-us/library/2z1788dd

static int buffer[BUFSIZE];
#pragma omp threadprivate(buffer)

Эта прагма работает с глобальной / статической переменной, поэтому вам не нужно беспокоиться о переполнении стека. (В таком случае переполнения стека вообще неплохо бы увеличить размер стека путем настройки опции компоновщика.)

Обратите внимание, что компиляторы могут иметь разные детали реализации для threadprivate. Например, компилятор VS 2010 не может сделать makepriprivate, если переменная имеет конструктор. Однако компилятор Intel C / C ++ отлично справляется с этой задачей.

Использование отдельных omp parallel и omp for также является хорошей идеей, как показала Сехе. Однако использование threadprivate позволяет использовать omp parallel for напрямую.

К вашему сведению: даже если вам нужно выделить свое собственное локальное хранилище потоков, во многих случаях вам на самом деле не нужно вызывать вызов функции для конкретной ОС, такой как TlsAlloc. Вы можете просто выделить массив из N структур данных. И затем получите к ним доступ, используя omp_get_thread_num, который дает идентификатор потока от 0 до N-1. Конечно, вы должны учитывать ложное совместное использование, вставляя отступы, чтобы гарантировать, что каждая структура данных должна быть выровнена по разной строке кэша (в основном современные кэши ЦП имеют строку кэша по 64 байта).

2 голосов
/ 20 октября 2011

Возможно, я вас неправильно понимаю, но я думаю, что это должно сработать:

#pragma omp parallel 
{
    unsigned char buffer[1024]; // private

    // while letting each thread process exactly one line in a single run
    #pragma omp for // ... etc
    for(int line = 0; line < max; ++line ) {
          //...
    }
}

Если вы действительно хотели использовать один и тот же буфер для разных блоков параллелизма, вам придется прибегнуть клокальное хранилище(В Boost, а также в C ++ 11 есть средства, позволяющие сделать это проще (и более переносимым), чем непосредственное использование TlsAlloc и друзей).этот подход заменяет часть бремени проверки безопасности потока на программиста, потому что вполне возможно иметь одновременно запущенные различные секции omp parallel, особенно когда они вложены.

Учтите, что параллельные блоки могут быть вложенными во время выполнения, даже если они не являются лексически вложенными.На практике это обычно не очень хороший стиль и часто приводит к плохой работе.Тем не менее, это то, что вы должны знать при этом).

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