Templates 当声明和定义之间的const不匹配时,代码可能会调用它。@njuffa:我认为这些答案是相关的:顺便说一句:float*上的\uuuu restrict\uuuu关键字也会出现同样的问题。它只适用于声明也有它。注意,问题是指C,而CUDA是C++的变体。虽

Templates 当声明和定义之间的const不匹配时,代码可能会调用它。@njuffa:我认为这些答案是相关的:顺便说一句:float*上的\uuuu restrict\uuuu关键字也会出现同样的问题。它只适用于声明也有它。注意,问题是指C,而CUDA是C++的变体。虽,templates,cuda,Templates,Cuda,当声明和定义之间的const不匹配时,代码可能会调用它。@njuffa:我认为这些答案是相关的:顺便说一句:float*上的\uuuu restrict\uuuu关键字也会出现同样的问题。它只适用于声明也有它。注意,问题是指C,而CUDA是C++的变体。虽然C和C++是紧密相关的,但它们之间存在着许多差异,我的意图是剥离不必要类型限定符的接口,以清除它。code>const只是一个例子,但问题也出现在\uuuu restrict\uuuu和volatile中。但是这些类型限定符应该只与实现相关,


当声明和定义之间的
const
不匹配时,代码可能会调用它。@njuffa:我认为这些答案是相关的:顺便说一句:
float*
上的
\uuuu restrict\uuuu
关键字也会出现同样的问题。它只适用于声明也有它。注意,问题是指C,而CUDA是C++的变体。虽然C和C++是紧密相关的,但它们之间存在着许多差异,我的意图是剥离不必要类型限定符的接口,以清除它。code>const只是一个例子,但问题也出现在
\uuuu restrict\uuuu
volatile
中。但是这些类型限定符应该只与实现相关,用于编译器错误检查和优化。它不应该对接口(即声明)有任何意义,至少在C语言中是这样的:@mxmlnkn为什么您认为
const
限定符是肮脏的标志?:)同样,正如我所说的,答案可以通过检查大会找到。
#include <cstdio>
#include <cuda_runtime_api.h>

/* this declaration would normally be in a header, but it doesn't matter */
template<class T_PREC> __global__ void testKernel( T_PREC );

template<class T_PREC> __global__ void testKernel( T_PREC const x )
{
    printf( "%f", x );
}

int main()
{
    printf("calling kernel...");
    testKernel<<<1,1>>>( 3.0f );
    cudaDeviceSynchronize();
    printf("OK\n");
    return 0;
}
nvcc simple.cu && ./a.out
calling kernel...
[Inferior 1 (process 27899) exited with code 01]
template<class T_PREC> void testKernel( T_PREC );

template<class T_PREC> void testKernel( T_PREC const x )
{
    printf( "%f", x );
}

int main()
{
    printf("calling kernel...");
    testKernel( 3.0f );
    cudaDeviceSynchronize();
    printf("OK\n");
    return 0;
}
__global__ void testKernel( float );

__global__ void testKernel( float const x )
{
    printf( "%f", x );
}
//template<class T_PREC> void testKernel( T_PREC );
template<class T_PREC> __global__ void testKernel( T_PREC const );
nvcc sameTypeQualifier/main.cu -o same.o
    [no warning output whatsoever]

nvcc diffTypeQualifier/main.cu -o diff.o
    diffTypeQualifier/main.cu: In instantiation of ‘void __wrapper__device_stub_testKernel(T_PREC* const&) [with T_PREC = float]’:
    diffTypeQualifier/main.cu:8:45:   required from ‘void testKernel(T_PREC*) [with T_PREC = float]’
    diffTypeQualifier/main.cu:15:67:   required from here
    diffTypeQualifier/main.cu:7:86: warning: unused parameter ‘x’ [-Wunused-parameter]
             template<class T_PREC> __global__ void testKernel( T_PREC * const x )
                                                                                          ^
 diff <(nm -C same.o | sed 's/^[0-9a-f]*//') <(nm -C diff.o | sed 's/^[0-9a-f]*//')
    389a390
    >  t void __wrapper__device_stub_testKernel<float>(float*&)
    419c420
    <  t __sti____cudaRegisterAll_39_tmpxft_000050c8_00000000_9_main_cpp1_ii_main()
    ---
    >  t __sti____cudaRegisterAll_39_tmpxft_0000511c_00000000_9_main_cpp1_ii_main()
nvcc --keep [...]
colordiff -r c/ nc/

[...]
diff c/main.cu.cpp.ii nc/main.cu.cpp.ii
32767c32767
< template< class T_PREC> static void __wrapper__device_stub_testKernel(const T_PREC &); template< class T_PREC> void testKernel(const T_PREC);
---
> template< class T_PREC> static void __wrapper__device_stub_testKernel(T_PREC &); template< class T_PREC> void testKernel(T_PREC);
[...]
diff c/main.cudafe1.cpp nc/main.cudafe1.cpp
70764c70764
< template< class T_PREC> static void __wrapper__device_stub_testKernel(const T_PREC &); template< class T_PREC> void testKernel(const T_PREC);
---
> template< class T_PREC> static void __wrapper__device_stub_testKernel(T_PREC &); template< class T_PREC> void testKernel(T_PREC);
[...]
#include<cstdio>

void f( float const & x ) { printf( "float const &\n", x ); }
void f( float       & x ) { printf( "float &\n", x ); }

int main( void )
{
    f( 3.0 );
    float x = 3.0;
    f( x );
}
float const &
float &
grep -C20 '__wrapper__device_stub_testKernel' nc/main.cu.cpp.ii
# 4 "main.cu"
template< class T_PREC> static void __wrapper__device_stub_testKernel(T_PREC &);
template< class T_PREC> void testKernel(T_PREC);
# 5 "main.cu"
template< class T_PREC> static void __wrapper__device_stub_testKernel(const T_PREC &x)
{
    exit(1);
}
# 5 "main.cu"
template< class T_PREC> void testKernel(const T_PREC x)
{
    # 6 "main.cu"
    __wrapper__device_stub_testKernel<T_PREC>(x);
    # 8 "main.cu"
    return;
}
# 10 "main.cu"
int main()
# 11 "main.cu"
{
    # 12 "main.cu"
    printf("calling kernel...");
    # 13 "main.cu"
    (cudaConfigureCall(1, 1)) ? (void)0 : (testKernel)((3.0F));
    # 14 "main.cu"
    cudaDeviceSynchronize();
    # 15 "main.cu"
    printf("OK\n");
    # 16 "main.cu"
    return 0;
    # 17 "main.cu"
}
[...]
static void __device_stub__Z10testKernelIfEvT_(float __par0)
{
    if (cudaSetupArgument((void *)(char *)&__par0, sizeof(__par0), (size_t)0UL) != cudaSuccess) 
        return;
    {
        volatile static char *__f __attribute__((unused));
        __f = ((char *)( (void ( *)(float))testKernel<float> ) );
        (void)cudaLaunch( ((char *)((void ( *)(float))testKernel<float> )) );
    };
}
[...]
template<> void __wrapper__device_stub_testKernel<float>( float &__cuda_0)
{
    __device_stub__Z10testKernelIfEvT_( __cuda_0);
}