(前頁)<<      >>(次頁)          (Up)

5章 要素モデルの計算速度調整
      〜 インスタンスの生成(new)の影響 〜


 
(3)ローカル変数のnew

 クラスや変数の new (インスタンスの生成) は 時間がかかります。 特に大きなメモリー領域を new する時に(PCの搭載メモリーにも依存しますが)顕著です。
 
 プログラム中の 変数の new の影響を調べるため Calculate()メソッド内、及び DataFusion( ) メソッド内で ローカル変数に3次元配列を生成します。

 それ以外の処理は何もしません。

// 変数の new の影響を調べる為のコーディング
        protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            double[ , , ]  X = new double[100,100,5];
            X[0,1,2] = 1.0;
            return 0;
        }
 
        protected override long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            double[ , , ]  X = new double[100,100,5];
            X[4,3,2] = -1.0;
            return 0;
        }



 比較のため、 ローカル変数の代わりに メンバー変数に 三次元配列を使用します。

// 変数の new の影響を調べる為のコーディング

        double[ , , ]  m_dX = new double[100,100,5];  // <-- ワーク領域として使用する

        protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            //double[ , , ]  X = new double[100,100,5];  <-- このローカル変数を使用しない
            m_dX[0,1,2] = 1.0;
            return 0;
        }
 
        protected override long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            //double[ , , ]  X = new double[100,100,5];  <-- このローカル変数を使用しない
            m_dX[4,3,2] = -1.0;
            return 0;
        }

      m_dX は ワーク領域なので、演算中データクラス内には入れません。



 要素モデルは1個のみ存在し 他の要素モデルとは接続しません。
  
     
 
 上記2つのモデルで 1ヶ月の計算を行ない、その計算時間を測定してみました。
 尚 使用したPCは DELL社製 LATITUDE D420 
       CPU    Intel Genuine Duo U2500  1.20GHz
           RAM   1.00 GB
           HDD    55GB
          OS   microsoft Windows VISTA

      CommonMP.cfg の ログ出力設定は LOG_LEVEL = TRIAL_RUN 

 測定した結果を下に示します。

 変数 

 計算時間(秒) 

 ローカル変数使用の場合 

 177秒 

 メンバー変数使用の場合 

  <2秒 



 ローカル変数を使用した場合には、毎回変数を new (インスタンスを生成)し、使用後、破棄されます。
 一方、メンバー変数をローカル変数の代わりに使用する場合には、インスタンスの生成は1回のみです。
 従って、大きな領域をワーク領域として使用する場合には、その都度 new するのではなく、メンバー変数として最初に領域を確保しておき、その領域を使用すると全体の計算速度が向上します。(大きな領域を使用する場合は特に) 

(ガーベージコレクション)
C++の世界では 確保した領域は プログラムの中で明示的に 開放する必要があります。 ( new  / delete )
一方、C#やJAVAはガーベージコレクションという機能があり、不要となった領域は自動的にVMが開放してくれます。

 



 明示的に new しなくても new が行われることがあります。
 例えば、 CommonMP固有のクラス:HySTime の演算子を使用した場合です。
 例えば、 HySime A; HySTime B; HySTime C; がある時
     A = B + C;
 の様に演算子を用いると 内部で new が動作してしまいます。
 演算子を使用せずに 以下の様にコーディングすると、 new は使用されません。
     A.SetTime(B.GetTime() + C.GetTime());
 CommonMP 独自クラスで、 +、−、==、!= 等の演算子が使用されている場合には、 内部で new が行われていると思い、それを使用しないで同様の操作を行う別なメソッドを使用するほうが速度は早くなります。(演算中に使用するのは HySTime クラス が多いと思いますが。)
 
 
 下のコーディングで HySTime の演算子の影響を調べてみます。

// 演算子 の影響を調べる為のコーディング

        double[ , , ]  m_dX = new double[100,100,5];  // <-- ワーク領域として使用する
        HySTime m_csWorkTime = new HySTime(0); // <-- ワーク領域として使用する

        protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            for (long i = 0; i < 1000; i++)
            {
                m_csWorkTime = this.m_csSimTime + this.m_csDltTime;  // <-- 演算子を使用する場合
                //m_csWorkTime.SetTime(this.m_csSimTime.GetTime() + this.m_csDltTime.GetTime());  // <-- 演算子を使用しない場合
            }
            return 0;
        }

                       繰り返し計算ループのネストがあると 知らず知らずのうちに 計算の回数が多くなります。

 測定結果(同じモデル、同じPC上で確認)

 変数 

 計算時間(秒) 

 演算子を使用する場合    

 87秒 

 演算子を使用しない場合

  7秒 


 演算子を使用しない時がずっと計算速度は早くなります
 



(前頁)<<      >>(次頁) 

初版:2013/06/27 |