2013-08-18 174 views
0

我有一個程序,它將2個大數字作爲char向量提供。 現在我必須確保它使用OpenMP。我有嵌套循環的問題,如果我使用它們,結果不是我期待的。我非常感謝你的幫助。 這裏的代碼在OMP中嵌套for循環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

不錯的建議高性能標記,我會試試:) –

回答

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; 
     } 

你做(每次)的主要錯誤...當你進入一個並行區域必須的例子照顧你的變量。什麼是共享的,什麼是每個線程私有的?在你的結束循環中,你不使用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條款

所以你的for循環計算sum += temp[y+i]可以用

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

重寫,而且你必須遵循所有的算法在每個環繞的和嵌套的parallel區域上使用sharedprivate子句的邏輯。

+0

是的,我認爲它可能是關於變量私人/共享聲明。如果我不聲明他們比循環轉向變量是私人的,其他人是公共的權利? –

+0

是在循環中聲明的所有var,包括(int j ...)的轉向變量var都是私有的,其他變量是公有的 – alexbuisson