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);
}