Templates 在CUDA中使用Lambda函数和模板函数

Templates 在CUDA中使用Lambda函数和模板函数,templates,lambda,cuda,Templates,Lambda,Cuda,我试图使用Cuda实现一个通用类,用于诸如Reduce或Scan之类的常用算法,提供一些预处理,例如算法内部的简单映射。此映射操作在实际的reduce/scan算法之前执行。为了实现这一点,我希望使用lambda函数。下面是我试图实现这一点的方法 template<typename T> void __device__ ReduceOperationPerThread(T * d_in, T * d_out, unsigned int size) { //Actual Red

我试图使用Cuda实现一个通用类,用于诸如Reduce或Scan之类的常用算法,提供一些预处理,例如算法内部的简单映射。此映射操作在实际的reduce/scan算法之前执行。为了实现这一点,我希望使用lambda函数。下面是我试图实现这一点的方法

template<typename T> void __device__ ReduceOperationPerThread(T * d_in, T * d_out, unsigned int size)
{
    //Actual Reduce Algorithm Comes here 
}

template<typename T, typename LAMBDA> 
__global__ void ReduceWithPreprocessing(T * d_in, T * d_out, unsigned int size, LAMBDA lam)
{
    lam();

    ReduceOperationPerThread(d_in, d_out, size);
}
但在这种情况下,无法预定义模板参数
LAMBDA
的可能值

template void ReduceWPreprocessing<int>(int * d_in, int * d_out, unsigned int size, ??? lambda);
模板无效缩减WPReprocessing(int*d_in,int*d_out,unsigned int size,λ);

有没有其他方法可以将lambda函数用于此类应用程序?

[将评论汇总到社区wiki答案中,以将此问题从未回答的队列中清除]

在问题发布的时候,没有办法按照问题的要求去做,因为CUDA缺少一个可以捕获lambda表达式的占位符机制


然而,CUDA(从2017年第1季度发布的第8版开始)现在有了一个类似于多态函数包装器的
std::function
。这将允许您为lambda表达式定义一个泛型类型,该类型可以在实例化过程中用作模板参数,然后捕获作为参数传递的lambda,并以泛型方式调用它。

我认为模型lambda表达式的用法在普通C++11中甚至都不有效。每个lambda表达式都会生成一个类型,因此您需要在模板实例化时定义
lambda
的类型,或者使用受支持的占位符机制,如
std::function
,以便将“匿名”lambda表达式作为模板参数。CUDA在设备代码中没有
std::function
支持,因此我不知道如何实现。有没有办法找到lambda函数的类型?没有。每个lambda表达式都会生成一个新的、唯一的、未命名的类型。唯一保证的属性是转换为函数指针。在CUDA中,我不这么认为。在C++11中,您有
decltype
,它可以捕获lambda表达式的类型。在CUDA中,这是不受支持的,因为CUDA 8有一种方法可以为设备代码声明lambda类型,如
std::function
。它是
nvstd::function
#include
中提供的。示例:
typedef-nvstd::function-unaryFunction
// Reduce.h
template<typename T, typename LAMBDA>
void Reduce(T * d_in, T * d_out, unsigned int size, LAMBDA lam);
// Reduce.cu
template<typename T> void __device__ ReduceOperationPerThread(T * d_in, T * d_out, unsigned int size)
{
    //Actual Reduce Algorithm Comes here 
}

template<typename T, typename LAMBDA> 
__global__ void ReduceWithPreprocessing(T * d_in, T * d_out, unsigned int size, LAMBDA lam)
{
    lam();

    ReduceOperationPerThread(d_in, d_out, size);
}

template<typename T, typename LAMBDA>
void ReduceWPreprocessing(T * d_in, T * d_out, unsigned int size, LAMBDA lam)
{
    // preparing block sizes, grid sizes
    // and additional logic for invoking the kernel goes here
    // with the Kernel invocation as following

    ReduceWithPreprocessing<T><<<gridSize, blockSize>>>(d_in, d_out, size, lam)
}
// At the end of the Reduce.cu file
// Writing functions with possible template values 
// For A normal Reduce function

template void Reduce<double>(double * d_in, double * d_out, unsigned int size);
template void Reduce<float>(float * d_in, float* d_out, unsigned int size);
template void Reduce<int>(int * d_in, int * d_out, unsigned int size);
template void ReduceWPreprocessing<int>(int * d_in, int * d_out, unsigned int size, ??? lambda);