[英]C++11 alias templates in CUDA
基本问题是CUDA编译器是否支持别名模板 ?
我在使用gcc-4.8的Ubuntu上使用CUDA 7.5。 我的所有模板类都在头文件中定义,并在编译期间将#include
d转换为单个翻译单元。
我有一个简单的cuda_array
类,它围绕std::vector
提供了一个薄包装器。 它本质上是一个非常简单的版本thrust::host_vector
用组合的thrust::device_vector
。 它的声明是
template <typename T, const size_t N>
class cuda_array {
std::vector<T> host;
T *device;
public:
// lots of type aliases to meet container requirements
void push() { /* cudaMemcpy(...,H2D); */ }
void pull() { /* cudaMemcpy(...,D2H); */ }
// a few others that aren't relevant here
};
为了制作矩阵,我只是做了一个快速的模板别名。
template <typename T, const size_t M, const size_t N>
using cuda_matrix = cuda_array<T, M * N>;
我想将我的矩阵矢量乘法CUDA内核映射到重载operator*
,以确保类型安全和易于使用(它留给调用方以确保正确调用push
和pull
)。
template <typename T, const size_t rows, const size_t cols>
__global__ void matrix_vector_mul(T *A, T *b, T *result) {
__shared__ T shared_b[cols];
// rest of it
}
template <typename T, const size_t M, const size_t N>
__host__ cuda_array<T, M> operator*(cuda_matrix<T, M, N> &m, cuda_array<T, N> &v) {
cuda_array<T, M> result;
matrix_vector_mul<T, M, N><<<16, 32>>>(m.device_data(), v.device_data(), result.device_data());
return result;
}
然后在我的“ main.cpp”中
cuda_matrix<int,16,32> A;
cuda_array<int,32> b;
auto result = A * b;
最后一行抛出错误说
error: no operator "*" matches these operands
operand types are: cuda_matrix<int, 16UL, 32UL> * cuda_array<int, 32UL>
我追逐了所有通常想到的模板类型推导错误,但没有任何效果。 无奈cuda_matrix
,我将cuda_matrix
别名模板转换为模板类。
template <typename T, const size_t M, const size_t N>
class cuda_matrix : public cuda_array<T, M * N> {};
并且编译错误消失了! 因此,似乎CUDA尚不支持别名模板。 还是我做了无法解决的愚蠢的事情?
您必须记住:
第14.5.7节[临时别名] / p2:
当template-id指代别名模板的特殊化时,它等效于通过将其模板参数替换为别名模板的type-id中的模板参数而获得的关联类型。 [ 注意 :永远不会推导出别名模板名称。 — 尾注 ]
这意味着不对以下项进行扣除:
template <typename T, const size_t M, const size_t N>
__host__ cuda_array<T, M> operator*(cuda_matrix<T, M, N> &m, cuda_array<T, N> &v)
但对于:
template <typename T, const size_t M, const size_t N>
__host__ cuda_array<T, M> operator*(cuda_array<T, M * N> &m, cuda_array<T, N> &v)
// ~~~~~~~~~~~~~~~~~~~^
所以:
§14.8.2.5 [温度扣除类型] / p16:
如果在具有非类型模板参数的功能模板的声明中,如果在函数参数列表的子表达式中使用了非类型模板参数,则该表达式是如上所述的非推导上下文 。
M
在不可推论的上下文中,因此该operator*
不被视为可行的重载。
作为解决方法之一,您可以改为验证cuda_array
本身的推导值:
template <typename T, std::size_t MN, std::size_t N>
auto operator*(const cuda_array<T, MN>& m, const cuda_array<T, N>& v)
-> typename std::enable_if<(MN/N)*N==MN, cuda_array<T, MN/N>>::type;
或使用您已有的继承技巧; 那么M
和N
是cuda_matrix
单独的非类型模板参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.