2011/07/10

『もったいない』を考えてみた。② ■■■

先回の続きです。ただし、今回取り上げる内容は、いろいろと問題がありますのでご了承ください。

メモリの視点から見ると・・・・

使う予定のないデータをメモリ上に保存しておくのは、非常にもったいないことです。そこで、膨大な配列数を持つ配列を最低限の配列数にまとめ、使い回す方法を試してみました。

使い回す方法① 要素のシフト

下図のように配列の要素をシフトさせて空いた場所に新たな要素を追加する方法。
hei
※上記はArray[8]を示し、数値が配列番号、英字が要素を示す。また、I、Jはそれぞれ新たな要素を示す。
コードで記載すると以下の様になります。
double Array[8];
bool newrecord; //更新の有無

if(newrecord){  //更新があれば
   for(int i=0;i<7;i++) Array[7-i] =Array[6-i];
} 
問題点
この方法は、ループ処理がなされるためCUP【CPU】に負荷が掛かります。その為、あまり良い方法とは言えません。

使い回す方法② ポイントのシフト

ポイント(代入先)のシフトをする方法を考えるために、脳内処理として配列の頭と最後をくっ付けてドーナッツ状にします。下図を参照(上記と同じ配列を使用) そして、一番古い要素のところに新しい要素を追加します。最後に、新しく代入した要素と一番古い要素との間を切り離せば脳内処理完了です。上記と同じ要素の並びが出来上がります。
maru
この方法を用いればループ処理を行わずに使い回しが可能になります。
コード表記すると以下のようになります。
double Array[8];
bool newrecord; //更新の有無
int zeroindex=0; //仮想配列番号
if(newrecord){  //更新があれば
  int index;   
  zeroindex++;
  index=7-zeroindex%8
  Arraay[index]=newdate//新しい要素の代入
} 
問題点
MQL4では試していませんが、MQL5だと55621回処理した後で【stack overflow】エラーを吐き出して強制終了場合(毎回ではありませんが・・・)があります。無限ループ対策に引っかかるのが原因でしょうか?そのため回避対策を施してやる必要が出てきます。

まとめ

今回の内容は、ほとんどの方にとってどうでもいいことだと思いますが、自分用の資料として記載しました。

7 件のコメント:

  1. こりゃ凄い…早速パク・・・試してみよう
    もしかしてなんですが、問題点の欄のCUPってアレですよね?

    返信削除
  2. MT5も「無限ループ対策」もわかってませんが、コンパイラの気持ちになると、if文の中の変数確保でスタックを使って、ifを抜けた時にスタック開放漏れというMT5のバグだったのかもしれませんね~

    もう、根拠もへったくれも無い仮設ですけど。。。

    返信削除
  3. 天狗さんへ
    ホントですねorz 変更しておきました。いい加減な性格なついつい出てしまいます。^_^;

    あははさんへ
    私が試したのは、クラス内で関数化していますので、その辺りが原因かもしれませんが・・・、とりあえずこの問題は、一時棚上げして、全体をまとめ上げる作業に進もうと思っています。

    返信削除
  4. そうですね~

    1つの問題でとまってたら物事進まないですもんね!

    返信削除
  5. 通りすがりです。

    見たところ、関数内のインデックスは0~7の範囲のようですし、問題なさげですね。

    スタックオバーフローが発生したのは、この関数の問題ではなく、この関数の呼ばれた所が既に深い場所で呼ばれた可能性はないですか?

    ・エラーが起こった時のコールツリー等を確認して意図する 場所で呼ばれているか確認。
    ・コールツリーの最深部での関数のスタック使用料を
     概算する。
    ・概算したスタックサイズと、現在の設定している、スタックメモリサイズ を比較して、必要なら増やす。
    ・エラーが55621回で落ちるか?或いは変化するか、
     或いは落ちないかを試し、妥当なサイズを探る。
     (1Mとかにしてみる)

    こんな感じでしょうか。

    返信削除
  6. ごめんなさい。
    MT5の話ですね。コールツリーなんてデバック機能無いかもしれませんね。

    返信削除
  7. >コールツリーなんてデバック機能
    あるのかな? わかりません。。orz
    ただ、今回の記事のエラーは、MT5のバージョンアップで解消されたみたいです。。たぶん^^;
    正直、スタックオーバーフローが出た時点で、お手上げでした。。^^;
    教えて頂いてありがとうございます。

    返信削除