When using odeint with thrust, I am developing an observer that will generate a histogram of state-variables while solving many initial condition problems in parallel.
The initial conditions problems run in parallel, populating a device_vector with the data like this.
Trajectory 0, Variable 0, Histogram Bin 0;
Trajectory 0, Variable 0, Histogram Bin 1;
...
Trajectory 0, Variable 1, Histogram Bin 0;
Trajectory 0, Variable 1, Histogram Bin 1;
...
Trajectory 1, Variable 0, Histogram Bin 0;
Trajectory 1, Variable 0, Histogram Bin 1;
...
Or, put more concisely, the indexing of the array will be calculated according to:
trajectoryIndex*N_BINS*N_VARS +varIndex*N_BINS +binIndex
... and later, this vector will be reduced to one histogram for each variable.
The paradigm that I have seen used in odeint + thrust is to have the operator functor called using thrust's make_zip_iterator
and make_tuple
, thus:
thrust::for_each(
thrust::make_zip_iterator(
thrust::make_tuple(
boost::begin( x ) + 0*m_N,
boost::begin( x ) + 1*m_N
),
thrust::make_zip_iterator(
thrust::make_tuple(
boost::begin( x ) + 1*m_N,
boost::begin( x ) + 2*m_N
),
observer_functor()
);
which works great when the arguments to the functor are all of the same length. But in my case the histogram-data device_vector that is to be populated as described above is of a different size, and needs to be indexed differently than the other arguments given to the functor (e.g. the state-variables).
Having looked around a bit, I think that the best way to do this is to pass a thrust::counting_iterator that provides the functor with the trajectory-index needed to populate the histogram matrix. I then would also (obviously) have to somehow provide a pointer to the histogram matrix so that it can be populated. Perhaps the best solution for providing the observer_functor with the pointer to the histogram vector would be to provide it as an argument to the constructor of the observer (similar to the solution of another question I posted here).
All of this raised some confusion about how the arrays in the make_zip_iterator
/ make_tuple
paradigm above work when the passed arguments indicate vectors of different length.
QUESTIONS:
Is my proposed use of
thrust::counting_iterator
and passing a pointer to the output array via the constructor of the functor object the recommended approach?More generally, how does the
make_zip_iterator
/make_tuple
paradigm above work when the passed arguments indicate vectors of different length?