Глобальная закрытая переменная OpenMP - PullRequest
0 голосов
/ 05 декабря 2018

У меня есть вопрос по поводу моего распараллеленного C-кода.Не изменяя тип возвращаемого значения bar() и не добавляя параметры к bar(), я понятия не имею, как сообщить foo() о *number, когда он вызывается рекурсивно после выполнения bar().

Во-вторых, я хотел бы знать, объясняет ли комментарий после bar() окончательный пункт задания?
Для записи в этом контексте r равно maxIndex(A), l равно minIndex(A), A является массивом целых чисел, и все 3 являются параметрами функции foo().

int *number;
#pragma omp threadprivate(number)

void bar(...) 
{ 
    [...] 
    *number = i + 1; 
}

void foo(...)
{
    if(...)
    {
        bar(...);
        // no more tasks for arrays (< 100 elements)?
        #pragma omp task final(r - l <= 100)
            foo(*number - 1);
        #pragma omp task final(r - l <= 100)
            foo(*number + 1);
    }
}

int main(...)
{
    [...]
    #pragma omp parallel
        #pragma omp single
            foo(...);
    #pragma omp taskwait
    [...]
}

1 Ответ

0 голосов
/ 16 января 2019

Вы пытаетесь передать число из одной функции (bar или find_pivot) вызывающей стороне (foo или quicksort).

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

Сравните это:

int find_pivot(int *arr, int low, int high)
{
    return ...;
}

void quicksort(int *arr, int low, int high)
{
    ...
    int pivot_index = find_pivot(arr, low, high);
    quicksort(arr, low, pivot_index - 1);
    quicksort(arr, pivot_index + 1, high);
}

Или используяуказатель (обычно, если у вас есть несколько значений или сложное значение для возврата):

void find_pivot(int *arr, int low, int high, int *pivot_index)
{
    *pivot_index = ...;
}

void quicksort(int *arr, int low, int high)
{
    ...
    int pivot_index = -1;
    find_pivot(arr, low, high, &pivot_index);
    quicksort(arr, low, pivot_index - 1);
    quicksort(arr, pivot_index + 1, high);
}

со следующим (неправильно!), что близко к тому, что вы написали:

int pivot_index;

void find_pivot(int *arr, int low, int high)
{
    pivot_index = ...;
}

void quicksort(int *arr, int low, int high)
{
    ...
    find_pivot(arr, low, high);
    // What happens if two tasks call pivot_index simultaneously?
    // Which value will you get for quicksort? No way of knowing!
    quicksort(arr, low, pivot_index - 1);
    // pivot_index has changed value due to recursive quicksort() ! The next call is wrong!
    quicksort(arr, pivot_index + 1, high);
}

Он не только менее читабелен (например, при чтении быстрой сортировки, откуда берется pivot_index?), Но также должен быть исправлен (не используйте это, это ужасно!):

// can be set from several threads simultaneously
int pivot_index;
#pragma omp threadprivate(pivot_index)

void find_pivot(int *arr, int low, int high)
{
    pivot_index = ...;
}

void quicksort(int *arr, int low, int high)
{
    ...
    find_pivot(arr, low, high);
    // save value to protect from recursive calls
    int my_pivot_index = pivot_index;
    quicksort(arr, low, my_pivot_index - 1);
    quicksort(arr, my_pivot_index + 1, high);
}
...