2013-10-24 6 views
6

大量のテキストファイルを解析してディスクに* .matファイルとして保存するので、その部分だけを簡単にロードできます(詳細はhereを参照してください)。ファイルの読み込み時、データの場合はhere)。これを行うには、一度に1行ずつ読み込み、その行を解析してファイルに追加します。問題は、ファイル自体がそこに含まれるデータより3桁以上大きいことです!それは非常に長い時間を取っていたと、ファイルサイズが巨大になっていたので、224515行の13813が解析された後、私は、コードを停止しMATLAB .matファイルのオーバーヘッドが非常に大きい

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); 

:ここ

は、私のコードのストリップダウンバージョンです。最後のプリントアウトは、私はただ10k行をクリアしたことを示しました。私はメモリをクリアした後、走っ:

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

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

disp([fileBytes diskBytes diskBytes/fileBytes]) 

と出力を得る:余分895664115バイトを取っている何

524894 896189009 1707.37141022759

を?ヘルプページに少し余分なオーバーヘッドがあると言われていることは分かっていますが、わかりやすいヘッダのGbは少し余計です。

新情報:
私は多分MATLABは行列がループ内でembiggenedと上の行列全体のディスク領域のチャンクを再割り当てされたときにそれがないと同じことをやっていたことを考えて、事前割り当てファイルを試してみましたそれぞれの書き込み、それはそれではありません。

8531570 71467 0.00837677004349727

これは私に多くの意味があります:私のショートチェックスクリプトが返すファイルに適切なデータ型結果のゼロでファイルを充填。 Matlabはファイルをまばらに保存しているので、ディスクファイルのサイズはメモリのフルマトリックスのサイズよりもずっと小さくなります。しかし、実際のデータで値を置き換えると、前と同じ動作になり、ファイルサイズがすべての妥当な範囲を超えて急激に増加し始めます。

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

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

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

+0

あなたのOSは実際にディスク上でどれくらいのスペースが実際に使用されていると言いますか? – Daniel

+0

857,185Kb(Windows 7 64ビット、MATLAB 2013a 64ビット) – craigim

+0

確かに私にはバグのようですが、チャンクで書くことで回避できます。私は10,000の塊のためにそれを試み、ファイルは合理的なサイズです。 – chappjc

答えて

2

これは私のバグのようです。この問題を回避するには、をあらかじめ割り振られた配列のチャンクに書き込んでください。ディスク上の

... % your code plus pre-alloc first 
bs = 10000; 
while ischar(hitranTemp) 
    if abs(hitranTemp(1)) == 32; 
     hitranTemp(1) = '0'; 
    end 

    for ii = 1:bs, 
     hitran{ii} = textscan(hitranTemp,'%2u%1u%12f%10f%10f%5f%5f%10f%4f%8f%15c%15c%15c%15c%6u%2u%2u%2u%2u%2u%2 u%1c%7f%7f','delimiter','','whitespace',''); 
     hitranTemp = fgetl(fidr); 
     if hitranTemp==-1, bs=ii; break; end 
    end 

    % this part really ugly, sorry! trying to keep it compact... 
    matObj.moleculeNumber(1,k:k+bs-1)  = uint8(builtin('_paren',cellfun(@(c)c{1},hitran),1:bs)); 
    matObj.isotopeologueNumber(1,k:k+bs-1) = uint8(builtin('_paren',cellfun(@(c)c{2},hitran),1:bs)); 
    matObj.vacuumWavenumber(1,k:k+bs-1) = builtin('_paren',cellfun(@(c)c{3},hitran),1:bs); 
    matObj.lineIntensity(1,k:k+bs-1)  = builtin('_paren',cellfun(@(c)c{4},hitran),1:bs); 
    matObj.airWidth(1,k:k+bs-1)   = single(builtin('_paren',cellfun(@(c)c{5},hitran),1:bs)); 
    matObj.selfWidth(1,k:k+bs-1)   = single(builtin('_paren',cellfun(@(c)c{6},hitran),1:bs)); 
    matObj.lowStateE(1,k:k+bs-1)   = single(builtin('_paren',cellfun(@(c)c{7},hitran),1:bs)); 
    matObj.tempDependWidth(1,k:k+bs-1)  = single(builtin('_paren',cellfun(@(c)c{8},hitran),1:bs)); 
    matObj.pressureShift(1,k:k+bs-1)  = single(builtin('_paren',cellfun(@(c)c{9},hitran),1:bs)); 

    k = k + bs; 
    fprintf('.'); 
end 
fclose(fidr); 

最終的なサイズは21393408バイトです:事前に割り当てることにより、

スタートオフ:次のように

fid = fopen('01_hit12.par', 'r'); 
data = fread(fid, inf, 'uint8'); 
nlines = nnz(data == 10) + 1; 
fclose(fid); 

matObj.moleculeNumber = zeros(1,nlines,'uint8'); 
matObj.isotopeologueNumber = zeros(1,nlines,'uint8'); 
matObj.vacuumWavenumber = zeros(1,nlines,'double'); 
matObj.lineIntensity = zeros(1,nlines,'double'); 
matObj.airWidth = zeros(1,nlines,'single'); 
matObj.selfWidth = zeros(1,nlines,'single'); 
matObj.lowStateE = zeros(1,nlines,'single'); 
matObj.tempDependWidth = zeros(1,nlines,'single'); 
matObj.pressureShift = zeros(1,nlines,'single'); 

はその後10000のチャンクに書き込むためには、私はあなたのコードを変更しました。使用法は次のように分類されます。

>> S = whos('-file','01_hit12.mat'); 
>> fileBytes = sum([S.bytes]); 
>> T = dir(which('01_hit12.mat')); 
>> diskBytes = T.bytes; ratio = diskBytes/fileBytes; 
>> fprintf('%10d whos\n%10d disk\n%10.6f\n',fileBytes,diskBytes,ratio) 
    8531608 whos 
    21389582 disk 
    2.507099 

まだ効率的ではありませんが、制御不能ではありません。

+0

私はこの夜間稼働のバージョンを持っています(それはそれほど長くはかかりませんが、仕事をする前に走っていました)。午前中は、私が働くことができる20Mバイトのファイル私のハードドライブを食べる30ギガバイトの怪物です。あなたが主題に注意を払ってデータファイルを持っている間に、先週投稿したリンク先の質問を読んでいただければ幸いです。 'textscan'を使用している場合(つまり、if(abs(hitranTemp)== 32); hitranTemp(1)=' 0 '; end'ブロック)、データを解析するときに同じことが表示されますか? – craigim

+0

:)私のマシンでは20分以上ではなく20回程度の書き込みしかないので、ほんの数分しかかかりませんでした。 0,000。 – chappjc

+0

私のコンピュータはわずか6ヶ月ですが、まだかなり遅いです。私はそれを走らせ始めました、そして、私が出発するために私のものを集めていた時に、それはまだ去っていました。 – craigim

関連する問題