2012-02-14 197 views
0

爲什麼在使用CUDA時,如果我執行一個大小爲1百萬的FFT,每次都會有不同的結果?同一數據上的FFT與CUDA每次都會給出不同的結果?

我的硬件有費米架構。

+0

這很有趣。你能發佈一些代碼來告訴我們你在做什麼嗎? – 2012-02-14 19:56:06

+2

很可能是因爲你每次都在做某種微妙的變化。向我們展示一個展示此問題的最小示例。 – Bart 2012-02-14 20:00:31

+0

除了發佈一些代碼,你需要更精確地描述「微妙不同」。 – 2012-02-14 20:07:02

回答

4

這可能有一個簡單的答案。 CUDA程序經常使用float變量類型,因爲它可能比double快得多。評估操作的順序可以顯着影響浮點計算的最終值;這不是CUDA的獨特之處,但是您可能會注意到這些影響特別尖銳,因爲它是一個大規模並行的範例(並行性帶有非確定性,至少在執行像全局縮減時)。

編輯:只是要清楚,它是一個必要(雖然不足)的條件,即CUDA不保證相同的內核將在多次執行中以相同的順序執行。如果CUDA確實保證了這一點,那麼算術運算的執行順序就不可能因運行而不同,因此,對於相同的浮點運算不會有不同的值。

這是一個簡單的C程序,演示了上述說明。試試代碼

#include <stdio.h> 

int main() 
{ 
    float a = 100.0f, b = 0.00001f, c = 0.00001f; 

    printf("a + b + c = %f\n", a + b + c); 
    printf("b + c + a = %f\n", b + c + a); 
    printf("a + b + c == b + c + a ? %d\n", (a + b + c) == (b + c + a)); 

    return 0; 
} 

在Linux上,看看你得到了什麼(我正在使用64位RHEL 6和gcc版本4.4.4-13)。我的輸出如下:

[[email protected] directory]# gcc add.c -o add 
[[email protected] directory]# ./add 
a + b + c = 100.000015 
b + c + a = 100.000023 
a + b + c == b + c + a ? 0 

編輯:請注意,雖然此程序可能意味着潛在的問題是,浮點加法是不可交換的,它實際上是浮點加法是非的情況下關聯(因爲C從左向右評估加法運算,所以第一次加法按照(a + b)+ c執行,第二次按照(b + c)+ a執行)。非關聯性的原因是浮點表示只能表示有限數量的有限數字(以2爲底,但基本10系統的討論基本上是等價的)。例如,如果只能表示三位有效數字,則可以得到(100 + 0.5)+0.5 = 100 + 0.5 = 100,而100 +(0.5 + 0.5)= 100 + 1 = 101。在第一種情況下,結果100 + 0.5必須被截斷(或可能被舍入),因爲不可能僅用三位有效數字來表示中間值100.5。

這種現象有許多重要的含義;例如,您將通過按大小(指數)的升序添加數字來得到更準確的答案。真正的收穫是,除非計算按照相同的順序執行,否則不應期望結果相同,這可能很難保證在真實的GPU上使用CUDA。

+1

這將如何解釋從運行到運行在相同輸入數據上的變化,其他要求硬件隨機地重新排序運行的執行?根據我的經驗,雖然執行順序不能事先確定,但硬件不會隨機化相同代碼的執行順序。 – talonmies 2012-02-14 21:09:08

+1

@talonmies我的印象並不是CUDA保證您將從運行到運行獲得相同的執行順序。雖然它可能不會(有意)隨機化執行,但可能會受到某種干擾或某種干擾。如果CUDA確實提供了這樣的保證,那麼我會同意這個答案是不正確的,並將刪除它。 – Patrick87 2012-02-14 21:21:42

+2

可能每次發佈第一個發佈的塊到不同的多處理器,並且如果跨多處理器的塊數量不均勻,那麼執行順序可能會在運行之間略有不同。如果涉及到原子,並且內存地址在不同運行中有所不同,則可能會更多地改變執行順序。 BTW @ Patrick87,爲了讓您對浮點執行方差的解釋真正正確,您可能想指出所有這一切的真正原因是「浮點算術是非關聯性的」。 – harrism 2012-02-15 00:17:13

相關問題