Запуск потока для каждого внутреннего цикла в OpenMP

Я довольно плохо знаком с OpenMP, и я пытаюсь запустить отдельный поток для обработки каждого объекта в 2D массиве.

Таким образом, по существу, это:

for (i = 0; i < dimension; i++) {
    for (int j = 0; j < dimension; j++) {
        a[i][j] = b[i][j] + c[i][j];

То, что я делаю, является этим:

#pragma omp parallel for shared(a,b,c) private(i,j) reduction(+:diff) schedule(dynamic)
    for (i = 0; i < dimension; i++) {
        for (int j = 0; j < dimension; j++) {
            a[i][j] = b[i][j] + c[i][j];

Это на самом деле запускает поток для каждого 2D объекта или нет? Как я протестировал бы это? Если неправильно, что корректный путь состоит в том, чтобы сделать это?Спасибо!

Примечание: Код был значительно упрощен

6
задан achinda99 7 February 2010 в 16:21
поделиться

2 ответа

В вашем примере кода параллелен только внешний цикл. Вы можете проверить, распечатав во внутреннем цикле omp_get_thread_num(), и вы увидите, что для заданного i нумерация потока одинакова (конечно, этот тест является демонстративным, а не окончательным, т.к. разные прогоны дадут разные результаты). Например, с:

#include <stdio.h>
#include <omp.h>
#define dimension 4

int main() {
    #pragma omp parallel for
    for (int i = 0; i < dimension; i++)
        for (int j = 0; j < dimension; j++)
            printf("i=%d, j=%d, thread = %d\n", i, j, omp_get_thread_num());
    }

I get:

i=1, j=0, thread = 1
i=3, j=0, thread = 3
i=2, j=0, thread = 2
i=0, j=0, thread = 0
i=1, j=1, thread = 1
i=3, j=1, thread = 3
i=2, j=1, thread = 2
i=0, j=1, thread = 0
i=1, j=2, thread = 1
i=3, j=2, thread = 3
i=2, j=2, thread = 2
i=0, j=2, thread = 0
i=1, j=3, thread = 1
i=3, j=3, thread = 3
i=2, j=3, thread = 2
i=0, j=3, thread = 0

Что касается остального вашего кода, вы можете захотеть вставить больше подробностей в новый вопрос (трудно сказать по маленькому образцу), но, например, нельзя ставить private(j), когда j объявляется только позже. В моем примере, приведенном выше, он автоматически является приватным. Думаю, что diff - это переменная, которую мы не видим в примере. Также переменная цикла i автоматически приватна (из версии 2.5 spec - то же самое в 3.0 spec)

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

Правка: Все вышеизложенное верно для кода, который мы с вами показали, но вас может заинтересовать следующее. Для OpenMP версии 3.0 (доступно, например, gcc версии 4.4, но не версии 4.3) есть пункт collapse, где вы можете написать код, как у вас есть, но с помощью #pragma omp parallel for collapse (2) для распараллеливания обоих циклов (см. спецификацию ).

Редактирование : OK, я скачал gcc 4.5.0 и запустил приведенный выше код, но используя collapse (2) для получения следующего вывода, показывающего, что внутренний цикл теперь распараллелен:

i=0, j=0, thread = 0
i=0, j=2, thread = 1
i=1, j=0, thread = 2
i=2, j=0, thread = 4
i=0, j=1, thread = 0
i=1, j=2, thread = 3
i=3, j=0, thread = 6
i=2, j=2, thread = 5
i=3, j=2, thread = 7
i=0, j=3, thread = 1
i=1, j=1, thread = 2
i=2, j=1, thread = 4
i=1, j=3, thread = 3
i=3, j=1, thread = 6
i=2, j=3, thread = 5
i=3, j=3, thread = 7

Комментарии здесь (поиск "Обходных путей") также относятся к обходным путям в версии 2.5, если вы хотите распараллелить оба цикла, но спецификация версии 2.5, приведенная выше, достаточно ясна (см. несоответствующие примеры в разделе A.35). ).

7
ответ дан 17 December 2019 в 00:09
поделиться

Можно попробовать использовать вложенные omp параллельные fors (после вызова omp_set_nested(1)), но они поддерживаются не во всех реализациях openmp.

Итак, я думаю сделать какую-нибудь двумерную сетку и начать все потоки на сетке с одного, например (например, для фиксированной сетки 4x4 потоков):

#pragma omp parallel for
for(k = 0; k < 16; k++)
{
    int i,j,i_min,j_min,i_max,j_max;
    i_min=(k/4) * (dimension/4);
    i_max=(k/4 + 1) * (dimension/4);
    j_min=(k%4) * (dimension/4);
    j_max=(k%4 + 1) * (dimension/4);

    for(i=i_min;i<i_max;i++)
      for(j=j_min;j<j_max;j++)
       f(i,j);

}
0
ответ дан 17 December 2019 в 00:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: