2017-09-25 370 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) 

我想找到b行是共同存在于a(的行索引)。 对于不同版本的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这里有两种替代方法。在开始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

感谢您的澄清,你能否提一下'out'代表什么? – YAS