Как я могу преобразовать программу с кодом C в OpenMP, используя задачи и зависимости - PullRequest
0 голосов
/ 07 марта 2020

У меня есть код, написанный на C, и мне нужно преобразовать его в openMP, используя задачи и зависимости.

Ниже мой код:

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

int main(int argc, char *argv[])
{
    //declare two dimensional array A and define its values
    int arrA[3][3] = { { 1, 1,0 }, { 1, 1,0 },{ 1, 1,0 } }; 
    //declare two dimensional array B and give properties of its dimensions
    int arrB[3][3];
    //declare variables to be used
    int diag, i, j,top,left;

    printf("Array A:\n");
    //use for loop to make two dimensional array
    for ( i = 0; i < 3; i++) { 
        for ( j = 0; j < 3; j++) { 
            //display values in two dimensional array A
            printf("%d\t",arrA[i][j]); 
        } 

        printf("\n");  
    } 

    printf("Array B:\n");
    for( i=0;i<3;i++){
        for( j=0;j<3;j++) {
            diag = 0; top=0; left=0;
            if(i-1>=0 && j-1>=0) {
                diag = arrB[i-1][j-1];
            }
            if(i-1>=0) {
                top = arrB[i-1][j];
            }
            if(j-1>=0) {
                left = arrB[i][j-1];
            }
            #pragma omp task private(i, j, top,left) shared(arrA,arrB)\
            depend ( inout: arrA[i][j], arrA[top][left] ) \
           depend ( inout: arrB[i][j] )
            arrB[i][j] = diag + arrA[i][j] + (top-diag) + (left-diag);
        }
    }
    //use for loop to make two dimensional array
    for(i=0;i<3;i++) {
        for(j=0;j<3;j++) {
            //display values in two dimensional array A
            printf("%d\t",arrB[i][j]);
        }
        printf("\n");
    }
}

Я новичок в параллельном программировании и C язык, поэтому я не уверен, как это сделать. Проблема, которую я имею, состоит в том, чтобы закодировать это, имея одну задачу для вычисления каждой записи массива B с соответствующими зависимостями, чтобы гарантировать, что они выполняются в правильном порядке.

То, что я пытаюсь выполнить sh, имеет два размерный массив (массив A) со следующими значениями:

1 1 0
1 1 0
1 1 0

Создайте еще один двумерный массив B, чтобы он выглядел следующим образом:

1 2 2
2 4 4
3 6 6

с задачами и зависимостями openMP.

1 Ответ

0 голосов
/ 08 марта 2020

Сначала необходимо использовать depend(in: ...) и depend(out: ...), чтобы указать входные и выходные зависимости задачи. Кроме того, вы должны включить 3 условия в тело задачи, поскольку они читают ячейки arrB, записанные задачами. Наконец, вы должны добавить секцию #pragma omp parallel и позволить только одному потоку создавать задачи с #pragma omp master из #pragma omp single.

Вот решение:

    printf("Array B:\n");
    #pragma omp parallel
    #pragma omp master
    for( i=0;i<3;i++){
        for( j=0;j<3;j++) {
            #pragma omp task \
                    firstprivate(i, j) \
                    private(diag, top, left) \
                    shared(arrA, arrB) \
                    depend(in: arrB[i-1][j], arrB[i][j-1]) \
                    depend(out: arrB[i][j])
            {
                diag = 0; top=0; left=0;
                if(i-1>=0 && j-1>=0) {
                    diag = arrB[i-1][j-1];
                }
                if(i-1>=0) {
                    top = arrB[i-1][j];
                }
                if(j-1>=0) {
                    left = arrB[i][j-1];
                }
                arrB[i][j] = diag + arrA[i][j] + (top-diag) + (left-diag);
            }
        }
    }
    #pragma omp taskwait

Обратите внимание что зависимость arrB[i-1][j-1] не указана, так как она косвенно включена в другую. arrA[i][j] тоже не нужен, так как в него нет других заданий. Оба варианта являются оптимизациями.

Хотя это решение является правильным, оно, вероятно, будет выполнять код последовательно. Проблема возникает из-за зависимостей: OpenMP не предоставляет простой способ добавления условий для первой строки и первого столбца. Один из способов преодолеть это - разделить код на 3 части, вычисляя каждый возможный случай (громоздкий, поскольку он дублирует код). Другой способ - создать задачу в другом порядке, чтобы не возникали ложные зависимости (например, обход по диагонали). Еще один способ - создать зависимости с помощью указателей (требуется хорошее понимание OpenMP). Ни одно из решений не является действительно хорошим.

PS: Я полагаю, что вы хотите играть с задачами OpenMP и не ожидаете какого-либо ускорения, связанного с распараллеливанием этого кода, поскольку вычисления не достаточно интенсивны, чтобы быть полезным).

...