2017-09-25 19 views
2

私の質問は、MATLABでより速い方法でismember()が行うことの代替アプローチを見つけることです。ここでMATLABのismember()関数の高速バージョン

は私の問題です:

M [92786253*1] (a: roughly 100M rows) 
x [749*1]  (b: # of rows can vary from 100 to 10K) 

私はa(の行インデックス)で、存在する共同b内の行を見つけたいです。 bの異なるバージョンの場合、この操作を約10M回回繰り返す必要があります。

通常のアプローチ:

tic 
ind1 = ismember(M,x); 
toc 

Elapsed time is 0.515627 seconds. 

高速アプローチ:

tic 
n = 1; 
ind2 = find(any(all(bsxfun(@eq,reshape(x.',1,n,[]),M),2),3)); 
toc 

Error using bsxfun 
Requested 92786253x1x749 (64.7GB) array exceeds maximum array size preference. 
Creation of arrays greater than this limit may take a long time and cause MATLAB to become unresponsive. 
See array size limit or preference panel for more information. 

Error in demo_ismember_fast (line 23) 
ind2 = find(any(all(bsxfun(@eq,reshape(x.',1,n,[]),M),2),3)) 

第二のアプローチは、しかし、この場合には、通常、通常より15〜20倍高速であります私はメモリ制限のためにそれを使用することはできません。この操作をスピードアップする方法はありますか?私と専門家の意見を共有してくれてありがとう!

+0

64GbのRAMを購入すると思いますか? :Pこれは非常に大きな問題で、遅くなることを期待する必要があります –

+0

もしそうなら、最初のケースでは何のエラーもありません。私は 'ismember()'を使う以外はこれ以外のトリックがあると思います。 – YAS

+0

そこにどんな制約がありますか? 'M'か' x'のどちらかがソートされていますか? – Divakar

答えて

1

ここでソートされたaを使用することができる場合は、2つの方法があります。 100Mの繰り返しを開始する前に、必要な入力変数と出力変数indが初期化され、各繰り返しでindが変更され、最後にすべての要素がfalseに設定されます。

interp1を:

s=sort(M); 
edge = [-Inf s(2:end) Inf]; 
v = [1:numel(M) numel(M)]; 
ind = false(size(M)); 
%for ... 100M iterations 
    tic 
    bin = interp1(edge,v,x,'previous'); 
    ind(bin)= ind(bin)==x; 
    toc 
    %... 
    ind(bin) = false;%at the end of each loop set all elements of ind to 0; 
%end 

histcounts:

​​
+0

これらの提案をありがとう、私の元の質問では、私たちは 'M'と' x'を持って、これに基づいて答えを変更できますか?私が言及した100Mの反復のためにあなたのために組み込まれているか、1回の反復のために必要ですか? – YAS

+0

forループは100Mの反復を持つと仮定します。私は変数を変更します。 – rahnema1

+0

明確にしていただき、ありがとうございます。 – YAS

1

あなたが便利(内蔵)内部ismembc機能を見つけるかもしれない - それは速くismemberよりも桁違いにすることができ:http://UndocumentedMatlab.com/blog/ismembc-undocumented-helper-function

つまり、ismembcは、ソートされた非スパース非ナンの数値データに対してのみ正しく動作します。

関連する問題