2015-01-30 8 views
0

Когда я пытаюсь запустить следующий код в моей системе centos, запущенный практически, я получаю правильный вывод, но когда я пытаюсь запустить тот же код на компактном суперкомпьютере «Param Shavak», я ошибаюсь выход .... :(Различные выходные данные OpenMP в разных машинах

#include<stdio.h> 
#include<omp.h> 
int main() 
{ 
    int p=1,s=1,ti 
    #pragma omp parallel private(p,tid)shared(s)  
    { 
    p=1; 
    tid=omp_get_thread_num();  
    p=p+tid;  
    s=s+tid;  
    printf("Thread %d P=%d S=%d\n",tid,p,s);  
    }  
    return 0;  
} 
+1

Редактирование вопроса, чтобы мы могли прочитать код, поможет. Итак, объясняем, каковы различия в выходе. Несмотря на все, что у вас, вероятно, есть * гонка данных *, которая отображается только при ее переносе с одной машины на другую. Вы пробовали использовать код на разных количествах потоков в вашей системе и получали одинаковые результаты каждый раз? –

ответ

0

Если ваша программа работает правильно в одной машине, он должен быть, потому что это на самом деле не работает параллельно в этой машине.

Ваша программа страдает от гонки в s=s+tid; строка кода. s - общая переменная, поэтому несколько потоков одновременно пытаются ее обновить, wh Это приводит к потере данных.

Вы можете решить эту проблему, превратив эту строку кода в атомарные операции:

#pragma omp atomic 
s=s+tid; 

Таким образом, только один поток может одновременно читать и обновлять переменную s и состояние гонки не более ,

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

EDIT: Как было предложено пользователем High Performance Mark, я должен отметить, что вышеприведенная программа очень неэффективна из-за атомной операции. Правильный способ сделать такой расчет (добавление к одной и той же переменной во всех итерациях цикла) заключается в реализации сокращения . OpenMP позволяет легко с помощью reduction пункт:

#pragma omp reduction(operator : variables) 

Попробуйте эту версию программы, с помощью сокращения:

#include<stdio.h> 
#include<omp.h> 
int main() 
{ 
    int p=1,s=1,tid; 
    #pragma omp parallel reduction(+:s) private(p,tid) 
    { 
      p=1; 
      tid=omp_get_thread_num(); 
      p=p+tid; 
      s=s+tid; 
      printf("Thread %d P=%d S=%d\n",tid,p,s); 
    } 
    return 0; 
} 

Следующая ссылка объясняет критические секции, атомарные операции и сокращение более многословным способом : http://www.lindonslog.com/programming/openmp/openmp-tutorial-critical-atomic-and-reduction/

+1

Если бы мне было сложно написать ответ, я бы предложил использовать * сокращение *, а не эффективно выполнять последовательное выполнение кода. –

+0

@HighPerformanceMark Для более общего практического случая я бы предложил именно это, конечно. Но контекст подсказывал мне, что проблема была упражнением новичка. В этот момент я подумал, что лучше дать самое простое решение, которое гарантирует правильное выполнение, и пусть OP узнает о сокращении позже. –

+0

Просто сделал то, что вы предложили, @HighPerformanceMark. Теперь лучше? –

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