2013-08-18 301 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