【问题标题】:C++ struct functor as function template parameterC++ struct functor 作为函数模板参数
【发布时间】:2016-03-05 22:36:33
【问题描述】:

我很困惑,我知道 CUDA 和其他库允许使用模板结构作为函子。因此,我为神经网络类设计了其中的一些:

struct sigmoid
{
     sigmoid()=default;                                                           
     __device__ float operator()(const float x) const                                                                                     
    {                                                                                                                                     
         float exp_val = __expf(-x);                                                                                                       
         float denom = __fadd_rz(1.f,exp_val);                                                                                             
         return __fdividef(1.f,denom);                                                
    }                                                                     
};       

当我将它用于 CUDA 内核时,它的用法有点简单:

activate<sigmoid><<num_blocks_x,block_threads_x>>>(sigmoid(),output_ptr);

为:

template <typename F>                                                                                                                     
__global__ void activate(F const& func, float * input)                                                                                    
{                                                                                                                                         
   int x = blockIdx.x * blockDim.x + threadIdx.x;                                                                                        
   input[x]  = func(input[x]);                                                                                                           
} 

但是我想将函数模板包裹调用CUDA内核的方法,然后转发给它:

template <class A>                                                                                                             
thrust::host_vector<float> propagate (                                                                                                
                                       A func,                                                                 
                                       thrust::device_vector<float> & input                                                          
                                     ) const; 

我已经将它实现到一个单独的头文件中,它包含在声明类的头文件的末尾。

class ann
{
...
};
#include ann_imp.hpp

还有 imp 标头:

template <class A> inline                                                                                                                   
__host__ thrust::host_vector<float> ann::propagate (                                                                                        
                                                       A func,                                                                            
                                                       thrust::device_vector<float> & input                                               
                                                    ) const                                                                                 
{
     activate<func><<<num_blocks_x,block_threads_x>>>(func(),output_ptr);
}  

然而,当我调用实际的 propagate 方法时,我遇到了麻烦:

net.propagate<sigmoid>( sigmoid(), in_vec1 );

生产:

error: function "sigmoid::operator()" cannot be called with the given argument list
            object type is: sigmoid

当我不使用 operator() 而只使用类型名时:

xor_net.propagate<sigmoid>( sigmoid, in_vec1 );

我明白了:

error: type name is not allowed

使用实际对象会产生相同的错误:

sigmoid func;
xor_net.propagate<sigmoid>( func, in_vec1 );

我尝试过使用 A const&amp; func 等参数,但无济于事。

如何传递一个 struct functor,然后将其转发给 CUDA 内核?

编辑 没有包装器,只需要调用激活函数:

activate<sigmoid><<<num_blocks_x,block_threads_x>>>(sigmoid(),output_ptr); 

【问题讨论】:

    标签: c++ templates struct cuda


    【解决方案1】:

    你有:

     __device__ float operator()(const float x) const ...
    

    函数需要float 类型的参数。您从ann::propagate 调用它为:

    activate<func><<<num_blocks_x,block_threads_x>>>(func(),output_ptr);
                                                     ^^^^^^
    

    我认为该行需要:

    activate<A><<<num_blocks_x,block_threads_x>>>(func,output_ptr);
           ^^^^                                   ^^^^^     
           Fix the type                           Use the object.
    

    【讨论】:

    • 这成功了!现在我更加困惑了。为什么我在调用propagate 时会出错,而在调用activate 时却没有????当我没有使用包装器时,我不得不调用它:activate&lt;sigmoid&gt;&lt;&lt;&lt;...,...&gt;&gt;&gt;( sigmoid(), ptr );
    • @Alex,如果没有看到完整的错误堆栈,我不知道如何回答。
    • @R Sahu 我进行了编辑。当我没有使用任何模板包装器,并且只(直接)调用activate 时,我所要做的就是调用sigmoid() 作为cuda 内核参数,并使用类型名。为什么包装器得到错误,而不是 cuda 内核调用?
    • @Alex,在直接调用activate 时,您使用sigmoid 作为模板参数并使用新构造的对象作为参数。当ann::propagate 被调用时,您使用的是相同的模式。当你进入ann::propagate 时,funcsigmoid 的一个实例(或者A,如果你愿意的话)。
    • @Alex,当然可以。在这种情况下,您可以 (a) 不将对象传递给 propagate 并使用 A() 在对 activate 的调用中构造一个新对象,或者 (b) 从传递的对象构造一个新对象并使用新的在对activate 的调用中带有A(func) 的对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    相关资源
    最近更新 更多