2016-06-30 12 views
1

Мой код с openmp с использованием «сокращения» не возвращает те же результаты от запуска до запуска.Сокращение в Openmp возвращает разные результаты с тем же числом потоков в моем коде

Случай 1: с помощью "сокращения"

sum = 0; 
omp_set_num_threads(4); 
#pragma omp parallel for reduction(+:sum) 
for(ii = 0; ii < 100; i++) 
    sum = sum + func(ii); 

с FUNC (II) имеет побочные эффекты. Фактически, func (ii) использует другую функцию calcul(), которая может привести к условию гонки при параллельном выполнении. Я думаю, что функция calcul() может быть причиной этой проблемы. Тем не менее, я использую «критический», результаты всегда одни и те же, но это решение не подходит для производительности. Второй

Корпус: с помощью "критического"

sum = 0; 
#pragma omp parallel for 
for(ii = 0; ii < 100; i++) 
{ 
    #pragma omp critical 
    sum = sum + func(ii); 
} 

с FUNC (II) функции

func(int val) 
{ 
    read_file(val); 
    calcul(); /*calculate something from reading_file(val)*/ 
    return val_fin; 
} 

Пожалуйста, помогите мне решить это?

Большое спасибо!

+0

Похоже, ваш вопрос не с 'reduction' части, но в состоянии гонки в рамках' FUNC (II) 'вызова. Поскольку мы не можем видеть код для 'func' или' calcul', трудно сказать что-то еще. –

+0

Привет, Dan, мой func (ii) также усложняет, тогда я могу представить вам его копию func (ii) {... read (ii); ... calcul(); ... возвращаемое значение; } – hamalo

+0

Вам не нужно публиковать всю функцию, достаточно, чтобы * воссоздать вашу проблему * и сделать ваш вопрос понятным. См. [Как создать минимальный, полный и проверенный пример] (http://stackoverflow.com/help/mcve). –

ответ

0

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

Связанные вопрос: Order of execution in Reduction Operation in OpenMP

+0

Спасибо Phadjido: D – hamalo

1

Причина, по которой вы получаете низкую производительность во втором случае, - это весь корпус цикла в critical, поэтому он не может фактически выполнять что-либо параллельно.

Поскольку вы говорите, что существуют некоторые условия гонки в функции calcul, подумайте о том, чтобы разместить раздел critical только на этой линии внутри func. Таким образом, файлы могут считываться параллельно (что может быть вводом-выводом, которое все равно замедляет ваше выполнение).

Если производительность по-прежнему оставляет желать лучшего, вам нужно будет изучить вложенную функцию calcul и попытаться определить условия гонки.

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

+0

Thanks @Dan. Я сосредотачиваюсь на тех же результатах, «критический» может ответить на этот вопрос, но это плохо для производительности. Я попробую с вашей поддержкой – hamalo

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

  • Нет связанных вопросов^_^