2011-06-06 27 views
2

我正在使用不支持複雜參數的reduce()的openMP版本。我需要一個像帶有openMP的複數向量的點積

std::complex<double> dot_prod(std::complex<double> *v1,std::complex<double> *v2,int dim) 

{ 
    std::complex<double> sum=0.; 
    int i; 
# pragma omp parallel shared(sum) 
# pragma omp for 
    for (i=0; i<dim;i++) 
    { 
#pragma omp critical 
     { 
      sum+=std::conj<double>(v1[i])*v2[i]; 
     } 
    } 
    return sum; 
} 

快速點積函數顯然,這代碼不加快的問題,但減緩下來。你是否有一個快速的解決方案,而不使用reduce()來處理複雜的參數?

+1

注意,讓內容的並行for循環中的一個關鍵部分是像(或更糟)所有 – CharlesB 2011-06-06 10:25:15

回答

4

每個線程都可以計算出私人總數作爲第一步,並且作爲第二步可以組成最終總和。在這種情況下,關鍵部分僅在最後一步中需要。

std::complex<double> dot_prod(std::complex<double> *v1,std::complex<double> *v2,int dim) 
{ 
    std::complex<double> sum=0.; 
    int i; 
    # pragma omp parallel shared(sum) 
    { 
    std::complex<double> priv_sum = 0.; 
    # pragma omp for 
    for (i=0; i<dim;i++) 
    { 
     priv_sum += std::conj<double>(v1[i])*v2[i]; 
    } 

    #pragma omp critical 
    { 
     sum += priv_sum; 
    } 
    } 
    return sum; 
} 
1

嘗試在平行做乘法,然後總結它們串聯:

template <typename T> 
std::complex<T> dot_prod(std::complex<T> *a, std::complex<T> *b, size_t dim) 
{ 
    std::vector<std::complex<T> > prod(dim); // or boost::scoped_array + new[] 

    #pragma omp parallel for 
    for (size_t i=0; i<dim; i++) 
     // I believe you had these reversed 
     prod[i] = a[i] * std::conj(b[i]); 

    std::complex<T> sum(0); 
    for (size_t i=0; i<dim; i++) 
     sum += prod[i]; 

    return sum; 
} 

這確實需要O(暗)工作記憶,當然。

+0

感謝快速回答在沒有做並行!這是一個好主意,但不幸的是它的縫隙使得對於dim = 10^7的矢量(我測試過)它的速度仍然快3倍,而不是以這種方式使用openMP,而是使用非並行版本。我也將產品外包給外包商,但這並沒有改變這種情況。 – 2011-06-06 10:50:44

+0

@pawel:根據@Christian Rau的建議,您可能想自己編寫一個reduce算法。或者拿一個支持OpenMP'reduce'的更好的編譯器:) – 2011-06-06 11:20:57

+1

@pawel_winzig:由於大型向量的點積往往受存儲器帶寬而不是觸發器的限制,這並不奇怪。 – janneb 2011-06-06 11:24:00

0

爲什麼不能有N個線程計算N個單獨的總和。然後最後你只需要求和N個和,可以連續完成,因爲N很小。雖然我不知道如何用OpenMP來完成這個任務,但目前(我沒有任何經驗),我很確定這很容易實現。