CUDA C++ 中的友元函数
friend function in CUDA C++
我正在处理 class A 和 B 在命名空间 test0 中声明的问题,以及 class A 在命名空间 test1 中声明的友元函数 f。函数 f 接收一个 class B 对象的引用作为参数。这是一个简化的例子。
namespace test0 {
class B;
}
namespace test1 {
void f(test0::B& b);
}
namespace test0 {
class A {
friend void test1::f(test0::B& b);
};
}
该代码适用于 g++。但是nvcc给出如下编译错误。
a.cu:11:22: error: ‘B’ has not been declared
friend void test1::f(test0::B& b);
^
a.cu:11:27: error: ‘void test1::f(int&)’ should have been declared inside ‘test1’
friend void test1::f(test0::B& b);
^
你能帮我找出问题所在吗?提前谢谢你。
了解 nvcc 不是编译器很重要,它是一个 编译器驱动程序 ,在这两种情况下,代码都是用 gcc 编译的,错误是gcc 生成错误。如果你把那个代码放在一个 .cc
扩展文件中并通过 nvcc 编译它,就不会有任何错误。
但是在编译 CUDA 代码时(在本例中为 .cu
文件),在您的代码和编译它的最终 g++ 阶段之间有一些中间处理阶段。在幕后,正在发生的事情是您的代码正在被 CUDA C++ 前端解析器转换为:
# 1
# 2
namespace test0 {
# 3
class B;
# 4
}
# 6
namespace test1 {
# 7
void f(test0::B & b);
# 8
}
# 10
namespace test0 {
# 11
class A {
# 12
friend void test1::f(B & b);
# 13
};
# 14
}
将其与原始 friend void test1::f(test0::B& b);
进行比较,您可以看到名称空间已被 cudafe++ pass 剥离。我不知道 为什么 它被删除了,但这是错误的来源。
如果您的应用程序确实存在问题,我建议您将此作为错误报告给 NVIDIA。
经过 NVIDIA 开发团队的审查,这似乎暴露了 gnu 编译器中的错误。 nvcc
工具链的前端处理确实创建了一个主机代码(传递给主机编译器),它删除了 b
类型的名称空间限定,但这应该是可以接受的,因为 B
已经在 test0
命名空间中声明。
这似乎对 gnu 社区有 already been reported。
作为支持数据点,Fedora 25 上的 clang++ 3.9.1 编译了@talonmies 给出的 中报告的代码,没有错误也没有警告。在我通过 Fedora25 上的 gnu 6.4.1 进行测试时,gnu 工具链仍然会抛出错误。我并不是声称这是一个证据点,只是建议 gnu 中的错误声明可能 可能是正确的。我不是语言专家。此外,我不想在这里就此展开争论;这不是这个问题或答案的目的。
NVIDIA 开发团队已对该问题进行审核,并希望在未来的 CUDA 版本中提供修复或解决方法。
同时,建议的源代码级解决方法是在 class A
中为 B
使用虚拟 typedef。即:
class A {
typedef B dummy_t;
friend void test1::f(dummy_t & b);
};
更新:
该问题应在 CUDA 10.1.105 (CUDA 10.1) 中解决
我正在处理 class A 和 B 在命名空间 test0 中声明的问题,以及 class A 在命名空间 test1 中声明的友元函数 f。函数 f 接收一个 class B 对象的引用作为参数。这是一个简化的例子。
namespace test0 {
class B;
}
namespace test1 {
void f(test0::B& b);
}
namespace test0 {
class A {
friend void test1::f(test0::B& b);
};
}
该代码适用于 g++。但是nvcc给出如下编译错误。
a.cu:11:22: error: ‘B’ has not been declared
friend void test1::f(test0::B& b);
^
a.cu:11:27: error: ‘void test1::f(int&)’ should have been declared inside ‘test1’
friend void test1::f(test0::B& b);
^
你能帮我找出问题所在吗?提前谢谢你。
了解 nvcc 不是编译器很重要,它是一个 编译器驱动程序 ,在这两种情况下,代码都是用 gcc 编译的,错误是gcc 生成错误。如果你把那个代码放在一个 .cc
扩展文件中并通过 nvcc 编译它,就不会有任何错误。
但是在编译 CUDA 代码时(在本例中为 .cu
文件),在您的代码和编译它的最终 g++ 阶段之间有一些中间处理阶段。在幕后,正在发生的事情是您的代码正在被 CUDA C++ 前端解析器转换为:
# 1
# 2
namespace test0 {
# 3
class B;
# 4
}
# 6
namespace test1 {
# 7
void f(test0::B & b);
# 8
}
# 10
namespace test0 {
# 11
class A {
# 12
friend void test1::f(B & b);
# 13
};
# 14
}
将其与原始 friend void test1::f(test0::B& b);
进行比较,您可以看到名称空间已被 cudafe++ pass 剥离。我不知道 为什么 它被删除了,但这是错误的来源。
如果您的应用程序确实存在问题,我建议您将此作为错误报告给 NVIDIA。
经过 NVIDIA 开发团队的审查,这似乎暴露了 gnu 编译器中的错误。 nvcc
工具链的前端处理确实创建了一个主机代码(传递给主机编译器),它删除了 b
类型的名称空间限定,但这应该是可以接受的,因为 B
已经在 test0
命名空间中声明。
这似乎对 gnu 社区有 already been reported。
作为支持数据点,Fedora 25 上的 clang++ 3.9.1 编译了@talonmies 给出的
NVIDIA 开发团队已对该问题进行审核,并希望在未来的 CUDA 版本中提供修复或解决方法。
同时,建议的源代码级解决方法是在 class A
中为 B
使用虚拟 typedef。即:
class A {
typedef B dummy_t;
friend void test1::f(dummy_t & b);
};
更新:
该问题应在 CUDA 10.1.105 (CUDA 10.1) 中解决