2013-01-19 119 views
3

我有以下程序:OpenMP並行與浮點範圍

int main(){ 
    double sum=0; 
    #pragma omp parallel for reduction(+:sum) 
    for(double x=0;x<10;x+=0.1) 
    sum+=x*x; 
} 

當我編譯它,我得到的錯誤invalid type for iteration variable ‘x’

我認爲這意味着我只能將parallel for構造應用於基於整數的循環。但是我的循環的內部真的取決於它是浮點。

有沒有辦法說服OpenMP來做到這一點?有推薦的替代方法嗎?

+2

不,由於與給出的答案相同的原因[這裏](http://stackoverflow.com/a/13403626/463827);即使它在某些情況下可能會起作用,但編譯器並不是非常難以以分解循環的方式推斷浮點數。 (甚至這個循環的純序列優化/矢量化也會因爲相同的原因而受到影響)。做一個等價的整數循環並計算你的浮點數; 'for(int i = 0; i <100; i ++){double x = 0.1 * i; sum + = x * x; }' –

+0

@JonathanDursi,如果你把它寫成答案,我會接受它。 – Richard

+0

好的,謝謝,我已經在下面做了。 –

回答

6

從評論:

不,OpenMP的不會爲你同樣的理由這樣做如在this answer中給出的關於整數算術的OpenMP循環的問題;編譯器很難推斷浮點數 - 尤其是編譯器在進入循環之前需要知道循環的tripcount,而循環中的浮點運算使得這一般非常困難,即使有一些簡單的情況那就沒問題了(比如循環0.5到10.0)。因爲相同的原因,即使是這種形式的循環的純序列優化/矢量化也會受到影響。最好的辦法是做一個等價的整數循環並根據整數索引計算你的float值;

for (int i=0; i<100; i++) { 
    double x=0.1*i; 
    sum += x*x; 
} 
0

更一般地說,你需要去閱讀What Every Computer Scientist Should Know About Floating-Point Arithmetic。 您要添加0.1和期待準確的結果,這一事實表明,你已經沒有讀過:-)

+0

我已閱讀它。我希望沒有任何關於我的問題,這意味着我期待確切的結果。我不是。當然,在問題中顯示的代碼只是一個MWE代碼,對於更復雜的代碼而言,不需要確切的結果。 – Richard

+1

@Richard,實際上有一些關於你的問題,這意味着你(間接地通過你告訴編譯器)期待一種確切的結果。 OpenMP並行循環僅適用於如果可以準確計算循環跳閘次數。 「0.1」是一個無限長度的二進制小數,因此在給定不同的FPU條件下,行程計數可能會得到不同的計算結果。 –

+0

夠公平的,@HristoIliev。最終,我可能會最終對當前版本的答案進行投票,因爲我不覺得它真的試圖回答這個問題。但是,它可以作爲評論。我提到這個以防萬一你有想法來回答這個問題。 – Richard

0

OpenMP的標準定義的 「for」 循環只爲整數,指針和迭代器類型,而不是爲浮點類型:

http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf#page=62

2.7.1循環結構

#pragma omp for [clause[ [,] clause] ... ] new-line 
    for-loops 

具體而言,所有相關的for-loops必須具有規範的循環形式 (請參見第2節。 6第53頁)。

2.6規範的環形狀

環路具有典型循環形式,如果它符合以下幾點:

for (init-expr; test-expr; incr-expr) structured-block 

init-expr下列之一:

var = lb 
integer-type var = lb 
random-access-iterator-type var = lb 
pointer-type var = lb 

...

incr-expr以下之一:

++var 
var++ 
-- var 
var -- 
var += incr 
var -= incr 
var = var + incr 
var = incr + var 
var = var - incr 

var下列之一:

  • 有符號或無符號的整數類型的變量。
  • 對於C++,一個隨機訪問迭代器類型的變量。
  • 對於C,一個指針類型的變量。

規範形式允許所有相關的循環迭代次數,以執行最外層循環

因此,對於非經典類型的編譯器無法計算迭代次數之前計算。