2013-08-18 5 views
0

У меня есть программа, которая умножает 2 больших числа, предоставляемых как векторы символов. Теперь я должен убедиться, что он использует OpenMP. У меня проблема с вложенными циклами, если я использую их, результат не является тем, что я ожидаю. Я очень признателен вам за вашу помощь. Вот кодВложенные для циклов в OMP C

#include<stdio.h> 
#include<math.h> 
#include<stdlib.h> 
#include<string.h> 
#include<omp.h> 
#include<time.h> 
#define MAX 100000 

char * multiply(char [],char[], int manyThreads); 
int main(){ 
    //omp_set_dynamic(1); 
    omp_set_nested(1); 
    omp_set_num_threads(8); 
    char a[MAX]; 
    char b[MAX]; 
    char *c;  

    printf("First number : "); 
    scanf("%s",a); 
    printf("Second number : "); 
    scanf("%s",b); 
    printf("Result : "); 
    double start = omp_get_wtime(); 

    c = multiply(a,b,1); 
    printf("%s\n",c); 
    double end = omp_get_wtime(); 
    printf("Calculation time = %.16g\n", end - start); 

    return 0; 
} 

char * multiply(char a[],char b[], int manyThreads){ 
    static char result[MAX]; 
    char tempResult[MAX]; 
    char temp[MAX]; 
    int aLength,bLength; 
    int i,j,k=0,x=0,y; 
    long int r=0; 
    long sum = 0; 
    aLength=strlen(a)-1; 
    bLength=strlen(b)-1; 

    #pragma omp parallel if(manyThreads == 1) 
    { 
     #pragma omp for schedule(dynamic) nowait 
     for(i=0;i<=aLength;i++) 
     { 
      a[i] = a[i] - 48; 
     } 

     #pragma omp for schedule(dynamic) nowait 
     for(i=0;i<=bLength;i++) 
     { 
      b[i] = b[i] - 48; 
     } 
    } 

    #pragma omp parallel if(manyThreads == 1) 
    {  
     #pragma omp for schedule(dynamic) 
     for(i=bLength;i>=0;i--) 
     { 
      r=0; 

      #pragma omp parallel 
      { 
       #pragma omp for schedule(dynamic) 
       for(j=aLength;j>=0;j--) 
       { 
        temp[k++] = (b[i]*a[j] + r)%10; 
       r = (b[i]*a[j]+r)/10; 
       } 
      } 
      temp[k++] = r; 
      x++; 
      #pragma omp parallel 
      { 
       #pragma omp for schedule(dynamic)    
       for(y = 0;y<x;y++) 
       { 
        temp[k++] = 0; 
       }  
      }     
     } 
    } 

    k=0; 
    r=0; 
    #pragma omp parallel if(manyThreads == 1) 
    { 
     #pragma omp for schedule(dynamic) 
     for(i=0;i<aLength+bLength+2;i++) 
     { 
      sum =0; 
      y=0; 
      #pragma omp parallel 
      { 
       #pragma omp for schedule(dynamic) 
       for(j=1;j<=bLength+1;j++) 
       { 
        if(i <= aLength+j) 
        { 
         sum = sum + temp[y+i]; 
        } 
        y += j + aLength + 1; 
       } 
      } 

      tempResult[k++] = (sum+r) %10; 
      r = (sum+r)/10;    
     } 
    } 
    tempResult[k] = r; 
    j=0; 

    #pragma omp parallel if(manyThreads == 1) 
    { 
     #pragma omp for schedule(dynamic) 
     for(i=k-1;i>=0;i--) 
     { 
      result[j++]=tempResult[i] + 48; 
     } 
    } 

    result[j]='\0'; 

    if(result[0]==48) 
    { 
     result[0]=255; 
    } 

    return result; 
} 
+0

Ожидает, что у вас есть * гонка данных *, две или более темы, связанные с обновлением переменной. Используйте предложение 'default (none)' на всех ваших параллельных прагмах и укажите, какая переменная должна быть разделена и какая частная. Дисциплина этого упражнения приведет вас к решению вашей проблемы. –

+0

Хороший совет Высокая производительность Mark, я попробую это :) –

ответ

2

Я могу подтвердить, что у вас есть некоторая ошибка гонки данных.
Без OpenMP:

First number : 123456 
Second number : 654321 
Result :  08563613376 
Calculation time = 0.005543371655221563 

с OpenMP:

First number : 123456 
Second number : 654321 
Result :  00000000825 
Calculation time = 0.007188999978097854 

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

#pragma omp for schedule(dynamic) nowait 
     for(int i=0;i<=aLength;i++) 
     { 
      a[i] = a[i] - 48; 
     } 

И пример главной ошибки вы сделали (каждый раз) ... при входе в параллельную область вы MUST позаботьтесь о своей переменной. что общего, что является приватным для каждого потока? В конце цикла вы не используете nested parallelism, но в каждом потоке вы делаете j++, поэтому вам следует защитить j, как показано ниже.

#pragma omp parallel if(manyThreads == 1) shared(j) 
    { 
     int pos; 
#pragma omp for schedule(dynamic) 
     for(int i=k-1;i>=0;i--) 
     { 
#pragma omp atomic capture 
      pos = j++; 

      result[pos]=(tempResult[i] + 48); 
     } 
    } 

Обратите внимание, что вы также забывать, что OpenMP for конструкции имеет пункт reduction

так ваш цикл для вычисления sum += temp[y+i] можно переписать с

#pragma omp for schedule(dynamic) reduction(+:sum) 

И вы должны следовать все вашему алгоритму логики использовать shared и private пункт на каждом из ваших окружающих и вложенных parallel региона.

+0

Да, я думал, что это может быть о переменных частных/общих декларациях. Если я не объявляю их, а переменные руля управления являются частными, а другие - общедоступными? –

+0

да все переменные, объявленные в цикле, включая рулевое управление var for (int j ...), являются частными, другие являются общедоступными – alexbuisson