1

我正在 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

这两个程序之间的唯一区别是

  1. 在仿函数的内部operator(),我指的是状态变量和导数,以及

  2. 在仿函数的构造函数中,特别是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() );
4

0 回答 0