cuda GPU上的简单乘法给出错误

时间:2012-06-29 06:29:33

标签: cuda gpu thrust

我在GPU上执行以下操作

float decPart = valAtIndex - (int)valAtIndex;
int docID = decPart * numDocs;

其中valAtIdex类型为float,numDocs类型为float。对于我的情况,decPart为0.2,numDocs为10.但是,当我打印docID时,它打印为1(应该是2)。有人可以告诉我,我在哪里弄错了吗?

以下是完整的方法,如果有帮助

__global__ 
void finalNc(float* scSortedCounts, int* pos, int* maxCountEx, float numDocs, 
             int lengthStreamCompacted, int* finalNc, int actualLengthPos, 
             float* val, int* docIndex, int* acV ,int* ptwrite,int* diff,
             int* posIndex)
{ 
    int index = blockDim.x * blockIdx.x + threadIdx.x; 
    if(index < lengthStreamCompacted){ 
        float valAtIndex = scSortedCounts[index]; 
        float decPart = valAtIndex - (int)valAtIndex; 
        int docID = decPart * numDocs; 
        int actualCount = (int)valAtIndex; 
        int placeToWrite = maxCountEx[docID] + actualCount; 
        if( index == (lengthStreamCompacted -1 )){ 
            finalNc[placeToWrite] = actualLengthPos - pos[index]; 
        }else{ 
            finalNc[placeToWrite] = pos[index + 1] + pos[index]; 
        } 
    } 
}

1 个答案:

答案 0 :(得分:3)

对于您提到的情况,您看到的结果似乎是正确的,并且您的混淆的根源是计算中间结果的IEEE单精度表示(并且可能在打印或显示时舍入那些中间结果)。

对于您提供的示例,值0.2f不能完全表示为binary32值。两个可能的值是

3E4CCCCC (1.99999988079071044921875E-1) 

3E4CCCCD (2.0000000298023223876953125E-1)

如果第一个值是docID的实际值,那么您提到的中间计算应该生成1(这是您观察到的)。如果是第二个值,则结果为2.这是绝对预期的行为。

为了说明IEEE舍入模式的效果并帮助您放心,这里没有错误,请查看以下示例代码,该代码执行您要求的三个可能{{1}之一的计算{}}转换为float转换 - 纯粹截断,IEEE 754向负无穷大舍入,IEEE 754向无穷大舍入。我已经模拟了内核,并在1到10之间的一组随机浮点值上为每个案例运行它。您可以自己编译并运行它并验证纯截断(如在代码中)确实按预期工作,如以及符合IEEE标准的“向上舍入”和“向下舍入”转换的行为。

integer