1

私は odeint と推力の上に分析ツールを構築しています。このツールは、多数の初期条件の問題を解決します。私は odeint と throws のチュートリアル / デモに従って成功しました。これまで私が扱ってきたシステムには 5 つ未満の状態変数しかありませんでしたが、より多くの状態変数を処理できるようにシステムを拡張する必要があります。

チュートリアルで述べたように、thrust のタプルは最大 10 個のアイテムしか持てないという小さな問題があります。この問題は、ネストされた zip_iterators を使用することで解決できます。

チュートリアルの1つの下部近くから引用:

「Thrust のタプルの最大アリティが 10 であるという小さな問題があります。しかし、zip イテレータを詰め込んだ zip イテレータを作成できるので、これは小さな問題にすぎません。そのため、最上位の zip イテレータには、状態用の 1 つの zip イテレータと 1 つの通常のイテレータが含まれています。パラメータには 1 つの zip イテレータ、派生物には 1 つの zip イテレータを使用します。"

このソリューションを実装しましたが、機能しますが、残念ながら速度が大幅に低下します。同じシステム (8192 個の初期条件を同時に解く 2 変数システム) の場合、元のシンプルだが 5 つ以上の変数に拡張できないソリューションは 1 秒強で実行されます。

real   0m1.244s
user   0m0.798s
sys    0m0.356s

一方、より複雑ではあるが拡張可能なネストされたソリューションには、最大 2000 倍の時間がかかります!

real    4m3.613s
user    2m15.124s
sys     1m47.363s

2 つのプログラムの唯一の違いは、

  1. functor の内部でoperator()、状態変数と導関数を参照し、

  2. ファンクターのコンストラクター、特にfor_eachコマンド内で、zip_iterators とタプルを作成します。

以下に、各プログラムについて、これらのセクションからの抜粋を示します。この種の速度低下は壊滅的なので、ここで何か間違ったことをしているといいのですが! どんな助けでも大歓迎です。

「SIMPLE」コードの抜粋 (ネストされていないイテレータ)

//////////////////////////////////////////////////////////
//// 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