2011-03-20 63 views
0

我在打開MP開放MP - 點積

實現並行積我有這樣的代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#include <math.h> 
#include <omp.h> 
#define SIZE 1000 

int main (int argc, char *argv[]) { 

    float u[SIZE], v[SIZE], dp,dpp; 
    int i, j, tid; 

    dp=0.0; 
    for(i=0;i<SIZE;i++){ 
     u[i]=1.0*(i+1); 
     v[i]=1.0*(i+2); 
    } 
    printf("\n values of u and v:\n"); 

    for (i=0;i<SIZE;i++){ 
     printf(" u[%d]= %.1f\t v[%d]= %.1f\n",i,u[i],i,v[i]); 
    } 
    #pragma omp parallel shared(u,v,dp,dpp) private (tid,i) 
    { 
     tid=omp_get_thread_num(); 

     #pragma omp for private (i) 
     for(i=0;i<SIZE;i++){ 
      dpp+=u[i]*v[i]; 
      printf("thread: %d\n", tid); 
     } 
     #pragma omp critical 
     { 
      dp=dpp; 
      printf("thread %d\n",tid); 
     } 


    } 

    printf("\n dot product is %f\n",dp); 

} 

我與啓動它:pgcc -B -Mconcur -Minfo -o prog prog.c

,並導致我在控制檯中看到是:

33, Loop not parallelized: innermost 

39, Loop not vectorized/parallelized: contains call 

48, Loop not vectorized/parallelized: contains call 

上午什麼我做錯了?

從我的角度側,一切正常。

+0

你是什麼意思不對,編譯成功?該調用似乎是'printf'。 – 2011-03-20 11:32:25

+0

編譯時得到此信息 – Waypoint 2011-03-20 11:33:54

+1

您看到的消息不是OpenMP信息性消息。您使用了-Mconcur,這意味着您希望編譯器自動協調(或自動並行)代碼。要使用OpenMP,正確的選項是-mp。 – ejd 2011-03-21 01:26:50

回答

1

首先,一個簡單的1000元的點積沒有足夠的計算成本的理由多線程---你會在通信和同步的成本付出了那麼多比你更會在性能增益,這是不值得。

其次,它看起來像你正在計算全積在每個線程,而不是分割在多個線程的計算,結果在年底合併。

下面是如何做向量的點積從https://computing.llnl.gov/tutorials/openMP/#SHARED

#include <omp.h> 

main() 
{ 
    int i, n, chunk; 
    float a[100], b[100], result; 

    /* Some initializations */ 
    n = 100; 
    chunk = 10; 
    result = 0.0; 
    for (i=0; i < n; i++) { 
     a[i] = i * 1.0; 
     b[i] = i * 2.0; 
    } 

    #pragma omp parallel for  \ 
     default(shared) private(i) \ 
     schedule(static,chunk)  \ 
     reduction(+:result) 

    for (i=0; i < n; i++) 
     result += (a[i] * b[i]); 

    printf("Final result= %f\n",result); 
} 

基本上與實施,OpenMP是好做,當你有大的,昂貴的循環粗粒度並行。一般來說,在進行並行編程時,重新同步之前可以執行的計算「塊」越大越好。特別是隨着內核數量的增長,通信和同步成本將會增長。假設每次同步(抓取新的索引或大塊索引以執行,輸入關鍵部分等)花費10ms或1M指令,以更好地瞭解何時/何地/如何並行化代碼。

2

的問題仍然是相同的最新問題。你是在一個變量累積值,你必須告訴OpenMP的該怎麼做:

#pragma omp for reduction(+: dpp) 
for(size_t i=0; i<SIZE; i++){ 
    dpp += u[i]*v[i]; 
} 

使用循環局部變量的指標,這是你所需要的,忘掉所有你正在做的周圍的東西那。如果你想看看編譯器在你的代碼中做了什麼,用-S運行它並檢查彙編器輸出。這可能非常具有啓發性,因爲您隨後會了解這些簡單的語句在並行化時如何。

,並且不要循環使用的索引int。尺寸和這樣的東西是size_t

+0

您不必使用循環局部變量。它可以在for指令的一個子句中聲明爲私有的,或者如果for循環的工作循環是規範形式,那麼默認情況下循環索引將是私有的。另外,除非您使用OpenMP V3.0,否則不能將size_t變量用作循環索引。 – ejd 2011-03-21 01:23:27

+0

@ejd,我沒有說「他必須」。我給出的表格只是最簡單的形式,簡潔易讀。如果他不能使用'size_t',編譯器會告訴他,但這是C語言正確的索引類型。 – 2011-03-21 06:55:51

+0

雖然我不知道pgcc編譯器,但大多數編譯器在OpenMP工作共享的規範形式出現問題時都不會給出非常好的錯誤消息。用戶很可能會看到一條消息,說明初始化,條件和循環增量有問題 - 將其留給用戶來確定循環迭代變量不能無符號。 – ejd 2011-03-21 13:01:35