OpenMP разделить для цикла по ядрам - PullRequest
2 голосов
/ 29 ноября 2011

Я пытаюсь выполнить некоторое приложение параллельно, используя инструкции sse и openmp. Что касается части openmp, у меня есть код вроде:

for(r=0; r<end_condition; r++){
    .. several nested for loops inside ..
}

Я хочу разделить этот цикл по r на несколько ядер, и, например, при использовании двух ядер одно ядро ​​должно выполнить r = 0 .. r = end_condition / 2-1, а другое r = end_condition / 2 .. r = end_condition-1. Связь между итерациями цикла отсутствует, поэтому они могут выполняться параллельно, в конце цикла r результаты должны быть синхронизированы.

Как я могу разделить это по ядрам, используя директивы openmp? Должен ли я развернуть цикл над r и использовать openmp секции?

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

Ответы [ 4 ]

1 голос
/ 29 ноября 2011

С помощью следующего кода компилятор генерирует параллельную область, которая выполняется N потоками.

omp_set_num_threads(N);

#pragma omp parallel for
for(int r = 0; r < end_condition; ++r)
{
    .. several nested for loops inside ..
}

Каждый поток выполняет подмножество из end_condition. Обратите внимание, что ваша счетная переменная r теперь объявлена ​​внутри параллельной omp для области видимости. Теперь у каждого потока есть своя подсчетная переменная.

Та же цель может быть достигнута с помощью параллельной прагмы, а не параллели для, например:

omp_set_num_threads(N);
#pragma omp parallel private(r)
{
   int tid = omp_get_thread_num();
   for(r = (end_condition/N) * tid; r < (end_condition/N) * (tid+1) ; ++r)
   {
    .. several nested for loops inside ..
   }
}

конечно, только когда end_condition% N = 0, но вы можете получить сделку. Здесь переменная r явно помечена как приватная для потока и может быть объявлена ​​там, где вы хотите. Компилятор сгенерирует копию для каждого потока.

1 голос
/ 29 ноября 2011

Вы можете достичь этого, добавив:

#pragma omp parallel for
for(r=0; r<end_condition; r++){
    .. several nested for loops inside ..
}

Вы должны убедиться, что в вашем цикле является общим и частным. Хотя это не гарантирует, что r делится, как вы упомянули. Если вы хотите иметь это в явном виде, вы можете использовать задачи. Но делать это вручную не очень удобно, и я не могу рекомендовать это.

0 голосов
/ 29 ноября 2011

Я могу только добавить, что у вас могут возникнуть проблемы, если разные итерации цикла занимают разное время - в этом случае вы захотите добавить schedule (dynamic):

#pragma omp parallel for schedule (dynamic)
for(r=0; r<end_condition; r++){
    .. several nested for loops inside ..
}

Также обратите внимание, что барьер автоматически добавляется в конце цикла, поэтому вы можете быть уверены, что выполнение продолжается только после завершения всех итераций. если это нежелательно (у вас есть другая работа, выполняемая параллельно с циклом) - добавьте nowait к параметрам директивы for. Затем вы можете запросить синхронизацию с #pragma omp barrier.

0 голосов
/ 29 ноября 2011

Вы можете установить количество потоков, которые должен создать цикл for. И для каждого потока вы можете указать размер куска.

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