[英]Microsoft Visual Studio finds errors with all of my CUDA device-side functions
[英]How do I pass constexpr values to CUDA device-side functions taking const references?
考虑以下代码:
template <typename T> __host__ __device__ int foo1(const T& x);
template <typename T> __host__ __device__ int foo2(T x);
这两个函数对应于传递“输入”参数而不是“输出”或“输入/输出”参数的两种常见方式。 第二个更简单,因为不涉及引用或地址; 但第一个确保不会复制更复杂的类型,因此通常首选。
我的问题是将constexpr
值传递给第一种函数( foo1
)。 如果它在主机端 - 没问题。 constexpr
变量有地址,编译器会照顾我并做一些合理的事情。
但是 - 设备端情况并非如此。 如果我们编译:
constexpr const int c { 123 };
__host__ int bar() { return foo1(c); }
__device__ int baz() { return foo1(c); }
第一个函数可以很好地编译,但第二个函数将无法编译(GodBolt)。
我不能同时提供这两个函数,因为编译器将无法在它们之间做出决定(经常/总是)。 而且我不想只传递值,因为我确实想避免大T
的副本; 或者因为我需要通过某种形式约束提供foo1()
。
那我能怎么办?
我还要提一下,我希望能够在设备端和主机端编写相同的代码。
您可以显式复制它,这样它就不会使用不存在的东西的地址:
return foo(int{cci});
所以取而代之的是新右值的地址。 不过,这确实使设备端的代码有所不同。
您还可以提供两个重载:
template <typename T> __host__ __device__ std::enable_if_t<!std::is_trivial_v<T>, int> foo(const T& x);
template <typename T> __host__ __device__ std::enable_if_t<std::is_trivial_v<T>, int> foo(T x);
所以副本是为你完成的,比如int
。
目前,我使用以下丑陋的解决方法:
__device__ int baz() { return foo1(decltype(c){c}); }
这与@Artyer 建议的类似,但也适用于模板化代码,因为您不需要指定c
的类型,例如:
template <typename T>
__device__ int quux() { return function_taking_const_ref(decltype(c){c}); }
它还具有不必知道c
类型的额外好处。 这当然也可以在主机端代码中完成。
但是 - 我真的不喜欢它! 读者不会理解为什么需要它,并且会有些困惑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.