2012-04-16 4 views
4

Я хочу распараллеливать с помощью openMP функцию, которая отбирает поле (выборочно выбирает точки в поле и оценивает данную функцию в этих точках). Я написал следующий код.openMP - параллельный доступ к переменным и атомам

//storing points 
double** points_ = new double*[N-m]; 
for(int i=0;i<N-m;i++) 
{ 
    points_[i]=new double[ndim]; 
} 
double* evals_ = new double[N-m]; 

#pragma omp parallel for 
for(int i=0;i<N-m;i++) 
{ 
    double* pt_ = randomPoint(lower,upper); 
    for(int k=0;k<ndim;k++) 
    { 
     points_[i][k]=pt_[k]; 
    } 
    evals_[i]=evalFunc(pt_); 
    delete pt_; 
} 

Однако, я не уверен в этом коде: evals_ и points_ обновляются в eauch thread. Я думаю о добавлении некоторых атомных заявлений есть:

#pragma omp parallel for 
for(int i=0;i<N-m;i++) 
{ 
    double* pt_ = randomPoint(m_lower,m_upper); 
    for(int k=0;k<m_ndim;k++) 
    { 
     #pragma omp atomic update 
     points_[i][k]=pt_[k]; 
    } 
    #pragma omp atomic update 
    evals_[i]=evalFunc(pt_); 
    delete pt_; 
} 

, но я боюсь, что это было бы очень unefficient: у вас есть несколько советов, чтобы написать более точно? И ... это не компиляции ... (ошибка: выражение, следующее #pragma OMP атомные имеют неправильную форму) Althought я могу найти, что в OpenMP из базы подписки спецификации, A22

void atomic_example(float *x, float *y, int *index, int n) 
{ 
    int i; 
    #pragma omp parallel for shared(x, y, index, n) 
    for (i=0; i<n; i++) { 
    #pragma omp atomic update 
    x[index[i]] += work1(i); 
    y[i] += work2(i); 
    } 
} 

и атомное обновление также следует здесь аффектация массива.

Спасибо и приветствую.

EDIT --------

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

for(i=0;i<m_ndim;i++) 
{ 
    double sum_=0; 
    #pragma omp parallel reduction(+:sum_) 
    for(j=0;j<m_npts;j++) 
    { 
     sum_ += set_[j][i]; 
    } 
    Sum_[i] = sum_; 
} 

Почему тогда нужен? Или что-то еще не так?

ответ

3

Вам не нужны никакие атомные предложения в коде.

Причина заключается в том, что внешний контур расщепляется по индексу i, так что каждый поток получит набор элементов из points_ и eval_, которые не перекрываются с рабочим набором другого потока.

evals_ - это массив, поэтому каждый поток будет получать непрерывный подмассив (из-за неявной статической схемы планирования), например.

0 1 2 3 . 4 5 6 7 . 8 9 10 11... 
    t1  t2  t3 

points_ является двухразмерной матрицей, и каждый поток получит непрерывный набор строк:

0 
    1 
t1 2 
    3 
    . 
    4 
    5 
t2 6 
    7 
    . 
    8 
    9 
t3 10 
    11 
    ... 

В этом втором случае может показаться, что у вас есть перекрытие на величине k, потому что каждое нить имеет тот же диапазон для k, но обновленные точки попадают на разные строки (индекс i), которые, как показано выше, не перекрываются для разных потоков.

+0

Я согласен! Тем не менее, теперь я не понимаю, почему эта другая часть кода (я отредактировал мой пост выше с этим образцом) рушится, сообщая мне, что существует параллельный доступ в строке 'sum _ + = set_ [j] [i]'. Благодаря ! – octoback

+0

@dlib: Разве это не должно быть '#pragma omp parallel для сокращения ...'? Кажется, вам не хватает 'for', что дает совсем другую семантику вычисления. – Tudor

Смежные вопросы