雲雀は高く空を舞い このページをアンテナに追加 RSSフィード

「ひよこは高く空を舞い」について

2007-02-12

配列に対するメモリの割り当て  配列に対するメモリの割り当て - 雲雀は高く空を舞い を含むブックマーク はてなブックマーク -  配列に対するメモリの割り当て - 雲雀は高く空を舞い  配列に対するメモリの割り当て - 雲雀は高く空を舞い のブックマークコメント

配列ヘッダ

変数に配列を割り当てる場合、MATLAB も、 ヘッダと呼ばれるメモリの断片に (データタイプや次元など) 配列についての情報をストアします。たいていの配列に対して、ヘッダをストアするために必要なメモリは、 大きくはありません。 大きなデータセットを少数の大きな配列にストアすることは、多数の小さな配列にストアすることに比べ、必要な 配列ヘッダがより少ないため、利点は少なくなります。

構造体とセル配列.

構造体とセル配列に対して、MATLAB は、各配列に対するのみでなく、 構造体の各フィールド、セル配列の各セルに対してもヘッダを作成します。このため、構造体またはセル配列をストアするために必要なメモリ量は、データの保持量のみならず、作成される方法にも依存します。 

たとえば、 フィールド R, G, B を持つ、スカラ構造体配列 S1、大きさ 100×50 の各フィールドは、 構造体全体を記述するために、 1 つの配列ヘッダ、 3 つのフィールド配列のぞれぞれを記述する 1 つずつのヘッダが必要であり、データ構造全体に対して、合計 4 つの配列ヘッダを作成します。

S1.R(1:100,1:50)
S1.G(1:100,1:50)
S1.B(1:100,1:50)

他方、 各要素がスカラフィールド R, G, B である 100×50 構造体配列 S2 は、構造体全体を記述する1つの配列ヘッダと、 構造体の 5,000要素の各々に対して、フィールド毎に 1 つの配列ヘッダを必要とし、 データ構造全体に対して、15,001 の配列ヘッダを作成します。

S2(1:100,1:50).R
S2(1:100,1:50).G
S2(1:100,1:50).B

こうして、S1 と S2 は、同じ量のデータを含みますが、 S1 は、かなり少ないメモリスペースを使用します。 より少ないメモリが要求されるだけでなく、同様に、 S1 のフォーマットを使用することにより高速化されます。


関数引数

MATLAB は、関数呼び出しで渡される引数を同様に取り扱います。関数に 1 つの変数を渡す場合、実際には、変数が表すデータに対するポインタも渡しています。入力データが呼び出される関数により修正されない限り、呼び出す関数内の変数と、呼び出された関数内の変数は、メモリ内の同じ位置を指します。呼び出された関数が入力データの値を修正する場合、 MATLAB は、メモリ内の新しい位置に、オリジナルの配列のコピーを作成します。 そのコピーを修正された値を使用して更新し、呼び出された関数内の入力変数をこの新しい配列に対してポイントします。

下記の例題では、 関数 myfun は、関数に渡された配列の値を修正します。 MATLAB は、 Aによりポイントされる配列のコピーをメモリに作成し、変数 X をこの新しい配列へのポインタとして設定し、その後、 X の1行をゼロに設定します。 A により参照される配列は、変更されません。

A = magic(500);
myfun(A);

function myfun(X)
X(400,:) = 0;

大きなデータセットの取り扱い.

再度、大きなデータセットを取り扱う場合、呼び出された関数が値を修正する時に、 MATLAB が Aの一時的なコピーを作成することに注意する必要があります。 この ため、配列のストアに必要なメモリが倍になります。これは、十分なメモリを利用できない場合、 MATLAB がエラーを出力する原因となります。

この状況でメモリの不足を避ける1つの方法は、入れ子関数を使用することです。入れ子関数は、外側の関数すべてのワークスペースを共有し、入れ子関数の通常のスコープの外側のデータに入れ子関数がアクセスできるようになります。 ここで示す例題において、入れ子関数 setrowval は、外側の関数 myfunのワークスペースに直接的なアクセスができ、関数呼び出しにおいて、変数のコピーを渡すことが不要になります。 setrowval が A の値を修正する場合、呼び出し関数のワークスペース内で修正します。呼び出される関数に対して別の配列を保持するために追加のメモリを使用する必要はありません。また、 Aの修正された値を返す必要もありません。

function myfun
A = magic(500);

   function setrowval(row, value)
   A(row,:) = value;
   end

setrowval(400, 0);
disp('The new value of A(399:401,1:10) is')
A(399:401,1:10)
end
トラックバック - http://chick.g.hatena.ne.jp/allegro/20070212
テクノラティプロフィール