我正在 odeint 和推力之上构建一个分析工具。该工具解决了大量的初始条件问题。我在 odeint 和推力教程/演示之后取得了成功。到目前为止,我一直在使用的系统只有不到 5 个状态变量,但现在我需要扩展系统以能够处理更多。
正如教程中提到的,有一个小问题,thrust 的元组最多只能有 10 个项目。这个问题可以通过使用嵌套的 zip_iterators 来解决。
从其中一个教程的底部附近引用:
“Thrust 元组的最大元数为 10 是一个小问题。但这只是一个小问题,因为我们可以创建一个包含 zip 迭代器的 zip 迭代器。因此,顶级 zip 迭代器包含一个用于状态的 zip 迭代器,一个普通迭代器用于参数,一个 zip 迭代器用于导数。”
我已经实现了这个解决方案,它可以工作,但不幸的是速度大大降低。对于同一个系统(一个双变量系统,同时求解 8192 个初始条件),最初的、简单但不可扩展为超过 5 个变量的解决方案只需要一秒钟多一点的时间:
real 0m1.244s
user 0m0.798s
sys 0m0.356s
而更复杂但可扩展的嵌套解决方案需要大约 2000 倍的时间!
real 4m3.613s
user 2m15.124s
sys 1m47.363s
这两个程序之间的唯一区别是
在仿函数的内部
operator()
,我指的是状态变量和导数,以及在仿函数的构造函数中,特别是
for_each
在我创建 zip_iterators 和元组的命令中。
下面我为每个程序摘录了这些部分的摘录。我希望我在这里做错了什么,因为这种速度损失是毁灭性的!任何帮助将非常感激。
“简单”代码的摘录(非嵌套迭代器)
//////////////////////////////////////////////////////////
//// Inside ICFunctor's operator()
// getting the state variable
value_type X = thrust::get< 0 >( t );
// setting the derivative
thrust::get< 2 >( t ) = 0.5*A - 1.5*X;
//////////////////////////////////////////////////////////
//// the for_each statement that creates the zip_iterator
thrust::for_each(
//// START INDICES
thrust::make_zip_iterator( thrust::make_tuple(
// State-variables
boost::begin( x ) + 0*m_N,
boost::begin( x ) + 1*m_N,
// Derivatives
boost::begin( dxdt ) + 0*m_N,
boost::begin( dxdt ) + 1*m_N)) ,
//// END INDICES
thrust::make_zip_iterator( thrust::make_tuple(
// State-variables
boost::begin( x ) + 1*m_N,
boost::begin( x ) + 2*m_N,
// Derivatives
boost::begin( dxdt ) + 1*m_N,
boost::begin( dxdt ) + 2*m_N)) ,
ICFunctor() );
“EXTENSIBLE”代码(嵌套迭代器)的摘录
//////////////////////////////////////////////////////////
//// Inside ICFunctor's operator()
// getting the state variable
const int STATE_VARIABLES = 0; // defined as a global constant
value_type X = thrust::get<0>(thrust::get<STATE_VARIABLES>( t ));
// setting the derivative
const int DERIVATIVES = 1; // defined as a global constant
thrust::get<0>(thrust::get<DERIVATIVES>( t )) = 0.5*A - 1.5*X;
//////////////////////////////////////////////////////////
//// the for_each statement that creates the zip_iterator
thrust::for_each(
//// START INDICES
thrust::make_zip_iterator( thrust::make_tuple(
// State variables
thrust::make_zip_iterator( thrust::make_tuple(
boost::begin( x ) + 0*m_N,
boost::begin( x ) + 1*m_N)),
// Derivatives
thrust::make_zip_iterator( thrust::make_tuple(
boost::begin( dxdt ) + 0*m_N,
boost::begin( dxdt ) + 1*m_N))
)),
//// END INDICES
thrust::make_zip_iterator( thrust::make_tuple(
// State variables
thrust::make_zip_iterator( thrust::make_tuple(
boost::begin( x ) + 1*m_N,
boost::begin( x ) + 2*m_N)),
// Derivatives
thrust::make_zip_iterator( thrust::make_tuple(
boost::begin( dxdt ) + 1*m_N,
boost::begin( dxdt ) + 2*m_N))
)),
ICFunctor() );