繁体   English   中英

如何将 constexpr 值传递给采用 const 引用的 CUDA 设备端函数?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM