在CUDA内核模板函数中,如何测试类型?

In CUDA kernel template function, how to test types?

我有一个像这样的 CUDA 内核模板函数:

    template <typename scalar_t, typename accscalar_t, typename index_type, int indexing_kind>
    __global__ void lstm_cell_forward(
                TensorInfo<scalar_t, index_type> input,
                TensorInfo<scalar_t, index_type> hidden,
                TensorInfo<scalar_t, index_type> bias1,
                TensorInfo<scalar_t, index_type> bias2,
                TensorInfo<scalar_t, index_type> _cx,
                TensorInfo<scalar_t, index_type> _hy,
                TensorInfo<scalar_t, index_type> _cy,
                TensorInfo<scalar_t, index_type> workspace,
                index_type hsz,
                index_type totalElements) {
...
 scalar_t iig = DEVICE_LINEAR_GET(input, offset+0*hsz);
      scalar_t ifg = DEVICE_LINEAR_GET(input, offset+1*hsz);
      scalar_t icg = DEVICE_LINEAR_GET(input, offset+2*hsz);
      scalar_t iog = DEVICE_LINEAR_GET(input, offset+3*hsz);
...
}

我想在这个内核函数中添加 printf() 以仅当 scalar_t 为 float 时打印 iig, ifg, icg, iog 的值。我尝试使用 typeid(float) == typeid(iig) 来完成此操作,但 CUDA 代码显然不支持“typeinfo.h”。

如果我只省略 if 语句

   printf("iig = %f, ifg = %f, icg = %f, iog = %f\n",
    iig, ifg, icg, iog);

然后继续编译,编译器将尝试编译模板参数类型的不同组合,即使是 c10:Half 类型,pytorch 定义的数据类型。这将引发错误。

所以我的问题是如何写scalar_t的比较来检查它是否等于float

我采纳了@Robert Crovella 回答的建议,结果报错:

liwei.dai@854380cd7bb1:~/tests/cuda-debug-case/cuda/tmp$ !b
bash bi_make_and_run.sh 
test.cu:7:20: error: no template named 'is_same_v' in namespace 'cuda::std'; did you mean 'is_same'?
  if (::cuda::std::is_same_v<T, float>) printf("val is a float: %f\n", val);
      ~~~~~~~~~~~~~^~~~~~~~~
                   is_same
/opt/sw_home/local/cuda/include/cuda/std/std/detail/libcxx/include/type_traits:877:65: note: 'is_same' declared here
template <class _Tp, class _Up> struct _LIBCUDACXX_TEMPLATE_VIS is_same           : public false_type {};
                                                                ^
test.cu:7:39: error: expected unqualified-id
  if (::cuda::std::is_same_v<T, float>) printf("val is a float: %f\n", val);

但如果我尝试使用 cuda::std::is_same<T, float>::value,它就成功了。我查看了type_traits文件中的源代码,他们只是使用is_same_v来调用is_same::value。但是不知道为什么。

So my question is how to write the comparison of scalar_t to check if it equals to float?

我相信您可以为此使用 libcu++(类型特征)的特性:

$ cat t1868.cu
#include <cuda/std/type_traits>
#include <cstdio>
template <typename T>
__global__ void k(T val){
  if (::cuda::std::is_same_v<T, float>) printf("val is a float: %f\n", val);
  else printf("val is not a float\n");
}

int main(){

  float f = 1.2345;
  k<<<1,1>>>(f);
  double d = 1.2345;
  k<<<1,1>>>(d);
  cudaDeviceSynchronize();
}

$ nvcc -std=c++14 t1868.cu -o t1868
$ cuda-memcheck ./t1868
========= CUDA-MEMCHECK
val is a float: 1.234500
val is not a float
========= ERROR SUMMARY: 0 errors
$