2014-09-29 35 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