我的问题是如何以更快的方式在MATLAB中找到ismember()
所做的替代方法。
这是我的问题:
M [92786253*1] (a: roughly 100M rows)
x [749*1] (b: # of rows can vary from 100 to 10K)
我想在b
中找到共存于a
中的行(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 :(得分: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:强>
s=sort(M);
edge= [-Inf s(2:end) Inf];
ind = false(size(M));
%for ... 100M iterations
tic
[~,~,bin]=histcounts(x,edge);
ind(bin)= ind(bin)==x;
toc
%...
ind(bin) = false;
%end
答案 1 :(得分:1)
您可能会发现内部(内置)ismembc
函数很有用 - 它比ismember
快一个数量级:http://UndocumentedMatlab.com/blog/ismembc-undocumented-helper-function
请注意,ismembc
仅适用于已排序的非稀疏非Nan数字数据。