(int)-1的CUDA内核printf使用%d说明符给出了错误的输出

时间:2013-03-04 09:44:56

标签: cuda printf format-specifiers

在C中告诉我的电脑时

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

我确实期望,并且通常也得到'-1'响应。然而,在我的特斯拉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,如果是的话,你能告诉我为什么吗?非常感谢,马库斯。

2 个答案:

答案 0 :(得分:5)

如果您查看“CUDA C编程指南”的appendix B.20.1 "Format Specifiers",您会发现z中的%zd修饰符不受支持。您必须转换为unsigned long并使用%lu作为格式说明符:

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

答案 1 :(得分:2)

基本问题似乎是%zd格式说明符没有得到设备printf的尊重(我不确定,不管它是否受支持)。

编辑:

CUDA 5中printf的文档说明了这一点:

  

对于标准printf(),格式说明符采用以下形式:   %[标志] [宽度] [精度] [大小]类型

     

支持以下字段(请参阅广泛提供的文档   有关所有行为的完整描述):

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

请注意,CUDA的printf()将接受标志,宽度,   精度,大小和类型,无论它们是否整体形成有效   格式说明符。换句话说,“%hd”将被接受并且printf   将在相应的位置期望一个双精度变量   在参数列表中。

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

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

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