CUDA 内核"Only a single pack parameter is allowed"解决方法?

CUDA kernel "Only a single pack parameter is allowed" workaround?

本文关键字:allowed is 解决 方法 parameter pack 内核 Only single CUDA      更新时间:2023-10-16

关于可变参数全局函数模板的 CUDA 7 标准规定"只允许单个包参数"。 有没有一个优雅的解决方法? 我希望能够执行以下操作:

template<int... vals>
void RecursiveFunct() {
}
template<int... vals, typename T, typename... Args>
void RecursiveFunct(T t, Args... args) {
  t.template call<vals...>();
  RecursiveFunct<vals...>(args...);
}

我想我可以在传递它们之前将我的整数包包装成一些东西,但是是否可以以对此代码的调用者透明的方式执行此操作?

不确定是否了解您的确切限制,但是...我想std::integer_sequence和调用call()的包装函数可以帮助您。

下面是一个玩具,但可编译的示例,显示了我的意思。

struct foo
 {
   template <int ... vals>
   void call () const
    { std::cout << "- call " << sizeof...(vals) << std::endl; }
 };
template <typename IS>
void RecursiveFunct (IS const &)
 { }
template <typename T, int ... vals>
void wrapCall (T const & t, std::integer_sequence<int, vals...> const &)
 { t.template call<vals...>(); }

template<typename IS,  typename T, typename ... Args>
void RecursiveFunct (IS const & is, T t, Args... args)
 {
   wrapCall(t, is);
   RecursiveFunct(is, args...);
 }
int main ()
 {
   // print 5 times "- call 4"
   RecursiveFunct(std::integer_sequence<int, 2, 3, 5, 7>{},
                  foo{}, foo{}, foo{}, foo{}, foo{});
 }

考虑到std::integer_sequence是 C++14 功能,因此前面的代码(至少(需要一个 C++14 编译器。

但是,如果您需要使用 C++11,创建一个std::integer_sequence替代品是微不足道的。

通过示例

template <typename T, T ... ts>
struct myIntegerSequence
 { };

--编辑--

OP问

这可以在不创建integer_sequence实例的情况下工作吗?

在正常的 C++14 中,是的。与库达一起工作吗?我不知道。

我已经获得了使用wrapCall结构和func()静态方法更改wrapCall()函数的方法。这是因为我使用了不能与 func 一起使用的部分专用化。

福林是玩具的例子

#include <utility>
#include <iostream>
struct foo
 {
   template <int ... vals>
   void call () const
    { std::cout << "- call " << sizeof...(vals) << std::endl; }
 };
template <typename>
void RecursiveFunct ()
 { }
template <typename>
struct wrapCall;
template <int ... vals>
struct wrapCall<std::integer_sequence<int, vals...>>
 {
   template <typename T>
   static constexpr void func (T const & t)
    { t.template call<vals...>(); }
 };
template<typename IS,  typename T, typename ... Args>
void RecursiveFunct (T t, Args... args)
 {
   wrapCall<IS>::func(t);
   RecursiveFunct<IS>(args...);
 }
int main ()
 {
   // print 5 times "- call 4"
   RecursiveFunct<std::integer_sequence<int, 2, 3, 5, 7>>
                  (foo{}, foo{}, foo{}, foo{}, foo{});
 }

但是你确定这是一个std::integer_sequence的问题吗?