我目前正在尝试理解下面的boost库示例,它使用具有推力的并行处理。
struct lorenz_system
{
struct lorenz_functor
{
template< class T >
__host__ __device__
void operator()( T t ) const
{
// unpack the parameter we want to vary and the Lorenz variables
value_type R = thrust::get< 3 >( t );
value_type x = thrust::get< 0 >( t );
value_type y = thrust::get< 1 >( t );
value_type z = thrust::get< 2 >( t );
thrust::get< 4 >( t ) = sigma * ( y - x );
thrust::get< 5 >( t ) = R * x - y - x * z;
thrust::get< 6 >( t ) = -b * z + x * y ;
}
};
lorenz_system( size_t N , const state_type &beta )
: m_N( N ) , m_beta( beta ) { }
template< class State , class Deriv >
void operator()( const State &x , Deriv &dxdt , value_type t ) const
{
thrust::for_each(
thrust::make_zip_iterator( thrust::make_tuple(
boost::begin( x ) ,
boost::begin( x ) + m_N ,
boost::begin( x ) + 2 * m_N ,
m_beta.begin() ,
boost::begin( dxdt ) ,
boost::begin( dxdt ) + m_N ,
boost::begin( dxdt ) + 2 * m_N ) ) ,
thrust::make_zip_iterator( thrust::make_tuple(
boost::begin( x ) + m_N ,
boost::begin( x ) + 2 * m_N ,
boost::begin( x ) + 3 * m_N ,
m_beta.begin() ,
boost::begin( dxdt ) + m_N ,
boost::begin( dxdt ) + 2 * m_N ,
boost::begin( dxdt ) + 3 * m_N ) ) ,
lorenz_functor() );
}
size_t m_N;
const state_type &m_beta;
};
此示例可在以下位置进行全面探讨:
https://github.com/headmyshoulder/odeint-v2/blob/master/examples/thrust/lorenz_parameters.cu
我对C++还是个新手,但是已经学过C的入门课程,也学过Java的编程。所以,我对这些概念大部分都很熟悉。
我的问题是在第二个操作符overwrite中。据我所知,thrust::for_each()
有两个迭代器,一个在它开始的地方,一个在它结束的地方,还有一个函子。当thrust::make_zip_iterator()
被调用时,它创建了一个zip_iterator
。据我所知,zip_iterator
为整个bundle创建了一个移动引用。为此,它要求长度都是相同的。
但是m_beta.begin()
出现在两个迭代器中,没有任何变化,这是否意味着m_beta
只包含一个值(如果你在GitHub上查看完整的代码,结果是0),因此zip_iterator
失败了?
我运行了代码,它工作得很好,所以我对zip_iterator
s,或者特别是thrust s还有什么不理解的呢?
1条答案
按热度按时间iswrvxsc1#
在这种情况下(可能在所有并行情况下),Thrust只需要“end”迭代器来计算到“开始”迭代器的距离。
也就是说,只使用第一个“结束”迭代器,忽略所有其他迭代器。**这是一个实现细节,因此不应该依赖它。**有人可能会说,至少在调试构建中,应该计算所有迭代器对的差异,如果任何一对迭代器产生与其他迭代器不同的东西,应该抛出异常。
简而言之,问题中的代码可以工作(目前),但应该进行修复,以避免依赖于实现细节,并让读者更清楚地了解
m_beta
是迭代的,而不仅仅是使用的第一个元素,初学者可能会第一眼就想到这一点。这是否意味着
m_beta
只包含一个值[...]?如果它以这种方式工作,则意味着
m_beta
具有零个元素,因为结束迭代器是最后一个元素的后一个元素。