【问题标题】:CUDA: Why is it not possible to define static global member functions?CUDA:为什么不能定义静态全局成员函数?
【发布时间】:2013-09-04 07:14:49
【问题描述】:

使用 nvcc (CUDA 5.0) 编译下面的代码时,会出现错误“内存限定符的非法组合”,因为在一个类中显然不可能有全局内核。

class A
{
public:
    __global__ static void kernel();
};

__global__ void A::kernel()
{}

我在处理非静态成员的时候可以理解这个限制,但是为什么内核声明为静态时仍然会出现错误?此类成员的调用与在命名空间中声明函数时调用函数没有什么不同(在这种情况下为A)。

A::kernel <<< 1, 1 >>> ();

我想知道为什么这还没有实施吗?

编辑:根据答案和 cmets 中的回答,我对我的问题还不够清楚。我的问题不是为什么会出现错误。显然,这是因为它尚未实施。我的问题是为什么它没有被实施。到目前为止,我还没有想到阻止此功能实施的原因。我意识到我可能忘记了一个会使事情复杂化的特殊情况,因此提出了这个问题。

我认为这是一个合理的功能的原因是:

  • 静态函数没有this 指针 因此,即使在主机上的对象上调用内核,访问其数据也不会发生冲突,因为首先无法访问此数据(来自什么对象的数据??)。
  • 您可能会争辩说,如果该类具有与之关联的静态数据,并且存在于主机上,则原则上应该可以从静态内核访问。但是,也不支持静态数据,因此也不会发生冲突。
  • 在主机上的对象上调用静态内核(A a; a.staticKernel&lt;&lt;&lt;...,...&gt;&gt;&gt;();) 完全等同于在没有对象的情况下调用它 (A::staticKernel&lt;&lt;&lt;...,...&gt;&gt;&gt;();),就像我们在常规 C++ 中习惯的那样。

我错过了什么?

【问题讨论】:

  • 你的目标是拥有一个具有_ 全局 _函数的类吗?
  • 所以这个问题的真正目的是争论为什么 CUDA 对象模型是这样的?这不是Stack Overflow 的问题。投票结束主要基于意见。
  • 我想向 NVidia 提交功能请求,因为我觉得不支持这很奇怪。在我这样做之前,我想确保没有明显的理由表明它就是这样。显然没有,显然这是对我投反对票的理由。它与意见或辩论无关。
  • 我们这里没有人设计过 CUDA 对象模型。因此,我们没有人能说出为什么它不受支持,因此任何答案充其量只是推测性的。如果我猜测,我会说这是因为它破坏了编译模型- __global__ 函数同时在 一个主机对象和一个设备对象中编译。 CUDA 类和结构只能在一个内存空间中实例化。这似乎排除了在结构和类中包含 __constant__ 或 __global__ 对象
  • @talonmies:我无法提前知道我的问题没有明显的答案,所以我无法预见猜测。如果你问我,答案/cmets 中的反对票和负面语气是非常不必要的。至于您的猜测:当您在其中声明静态函数时,不会向类/结构(在内存中)添加任何内容。声明只是为函数添加范围,类似于命名空间。我会联系 NVidia 看看他们要说什么。

标签: c++ static cuda global member


【解决方案1】:

幸运的是,在提出这个问题大约 4 年后,clang 4.0 can compile the CUDA language。考虑这个例子:

class A
{
public:
    __global__ static void kernel();
};

__device__ void A::kernel()
{}

int main()
{
    A::kernel <<< 1, 1 >>> ();
};

当我尝试用 clang 4.0 编译它时,我收到以下错误:

test.cu:7:1: error: kernel function 'kernel' must be a free function or static member function
__global__ void A::kernel()
^
/usr/local/cuda/include/host_defines.h:191:9: note: expanded from macro '__global__'
        __location__(global)
        ^
/usr/local/cuda/include/host_defines.h:88:9: note: expanded from macro '__location__'
        __annotate__(a)
        ^
/usr/local/cuda/include/host_defines.h:86:9: note: expanded from macro '__annotate__'
        __attribute__((a))
        ^
test.cu:7:20: error: __host__ function 'kernel' cannot overload __global__ function 'kernel'
__global__ void A::kernel()
                   ^
test.cu:4:28: note: previous declaration is here
    __global__ static void kernel();
                           ^
2 errors generated.

为了解决这些错误,我将内核定义内联到类声明中:

class A
{
public:
    __global__ static void kernel()
    {
        // implementation would go here
    }
};

然后clang 4.0编译成功,可以执行,没有任何错误。所以这显然不是 CUDA 语言 的限制,而是它事实上的标准编译器。顺便说一句,nvcc 有许多类似的不合理的限制,而 clang 没有。

【讨论】:

  • @talonmies 编程指南的E. C/C++ Language Support 部分只是nvcc 支持或不支持的(部分)规范。它与 CUDA 语言规范无关,遗憾的是它不存在。 B. C Language Extensions 部分很接近,但它与 nvcc 细节和 CUDA 运行时 API 混合在一起。
  • 目前(CUDA 10.2),如果内核被模板化,这仍然不起作用,例如template&lt;typename T&gt; __global__ static void kernel(T something){}。在没有 inline 限定符的情况下获取warning: inline qualifier ignored for "__global__" function,然后在函数声明的同一行获取error: illegal combination of memory qualifiers
  • 可以确认CUDA 11.1在nvcc中仍然存在这个缺陷。同样的错误信息和一切。现在必须想出一个全新的设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 2011-01-18
  • 2014-11-16
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
相关资源
最近更新 更多