如何将矢量传递给基于推力的odeint观测器的构造函数,以便在函子中读取

How to pass a vector to the constructor of a thrust-based odeint observer, such that it can be read within the functor

本文关键字:构造函数 读取 观测器 odeint 于推力      更新时间:2023-10-16

我正在扩展与推力一起使用的boost的odeint的参数研究示例,我不知道如何将值的向量传递给观测器的构造函数,以便可以从观测器的函子中访问(只读)这些值。

以下是仅针对观察者的代码。

//// Observes the system, comparing the current state to 
//// values in unchangingVector
struct minimum_perturbation_observer { 
  struct minPerturbFunctor
  {
    template< class T >
    __host__ __device__
    void operator()( T t ) const
    {
    //// I would like to be able to read any member 
    //// of m_unchangingVector here.
    }
  };

  // CONSTRUCTOR
  minimum_perturbation_observer( size_t N, state_type unchangingVector, int len) : 
        m_N( N ),
        m_output( N ),
        m_unchangingVector( len ) // len is the correct length of unchangingVector
  {
    // all trials start with output = 0
    thrust::fill( m_output.begin() , m_output.end() , 0.0 );
    // copy unchangingVector to m_unchangingVector, the latter 
    // of which should be accessible from the functor operator() 
    // above.
    thrust::copy( unchangingVector.begin(), unchangingVector.end(),
                  m_unchangingVector.begin());
  }
  template< class State >
  void operator()(State x , value_type t )
  {
    thrust::for_each(
                 thrust::make_zip_iterator( thrust::make_tuple(
                                   boost::begin( x ) + 0*m_N,
                                   boost::begin( x ) + 1*m_N,
                                   boost::begin( m_output )
                                   )
                            ),
                 thrust::make_zip_iterator( thrust::make_tuple(
                                   boost::begin( x ) + 1*m_N,
                                   boost::begin( x ) + 2*m_N,
                                   boost::begin( m_output ) + m_N
                                       )
                            ) ,
                 minPerturbFunctor() );
  }
  // variables
  size_t m_N; // number of trials (i.e. number of initial conditions)
  state_type m_output;   // of length N_ICS
  state_type m_unchangingVector; // 
};

我已经尝试过制作m_unchangingVector staticconst,但这是不正确的,因为它需要在观测者实例化时进行设置。

或者,也许最好的方法是将unchangingVector作为thrust::make_zip_iterator( thrust::make_tuple(...中的另一个参数传递,但我觉得这些项会按照状态变量的方式进行索引(这不是我想要的)。一个可能有帮助的答案是解释(T T)在函子声明中的含义,以及如何将unchangingVector作为同一对象传递给每个正在计算运算符的线程。

我认为这可能只是选择正确的关键词变量描述符的问题,但我不知道该使用哪一个,也不知道如何查找/弄清楚。

对于上面的代码,我得到的错误是error: a nonstatic member reference must be relative to a specific object。当我试图访问函子中的m_unchangingVector时抛出。


经过进一步的探索,我觉得我已经找到了完成这项任务的正确方法,但我仍然停滞不前。

我已经为函子添加了一个构造函数。

  struct minPerturbFunctor
  {
    minPerturbFunctor( state_type unchangingVector, int len ) :
    f_unchangingVector( len ) 
    {
      // copy from argument to local vector (probably unnecessary, but
      // getting errors about calling host-functions from device/host 
      // so being paranoid about trying to make sure things are device-side
      thrust::copy( f_unchangingVector.begin(), 
                    f_unchangingVector.end(), 
                    unchangingVector.begin());
      f_len = len;      
    };
    template< class T >
    __host__ __device__
    void operator()( T t ) const
    {
        // I can now access f_len here (progress!)
        // But when I try to access any element via e.g., 
        // f_unchangingVector[0] I get the error below
    }
  };

警告:不允许从主机设备函数("minimum_perturbation_observer::minIntroductFunctor::operator()>"

错误消息/usr/local/cuda/bin///include/trust/detail/function.h(104):错误:不允许从设备函数("rust::detail::device_function::device_ffunction")调用主机功能

我做错了什么?

您可以将推力向量传递给函子,但不能轻松地将其存储在这里。但是您可以将底层的原始指针存储在这个向量中:

struct minPerturbFunctor
{
    state_type::value_type* m_ptr;
    size_t m_len;
    minPerturbFunctor( state_type const& x )
    : m_ptr( thrust::raw_pointer_cast(&x[0]) )
    , m_len( x.size() )
    { }
    template< class T >
    __host__ __device__
    void operator()( T t ) const
    {
        // now you can access m_ptr like m_ptr[i] 
    }
};

这几乎是罗伯特·克罗维拉的建议。