2014-09-29 63 views
3

所以我剛剛從一所學校項目中取得了成績,而且我的表現很好,但是由於我沒有打電話給ceil(...),因此分級考試得了5分。它是一個使用CUDA的並行計算課程,但問題與任何CUDA功能都沒有直接關係。Ceil和Integers的使用

這裏是「有問題的」路線:

dim3 dimGrid(n/dimBlock.x, n/dimBlock.y); 

他的要求是我應該做的:

dim3 dimGrid(ceil(n/dimBlock.x), ceil(n/dimBlock.y)); 

所以我的問題是,爲什麼我會被標記過如果n此和dimBlock。*是整數?他們的結果將在ceil甚至被調用並被截斷之前計算。因此,標誌這件事似乎很愚蠢。

以下示例似乎表明GCC在使用-O2時優化了呼叫。

隨着小區:

#include <stdio.h> 
#include <math.h> 

int main() 
{ 
     int m = 3, n = 5, o; 

     o = ceil(n/m); 
     printf("%d\n", o); 
     return 0; 
} 

沒有:

#include <stdio.h> 
#include <math.h> 

int main() 
{ 
     int m = 3, n = 5, o; 

     o = n/m; 
     printf("%d\n", o); 
     return 0; 
} 

雖然我知道它只有五點,我還是想知道爲什麼,如果我是完全錯誤的。

+0

也許他們不應該是整數? – Boann 2014-09-29 17:57:38

+3

如果你打算四捨五入,那麼你需要投到一個浮動,以避免整數除法或做一些像'(n + dimBlock.x - 1)/ dimBlock.x' – Mysticial 2014-09-29 17:58:01

+0

這就是事情,你不會打算整理,也不會期望是浮動的。 dimBlock *根據定義,在CUDA中總是一個整數值,'n'是矩陣每個維度的大小。有問題的特定代碼涉及索引處理,因此實際上可能會導致分段錯誤 – csnate 2014-09-29 17:59:16

回答

2

平地機可能意味着你需要使用分數n/d的天花板,這是完全正確的:這樣就會有足夠的塊來覆蓋n,最後一塊可能不完整。

這並不意味着適當的實現與C表達式ceil(n/d)。事實上,C /是一個整數除法,並且將丟棄小數部分,實際上取小數部分的底部。

您可以使用ceil((double)n/(double)d)代替。

但我最喜歡的方式是沒有轉換爲雙打:(n+d-1)/d

+0

所以事實證明是這樣的。然而,我的代碼是正確的,所有測試在運行時都通過了,因此爲什麼我仍然以A結尾。基本上,如果n = 16(在我的代碼中從不發生),dimBlock.x和dimBlock.y = 1000 。1000/16 = 62.由於我使用dimBlock和dimGrid來啓動一個CUDA內核來執行矩陣乘法,所以我會丟失元素!仍然認爲自從我通過所有測試後,他可以給予我積分:p,但現在有意義。 – csnate 2014-09-30 14:25:36

+0

如果8個元素確實被排除在計算之外,那麼測試程序不應該得到A! ;-) – 2014-09-30 14:53:42

+0

他們雖然沒有。因爲在每個測試用例中n總是8,所以我從來沒有看到實際的問題。無論如何,我不知道爲什麼平地機改變了代碼。 – csnate 2014-09-30 15:04:57

-1

這裏,m = 3,n = 5 因此,n/m = 1.67(近似);因爲你將它賦值爲int類型,所以它會截斷它。即只存儲整數部分而不是小數部分,所以我們有o = 1。而如果你將使用ceil(n/m),則輸出將是2,然後將其分配給o。即o = 2。

+0

ceil將應用於n/m,這是兩個整數的一個整數,產生一個整數(實際爲floor(n/m))。 – 2014-09-30 14:00:51