2

大量の RAM を搭載したマシン上にフレームワークがあり、非常に大きくて特別に名前が付けられた 1 つの行列を含む MAT ファイルを生成します。この行列の計算は 1 回だけ実行され、多くの時間がかかります。最後に、ディスク上の MAT ファイルに保存されます。

使用段階で、この MAT ファイルをロードする必要があります。問題は、すべてのデータが必要ないことです。そのマトリックスから特定の列を選択するだけです。

たとえば、サイズ [500x250000] のファイル crfh.mat に行列 'sign' があり、double と入力します。そのマトリックスから「ids」を使用してベクトルのみをロードすることに興味があるかもしれません:

sign( :, ids )

それを行う方法はありますか?Web を検索しましたが、そのような機能の必要性を表明した人は誰もいないようです。次のような MEX 関数 select_mat() を作成することを考えています。

sign_sub = select_mat( mat_file, var_name, ids );

4

2 に答える 2

3

一部のみをロードしたい非常に大きな行列がある場合、.MAT ファイルとして保存しません。行列を独自のバイナリ ファイルに書き込む方が効率的です。次に、FSEEKなどの関数を使用して、ファイル内のさまざまなインデックス付きポイントにスキップし、必要なものだけを読み取ることができます。たとえば、関数FWRITEを使用して、最初に小さなサンプル行列をバイナリ ファイルに保存してみましょう。

>> M = magic(5)  %# A sample matrix
M =
    17    24     1     8    15
    23     5     7    14    16
     4     6    13    20    22
    10    12    19    21     3
    11    18    25     2     9

>> fid = fopen('bigmatrix.dat','w');  %# Open the file for writing
>> fwrite(fid,size(M),'uint8','l');   %# Write the matrix size (needed later) as
                                      %#   2 unsigned 8-bit (1-byte) integers
>> fwrite(fid,M,'uint8','l');         %# Write the matrix data as unsigned 8-bit
                                      %#   (1-byte) integers
>> fclose(fid);                       %# Close the file

これで、関数FREADおよびFSEEKを使用して 3 番目の列だけを読み取ることができます。

>> colIndex = 3;
>> fid = fopen('bigmatrix.dat','r');    %# Open the file for reading
>> sizeM = fread(fid,2,'uint8','l');    %# Read the first two bytes to get the
                                        %#   size of the matrix in the file
>> fseek(fid,sizeM(1)*(colIndex-1),0);  %# Seek forward by an amount of two
                                        %#   columns worth of bytes
>> colData = fread(fid,sizeM(1),'uint8','l');  %# Read column 3 data
>> fclose(fid);                         %# Close the file
>> disp(colData)                        %# Confirm that the right column was read
     1
     7
    13
    19
    25

これは簡単な例です。行列内の各値のバイト サイズやデータ型など、他の情報 (ヘッダー情報など)をファイルに書き込むことをお勧めします。これは単に .MAT ファイルに何かをダンプするよりも手間がかかるように思えるかもしれませんが、ファイル IO 操作の効率が大きな懸念事項である場合は、この場合、データを処理するための独自のファイル形式を作成することをお勧めします。

于 2011-03-17T18:56:06.300 に答える
2

.mat複数の変数を含むファイルから特定の変数をロードできます。ただし、MATLAB の変数内から任意のインデックスのセットだけを読み込むことはできないと思います。

とはいえ、特定の行/列のみにアクセスする必要があるタイプの問題である場合は、回避策があるかもしれません。

struct各列を個別のフィールドとしてマトリックスから作成し、オプションを使用して.matファイルを保存して、各フィールドが個別の変数として保存されるようにすることができます。-structそうすれば、あなたはあなたが望むものを引き出すことができます。

dummy=randn(100,200);%# this is a test matrix
[dim1,dim2]=size(dummy);

dummyCell=mat2cell(dummy,dim1,ones(dim2,1));%# create a cell from the matrix
fieldNames=strcat(repmat({'col'},1,dim2),cellfun(@num2str,mat2cell(1:dim2,1,ones(dim2,1)),'UniformOutput',false));%# generate fieldnames for the struct

dummyStruct=cell2struct(dummyCell,fieldNames,2);%# create the struct
save('myDummyFile','-struct','dummyStruct')

マトリックスを構造体に直接変換する方法を知りません。したがって、最初に各列をセルに分割します (順序付けは、列にアクセスする必要があることを示したためです。行が必要な場合は、物事を切り替える必要があります)。これはセルにありdummyCellます。構造体に保存するには、フィールド名を生成する必要があります。これは文字列セルにありfieldNamesます。col1、などの形式のフィールド名を生成col2します。必要に応じて、意味のある名前を付けることができます。次に、各セルを対応するフィールド名に割り当てることによりcell、を に変換します。struct最後に、-structMATLAB に各フィールドを個別の変数として保存するように指示するオプションを使用して、mat ファイルを保存します。これはすべて、プログラムが巨大なマット ファイルを保存しているときに実行する必要があります。アクセスする必要がある場合は、col52、あなたがする必要があるのはそれだけですload('myDummyFile','col52')。必要に応じて複数ロードすることもできます。

マトリックス内の任意のインデックスにアクセスする必要がある場合、インデックス要件 (つまり、各行/各列) に順序がある場合、これはうまく機能しますが、これは機能しません。セル/構造体を作成して保存するときに、関連するオーバーヘッドが発生する場合があります。ただし、保存は 1 回だけで、頻繁にアクセスする場合は、これで十分です。

マトリックスが巨大な場合 (500x250000 は、今日の標準ではそれほど大きくありません)、このアプローチではメモリの問題に注意する必要があります。これは、マトリックス全体をセルと構造体に複製しているためです。わかりやすくするために順を追って書いていますがdummy、構造体についても同様にセルを作成してそれ自体に代入することで重複を減らすことができます。ただし、Matlab は操作後に変数をメモリにコピーしてそれ自体に割り当てる必要があるため、これはコピーの数を 1 つ減らすだけです。

于 2011-03-17T18:29:31.680 に答える