2013-03-04 35 views
1

输出错误时告诉我的电脑用C(INT)-1的CUDA内核的printf给人以%d符

printf("%d",(int)-1); 

我也想到,通常可以得到,同样,一个 '-1' 的回应。然而,在我的Tesla M2090 NVIDIA显卡从我的基于Ubuntu的Cuda的5.0这个无辜的演示程序

/** cheese.cu */ 
#include <iostream> 
#include <cuda.h> 
#include <cstdio> 

using namespace std; 

template<typename T> struct SpacePtr 
    { size_t size; T* ptr; }; 

__global__ void f(SpacePtr<int>* sp) 
{ 
    printf("This _is_ a 'minus one' or ain't it: %d\n",(int)-1); 
    // Note: All appears to work fine with %lu instead of %zd 
    // Still: How does the size value affect the -1? 
    printf("On DEV: Size: %zd, Minus One: %d\n",sp->size,(int)-1); 
} 

int main() 
{ 
    SpacePtr<int> data; data.ptr = 0; data.size = 168; 
    SpacePtr<int>* devPtr = 0; 
    cudaMalloc(&devPtr,1); 
    cudaMemcpy(devPtr,&data,sizeof(SpacePtr<int>),cudaMemcpyHostToDevice); 
    f<<<1,1,0,0>>>(devPtr); 
    cudaError_t err = cudaGetLastError(); 
    cout << "The last error code was " << err << " (" << 
    cudaGetErrorString(err) << ")" << endl; 
    cudaDeviceSynchronize(); 
} 

编译并通过

nvcc -arch=sm_20 cheese.cu && ./a.out 

称为谈过产生的输出:

The last error code was 0 (no error) 
This _is_ a 'minus one' or ain't it: -1 
On DEV: Size: 168, Minus One: 10005640 

最后一个数字实际上是某种随机数(两个子查询返回不同的结果),就好像内存分配有什么不对。 -1之前的(int)已经是试错了。原来的程序没有它。

这里是问题:有没有人看,为什么-1不写,如果是这样,请你告诉我,为什么?非常感谢,Markus。

+0

唯一可能的不确定的行为可能是内存分配。如果不。不要忘记重新编译代码然后执行。我猜:)对于'printf(“%d”,(int)-1)defiantly没有问题;' – 2013-03-04 09:51:08

+0

这是我自己的问题的更新:如果我使用“%lu”作为size_t和“ %d“为臭名昭着的”-1“。所以可能与设备出于某种原因需要C90风格%lu有关。仍然:在内核代码%zd和%d之外工作正常。我保持开放的问题,我仍然没有看到一个大小值错误的格式化程序如何破坏-1的格式。 – 2013-03-04 10:02:11

回答

4

如果您查看CUDA C编程指南的appendix B.16.1 "Format Specifiers",您会发现不支持%zd中的z修饰符。你将不得不转换为unsigned long并使用%lu作为格式说明:因为`SP-> size`的

printf("On DEV: Size: %lu, Minus One: %d\n",(unsigned long)(sp->size), (int)-1); 
+0

我想这就是打印文档所得到的结果,因此在你的文档中有一个过时的变化...你的回答恢复了我的信念,没有在CUDA中发现错误,从而保留了我对整个事物的信心!非常感谢! :-) – 2013-03-04 10:17:20

2

基本的问题似乎是设备printf不支持%zd格式说明符(我不确定,不管我的头顶是否支持)。

编辑:

在CUDA 5 printf的文档说这样的:

至于标准printf()的,格式说明采取的形式: %[标志] [宽度] [精度] [大小]类型

以下字段支持(见广泛使用的文档 对于所有行为的完整描述):

Flags: ‘#’ ‘ ‘ ‘0’ ‘+’ ‘-‘ 
Width: ‘*’ ‘0-9’ 
Precision: ‘0-9’ 
Size: ‘h’ ‘l’ ‘ll’ 
Type: ‘%cdiouxXpeEfgGaAs’ 

请注意,CUDA的printf()将接受标志,宽度,精度,尺寸和类型的任意组合,不管它们是否总体上形成有效的 格式说明符。换言之,“%hd”将被接受,并且printf 将在参数列表中的相应位置 期望双精度变量。

因此不支持%zd格式说明符size_t。像这样修改你的内核:

__global__ void f(SpacePtr<int>* sp) 
{ 
    const int minus_one = -1; 
    printf("This _is_ a 'minus one' or ain't it: %d\n", minus_one); 
    printf("On DEV: Size: %d, Minus One: %d\n",int(sp->size), minus_one); 
} 

工作正常。

还要注意你在你的主机代码有一个非常重大的失误,虽然这不会对你的榜样清单的行为没有任何影响。你只是分配和复制一个字节为dev_ptr这显然是不正确的。它应该是这个样子:

cudaMalloc((void **)&devPtr, sizeof(data)); 
cudaMemcpy(devPtr, &data, sizeof(data), cudaMemcpyHostToDevice); 

从主机数据的全部内容传送到设备。

+0

回答:也谢谢你。显然我应该更新我的文档。我使用Cuda 4.0手册。内存分配:Eeek。是。在我的主程序中,我从这个黑客入侵这个演示是正确的! ;-) – 2013-03-04 10:18:51