2015-07-21 85 views
0

我與蘋果提供here與OpenCL的還原例如導致結果不準確

後解剖這幾天,我瞭解的基礎知識OpenCL的減少例如工作;我已經將它轉換爲在C++(Openframeworks)上可靠運行的版本,並在輸入集中找到最大的數字。

然而,這樣做,有幾個問題已經出現如下:

  • 爲什麼使用多遍?我能夠減少的最多的是兩個;後者通過只佔用非常少的元素,因此非常不適合openCL進程(即,堅持一次通過然後處理cpu上的結果會不會更好?)

  • 當我將'count'元素數設置爲非常高的數字(24M以上)並將類型設置爲float4時,我得到的結果不準確(或完全錯誤)。爲什麼是這樣?

  • 在OpenCL內核

    ,任何人都可以解釋什麼正在這裏進行:

while (i < n){ 
     int a = LOAD_GLOBAL_I1(input, i); 
     int b = LOAD_GLOBAL_I1(input, i + group_size); 
     int s = LOAD_LOCAL_I1(shared, local_id); 
     STORE_LOCAL_I1(shared, local_id, (a + b + s)); 
     i += local_stride; 
} 

,而不是正在這裏做了什麼?

#define ACCUM_LOCAL_I1(s, i, j) \ 
{ \ 
    int x = ((__local int*)(s))[(size_t)(i)]; \ 
    int y = ((__local int*)(s))[(size_t)(j)]; \ 
    ((__local int*)(s))[(size_t)(i)] = (x + y); \ 
} 

謝謝! 小號

回答

1

要回答第2個問題:

why are multiple passes used? 

減少數以百萬計的元素到幾千可以並行完成以幾乎100%的設備利用率。但最後一步相當棘手。因此,蘋果公司並沒有把所有東西都保持在一個空閒狀態,而是讓多個線程閒置,而不是一次一個地減少;然後使工作項目適應新的減少問題,最後完成它。對於OpenCL,Ii是一個非常具體的優化,但它可能不適用於C++。

當我設置元素的「伯爵」號,以一個非常高的數字(24M 及以上)和類型爲float4變量,我得到不正確(或完全錯誤的) 結果。爲什麼是這樣?

float32的精度是2^23的餘數。高於24M = 1.43 x 2^24(以浮點形式表示)的值在+/-(2^24/2^23)/ 2〜1的範圍內有誤差。

這意味着,如果您:

float A=24000000; 
float B= A + 1; //~1 error here 

操作員錯誤在數據範圍內,因此......如果您在循環中重複該操作,則會出現大錯誤!

這不會發生在64位CPU中,因爲32位浮點運算使用內部48位精度,因此避免了這些錯誤。然而,如果你得到的浮動接近2^48,他們也會發生。但這不是正常「計數」整數的典型情況。

+0

嘿,謝謝你的回覆。我理解第一個;我仍然想知道爲什麼後者(小得多)的減少不僅僅是在CPU上運行。由於不準確的問題 - 是的,我也這麼認爲(發現鏈接由下面的答案建議),但是當我使用int4而不是float4測試縮減時,不準確性仍然存在。是否有類似的int4錯誤範圍? –

+0

有沒有innacuracies與「整數」,所以檢查你的代碼。整數運算總是精確的。 – DarkZeros

+0

這就是我的想法,整數不能不準確! Aaand,我沒有編輯過上面鏈接的蘋果例子的代碼,所以我認爲它沒問題。然而,當這些元素是int4或float4時,當超過23個(ish)個m元素運行時,它會停止準確運行。從進一步測試來看,完全相同的事情發生在一個int2的數量超過約45m的數字上,而對於普通的舊int數據則超過了91m。我知道這些數字非常高(!),所以也許並不那麼重要,但我對這是什麼造成了興趣。 –