2016-04-18 21 views
3

私は、同期パターン(0xDEADBEEF)とそれに続く固定サイズのデータ​​ブロックで整理された大きなバイナリファイル(2GB以上)を持っています。 例:matlabメモリマップの効率的なバイトパターン検索

0xDE AD BE EF ... 96 bytes of data 
0xDE AD BE EF ... 96 bytes of data 
... repeat ... 

私は、各パケットの先頭にオフセットを特定する必要があります。理想的にはこれはちょうど[1:packetSize:fileSize]になるでしょう。しかし、散在させることができる他のデータ、ヘッダなどがありますので、ファイルを検索して同期パターンを調べる必要があります。

私はLoren from Mathworks findPattern2に基づいていますが、メモリマップを使用するために少し変更した次のコードを使用しています。

function pattLoc = findPattern(fileName, bytePattern) 
%Mem Map file 
m = memmapfile(fileName); 
% Find candidate locations match the first element in the pattern. 
pattLoc = find(m.data==bytePattern(1)); 
%Remove start values that are too close to the end to possibly match 
len = numel(bytePattern); 
endVals = pattLoc+len-1; 
pattLoc(endVals>length(m.data)) = []; 
% loop over elements of Sync Pattern to check possible location validity. 
for pattval = 2:len 
    % check viable locations in array 
    locs = bytePattern(pattval) == m.data(pattLoc+pattval-1);  
    pattLoc(~locs) = []; % delete false ones from indices 
end 

これはかなりうまく動作します。しかし、私は改善の余地があると思う。最初に私のパターンはpacketSize(この例では100)よりも近くはできませんが、もっと離れているかもしれません。何とかこの情報を使って検索をスピードアップできるように思えます。次に、行5の最初の検索では、論理ではなく数字の索引付けにはfindが使用されます。この行は論理的なままにしておくとほぼ2倍の時間がかかります。しかし、論理インデックスのみを使用してこの機能を再現しようとしましたが、悲惨に失敗しました。この問題は、ループ内で発生し、より多くの検索を使用せずに論理で入れ子になった索引付けを追跡したり、必要以上のデータをチェックしたりします。

これをスピードアップするのに役立つと思います。以下は、必要に応じて簡単なサンプルバイナリファイルを作成するコードです。 10000000個のパケットを使用してファイルを検索する

function genSampleFile(numPackets) 
pattern = hex2dec({'DE','AD','BE','EF'}); 
fileName = 'testFile.bin'; 
fid = fopen(fileName,'w+'); 
for f = 1:numPackets 
    fwrite(fid,[pattern; uint8(rand(96,1)*255)],'uint8'); 
end 
fclose(fid); 

は次を取っ:

>> genSampleFile(10000000); %Warning Makes 950+MB file 
>> tic;pattLoc = findPattern(fileName, pattern);toc 
Elapsed time is 4.608321 seconds. 

答えて

1

あなたが代わりにfindfindstrを使用することによって直ちにブーストを取得し、またはより良いまだstrfindことができます。

pattLoc = strfind(m.data, bytePattern) 

このそれ以上ループする必要はありません。返されたインデックス配列で2つのものをクリーンアップする必要があります。

最後に100バイトよりも近いものを最後から4バイト以内に削除したいので、len = length(bytePattern)の代わりにlen = 100と設定します。

は、より近い100のバイトが互いからある要素を除外するインデックスのリストにdiffを使用するには:

pattLoc[diff(pattLoc) < 100] = [] 

これは、より一般的にはるかにされている組み込みコマンド、に依存することによって、あなたのコードをスピードアップする必要がありますループよりも効率的です。

+0

Mathworksの記事を見ると、Lorenは既に 'findPattern2'アルゴリズムと' strfind'を比較しました。大きなデータセットに対して 'strfind'は高速ではありません。あなたはlen == 100について正しいです。また、私は 'diff'をチェックすることで悪い場所を除外することができますが、この既知の最小距離情報を使って最初の検索を高速化するだけでなく、裏面。 –

+0

memmapの場合、 'find(... == ...)'は*ファイル全体をメモリ上の '論理'配列に変換するので、 'strfind'は高速になります。 zLorenはすでにメモリ上にある配列で作業しています。その場合、findPattern2の例は本当に高速です。実際に 'memmap'の場合の' find'に対して 'strfind'バージョンを抑制しましたか? –

関連する問題