6

データでいっぱいの大きなテキスト ファイルを解析し、*.mat ファイルとしてディスクに保存して、その一部だけを簡単に読み込めるようにしています (ファイルの読み取りの詳細についてはこちらを、データについてはこちらを参照してください)。 )。そのために、一度に 1 行ずつ読み取り、その行を解析して、ファイルに追加します。問題は、ファイル自体がそこに含まれるデータよりも 3 桁以上大きいことです!

これが私のコードの簡素化されたバージョンです:

database = which('01_hit12.par');
[directory,filename,~] = fileparts(database);
matObj = matfile(fullfile(directory,[filename '.mat']),'Writable',true);

fidr = fopen(database);
hitranTemp = fgetl(fidr);
k = 1;
while ischar(hitranTemp)
    if abs(hitranTemp(1)) == 32;
        hitranTemp(1) = '0';
    end

    hitran = textscan(hitranTemp,'%2u%1u%12f%10f%10f%5f%5f%10f%4f%8f%15c%15c%15c%15c%6u%2u%2u%2u%2u%2u%2u%1c%7f%7f','delimiter','','whitespace','');

    matObj.moleculeNumber(1,k)      = uint8(hitran{1});
    matObj.isotopeologueNumber(1,k) = uint8(hitran{2});
    matObj.vacuumWavenumber(1,k)    = hitran{3};
    matObj.lineIntensity(1,k)       = hitran{4};
    matObj.airWidth(1,k)            = single(hitran{6});
    matObj.selfWidth(1,k)           = single(hitran{7});
    matObj.lowStateE(1,k)           = single(hitran{8});
    matObj.tempDependWidth(1,k)     = single(hitran{9});
    matObj.pressureShift(1,k)       = single(hitran{10});

    if rem(k,1e4) == 0;
        display(sprintf('line %u (%2.2f)',k,100*k/K));
    end
    hitranTemp = fgetl(fidr);
    k = k + 1;
end
fclose(fidr);

224,515 行のうち 13,813 行が解析された後、非常に長い時間がかかり、ファイル サイズが大きくなったため、コードを停止しましたが、最後の出力では、10,000 行しかクリアしていないことが示されました。メモリをクリアしてから実行しました:

S = whos('-file','01_hit12.mat');
fileBytes = sum([S.bytes]);

T = dir(which('01_hit12.mat'));
diskBytes = T.bytes;

disp([fileBytes diskBytes diskBytes/fileBytes])

出力を取得します。

524894 896189009 1707.37141022759

余分な 895,664,115 バイトを占めているのは何ですか? ヘルプ ページには少し余分なオーバーヘッドがあるはずだと書かれていることは知っていますが、約 1 GB の説明的なヘッダーは少し過剰だと感じています。

新しい情報:
ファイルの事前割り当てを試みました。おそらく、MATLAB は、行列がループ内で大きくなり、書き込みごとに行列全体のディスク領域のチャンクを再割り当てするときに行うのと同じことを行っているのではないかと考えましたが、そうではありません。それ。ファイルを適切なデータ型のゼロで埋めると、短いチェック スクリプトが返すファイルが生成されます。

8531570 71467 0.00837677004349727

これは私にとってより理にかなっています。Matlab はファイルをまばらに保存しているため、ディスク ファイルのサイズは、メモリ内の完全な行列のサイズよりもはるかに小さくなっています。ただし、値を実際のデータに置き換え始めると、以前と同じ動作になり、ファイル サイズがすべての妥当な範囲を超えて急上昇し始めます。

新しい新しい情報:
100 行の長さのデータのサブセットでこれを試しました。ディスクにストリーミングするには、データが v7.3 形式である必要があるため、スクリプトを使用してサブセットを実行し、それをメモリにロードしてから、v7.0 形式で再保存しました。結果は次のとおりです。

v7.3: 3800 8752 2.30
v7.0: 3800 2561 0.67

v7.3 形式がデフォルトではないのも不思議ではありません。誰もこれを回避する方法を知っていますか? これはバグですか、それとも機能ですか?

4

1 に答える 1