5

スラストで使用されるブーストの 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_unchingVectorstaticまたはを作成して実験しconstましたが、オブザーバーのインスタンス化時に設定する必要があるため、これは正しくありません。

または、おそらくこれを行う最善の方法は、 unchingVector 内の別の引数として渡すことですがthrust::make_zip_iterator( thrust::make_tuple(...、これらの項目は状態変数のようにインデックス付けされるように感じます (これは私が望むものではありません)。ファンクターの宣言で (T t) が何を意味するのか、およびオペレーターを評価しているすべてのスレッドに unchangeingVector を同じオブジェクトとして渡す方法の説明が役立つ可能性があります。

正しいキーワード変数記述子を選択するだけの問題かもしれませんが、どの変数記述子を使用すればよいかわかりません。また、それを調べたり理解したりする方法もわかりません。

上記のコードで得られるエラーはerror: a nonstatic member reference must be relative to a specific object. ファンクターで m_unchingVector にアクセスしようとするとスローされます。


さらに調査した結果、このタスクを達成する正しい方法を特定したような気がしますが、まだ行き詰まっています。

ファンクターにコンストラクターを追加しました。

  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::minPerturbFunctor::operator () > " ) からホスト関数 ("thrust::detail::vector_base > ::operator []") を呼び出すことは許可されていません

エラー メッセージ /usr/local/cuda/bin/..//include/thrust/detail/function.h(104): エラー:デバイス関数からホスト関数 ("thrust::device_vector > ::device_vector") を呼び出しています("thrust::detail::device_function ::device_function") は許可されていません

私は何を間違っていますか?

4

1 に答える 1

4

推力ベクトルをファンクターに渡すことはできますが、ここに簡単に格納することはできません。ただし、このベクターから基になる生のポインターを格納できます。

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] 
    }
};

これは、Robert Crovella からの提案です。

于 2014-08-29T21:36:59.940 に答える