使用模板特征类型时,NVIDIA NVCC会更改编译时常量

时间:2012-05-03 09:04:52

标签: c++ templates compiler-construction cuda

我在使用C ++模板时看到了NVIDIA NVCC(CUDA 4.0和4.1测试)的奇怪行为。 我把它简化为一个演示行为的简单例子。

这已经处于错误报告的状态。但是,我把它挂钩在这里,因为这个站点是一个越来越可靠的错误和修复源。所以,我保持这个页面更新。

代码:

#include"stdio.h"

#define PETE_DEVICE __device__

template<class T, int N>  class ILattice;
template<class T>         class IScalar;
template<class T, int IL> struct AddILattice {};

template<class T>
PETE_DEVICE
void printType() {
  printf("%s\n",__PRETTY_FUNCTION__);
}

template<class T> class IScalar {
  T F;
};

template<class T, int N> class ILattice {
  T F[N];
};

template<class T, int N>
struct AddILattice<IScalar<T> , N> {
  typedef ILattice< T , N > Type_t;
};

#define IL 16

__global__ void kernel()
{
  printf("IL=%d\n",IL);  // Here IL==16

  typedef typename AddILattice<IScalar<float> ,IL>::Type_t Tnew;

  // This still works fine. Output:
  // void printType() [with T = ILattice<float, 16>]
  //
  printType<Tnew>();

  // Now problems begin: Output:
  // T=4 Tnew=0 IL=64
  // Here IL should still be 16
  // sizeof(Tnew) should be 16*sizeof(float)
  //
  printf("T=%d Tnew=%d IL=%d\n",sizeof(IScalar<float> ),sizeof(Tnew),IL);   
}   

int main()
{
    dim3  blocksPerGrid( 1 , 1 , 1 );
    dim3  threadsPerBlock( 1 , 1, 1);
    kernel<<< blocksPerGrid , threadsPerBlock , 48*1024 >>>( );

    cudaDeviceSynchronize();
    cudaError_t kernel_call = cudaGetLastError();
    printf("call: %s\n",cudaGetErrorString(kernel_call));

}

编译器将IL从16更改为64的任何想法

1 个答案:

答案 0 :(得分:2)

也许是因为你使用了错误的printf转换。 %d表示输出int,但sizeof不返回int,而是返回size_t。另外使用size_t长度修饰符(并使其无符号),即将%d替换为%zu

printf无法知道(由于var-args列表)实际传递了什么类型,因此不会发生类型转换,它只能知道格式字符串的类型。所以你必须在那里传递正确的参数。当您在size_t与int具有相同大小的系统上时,您的代码可以正常工作(例如,许多32位系统)。但是你不能依赖这个事实,使用正确的转换会帮助你。

(所以它不是编译器改变你的常量,但你输错了)