このページの翻訳は最新ではありません。ここをクリックして,英語の最新版を参照してください。
このトピックでは,MATLAB®でメモリを効率的に使用するためのいくつかの手法を説明します。
MATLABでは,双
やuint8
などの,異なるサイズのデータクラスが提供されています。このため,小さなデータセグメントを格納するために大きなクラスを使用する必要はありません。1000年たとえば個の小さな符号なし整数値を格納するには,uint8
クラスを使用すれば,双
クラスの場合よりも必要なメモリが7 KB少なくて済みます。
MATLABでは,操作の内容の応じて異なる数値クラスを使用できます。既定のクラス双
では精度が最良となりますが,格納にはメモリの要素ごとに8バイトが必要です。線形代数のように複雑な計算を行う場合は,双
や单
などの浮動小数点クラスを使用しなければなりません。单
クラスで必要なのは,4バイトのみです。单
クラスで実行できる操作にはいくつかの制約がありますが,ほとんどのMATLAB数学演算がサポートされています。
簡単な演算のみを実行し,元のデータを整数として表す場合は,MATLABの整数クラスを使用できます。以下に,数値クラス,必要なメモリ(バイト単位),サポートされる演算を一覧にします。
クラス(データ型) | バイト | サポートされている演算 |
---|---|---|
单 |
4 | ほとんどの数学演算 |
双 |
8 | すべての数学演算 |
逻辑 |
1 | 論理演算と条件付き演算 |
int8, uint8 |
1 | 算術関数と一部の単純な関数 |
int16, uint16 |
2 | 算術関数と一部の単純な関数 |
int32, uint32 |
4 | 算術関数と一部の単純な関数 |
int64, int64 |
8 | 算術関数と一部の単純な関数 |
mxArrays
として内部実装されるMATLAB配列では,タイプ,次元,属性など,データに関するメタ情報を保存するメモリスペースが必要です。これには,配列ごとに約104バイト必要です。このオーバーヘッドは,多数の(何百または何千の)小さなmxArrays
(スカラー)がある場合には問題になります。谁
コマンドでは変数で使用されるメモリが一覧表示されますが,このオーバーヘッドは含まれません。
1つのmxArray
で構成される簡単な数値配列ではオーバーヘッドが最小になるので,できるだけこの数値配列を使用するようにします。データが複雑すぎて単純な配列や行列に保存できない場合は,他のデータ構造を使用できます。
细胞配列は,各要素に対する別々のmxArrays
で構成されます。このため,多くの小さな要素をもつ细胞配列ではオーバーヘッドが大きくなります。
構造体では,フィールドごとにほぼ同量のオーバーヘッドが必要です(配列ヘッダーを参照してください)。多くのフィールドと小さなコンテンツをもつ構造体は,オーバーヘッドが大きくなるので避けるようにします。数値スカラーフィールドをもつ構造体の大規模な配列では,大規模な数値配列を含むフィールドをもつ構造体よりも,多くのメモリが必要です。
また,MATLABでは数値配列が連続したメモリに格納されますが,構造体や细胞配列ではメモリは連続していないことに注意してください。
从文件中读
を使用してバイナリファイルからデータを読み込む場合,ファイル内のデータのクラスのみを指定し,データがワークスペースに読み込まれた後にMATLABで使用されるデータクラスを忘れてしまうというミスを犯しがちです。このような場合,わずか8ビットの値を読み取るとしても,既定の双
が使用されます。たとえば,
Fid = fopen('large_file_of_uint8s.bin', 'r');A = fread(fid, 1e3, 'uint8');% require 8k whos a Name Size Bytes Class Attributes a 1000x1 8000 double a = fread(fid, 1e3, 'uint8=>uint8');%需要1k谁是一个名称大小字节类属性1000x1 1000 uint8
データに多くのゼロが含まれる場合は,ゼロ以外の要素のみを格納する,スパース配列の使用を考慮します。次の例は,スパースストレージと非スパースストレージの要件を比較しています。
一个=眼(1000);%对角为1的满矩阵=稀疏矩阵(A);类属性A 1000x1000 8000000 double As 1000x1000 24008 double Sparse
この配列は,スパースとして保存すると約4 KBしか必要としませんが,非スパース行列ではおよそ8 MBが必要になることがわかります。一般に,非ゼロ要素がnnz
個,列数がncol
の双型スパース配列で必要なメモリは以下のとおりです。
16 *nnz
+ 8 *ncol
+ 8バイト(64ビットのコンピューターの場合)
MATLABでは,ほとんどの数学演算がスパース配列でサポートされていますが,全部ではありません。
データの不必要な一時コピーの作成を回避することで,必要なメモリ量を大きく削減できます。
大きな一時変数の作成を回避し,一時変数が不必要になった際にはクリアするようにします。たとえば,次のコードは一時変数一个
として保存される0で構成された配列を作成した後,一个
を単精度に変換します。
一个= 0 (1)e6, 1);=单(A);
1つのコマンドを使用して両方の演算を実行する方が,メモリ効率は高くなります。
= 0 (1 e6, 1, '单');
関数repmat
,配列の事前割り当て,および为
ループや他の方法を使用しても,メモリ内で一時的なストレージを必要とせずに双でないデータを扱うことができます。
大きなデータセットを扱う場合には,呼び出された関数で値を変更する際に,MATLABによって入力変数の一時的なコピーが作成されることに注意しなければなりません。このため,配列の格納に必要なメモリが2倍になり,十分なメモリがないとMATLABでエラーが発生します。
このような状況で使用メモリを減らす方法の1つとして,入れ子関数を使用することが考えられます。入れ子関数は外側の関数すべてとワークスペースを共有するため,通常のスコープ外にあるデータにもアクセスできます。ここで示す例では,入れ子関数setrowval
は,外側の関数myfun
のワークスペースに直接アクセスでき,関数呼び出しにおいて変数のコピーを渡す必要はありません。setrowval
によって一个
の値が変更される際には,呼び出し側の関数のワークスペース内で変更されます。呼び出す関数のために個別の配列を保持するための追加メモリは必要なく一个
の変更された値を返す必要もありません。
函数myfun A = magic(500);函数setrowval(row, value) = value;结束setrowval (400 0);disp('The new value of A(399:401,1:10) is') A(399:401,1:10) end
使用可能なメモリの量を簡単に増やす方法の1つとして,使用していない大きな配列をクリアすることがあげられます。
プログラムで大量のデータが生成される場合,データを定期的にディスクに書き込むようにします。この部分のデータを保存した後に,メモリから変数を清晰的
して,データ生成を続行します。
非常に大規模なデータセットを繰り返し,または対話形式で扱う場は合,まず古い変数をクリアして,新しい変数のための容量を確保します。この作業を行わない場合,変数をオーバーライドにする前に,MATLABで同じサイズの一時的なストレージが必要になります。以下に例を示します。
兰德(1 = e5);b =兰德(1 e5);内存不足。更多信息clear a a = rand(1e5);%新数组