2014-08-29 2 views
3

Я расширяю пример изучения параметров из odint boost, используемого с тягой, и я не знаю, как пройти вектор значений для конструктора наблюдателя, так что эти значения могут быть доступны (только для чтения) из функтора наблюдателя.Как передать вектор конструктору осеин-наблюдателя с осевым движением, чтобы его можно было прочитать внутри функтора

Следующий код для наблюдателя.

//// 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 static или const, но это не правильно, так как он должен быть установлен на конкретизации наблюдателя.

В качестве альтернативы, возможно, лучший способ сделать это - передать 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 
    } 
    }; 

предупреждение: вызов хоста функции ("тяга :: подробно :: vector_base> :: Оператор []") из хостаустройства функции ("minimum_perturbation_observer :: minPerturbFunctor :: оператора()> «) не допускается

ERROR MESSAGE /usr/local/cuda/bin/..//include/thrust/detail/function.h(104): ошибка: вызов хоста функцию ("thrust :: device_vector> :: device_vector") от devic e Функция («тяга :: деталь :: устройство_функция :: устройство_функции») не разрешена

Что я делаю неправильно?

+1

Я думаю, что я нашел пример, который делает то, что мне нужно, на https://github.com/boostorg/odeint/blob/master/examples/thrust/phase_oscillator_ensemble.cu. Я буду смотреть дальше и вернуться сюда. – weemattisnot

+2

Вы можете передать инициализирующий параметр вашему функтору. Этот параметр может быть указателем, возвращаемым '.data()' для 'thrust :: device_vector'.Этот указатель затем может быть использован в функторе с использованием обычных методов указателей c для доступа к любому элементу вектора устройства внутри функтора. –

+2

описан общий подход к передаче инициализирующего значения функтору (через его конструктор) [http://stackoverflow.com/questions/17468745/thrust-filter-by-key-value/17471046#17471046). в вашем случае у вас будет элемент данных вашей структуры, такой как 'T * a; ', и передайте инициализирующий элемент как' m_unchangingVector.data() ', грубо говоря. –

ответ

2

Вы можете передать вектор тяги к функтору, но вы не можете легко его сохранить здесь. Но вы можете сохранить базовый необработанный указатель с этим вектором:

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

Это в значительной степени предложение Роберта Кровеллы.

Смежные вопросы