问题 是否有像“ismember”这样的函数但效率更高?


例如,A是数字set.b是元素。

我想测试b中的数字是否是集合A的元素。

我知道matlab函数“ismember”可以做到这一点,但是当我使用它一百万次时它不够快。

b=[1,2,9,100];
A=[1,2,3,4,5,6,7,8,9];
tic;for ii=1:1e6,ismember(b,A);end;toc
Elapsed time is 45.714583 seconds.

我想返回[1,1,1,0],因为1,2,9在集合A中,而100则不在。

你知道像ismember这样的某些功能还是比“ismember”更有效的方法?


6912
2017-07-18 04:21


起源

你真的需要按顺序使用它一百万次吗? - Dennis Jaheruddin
@ Dennis Jaheruddin我为了测试效率而运行了一百万次,并不是真的要运行一百万次。 - lihaitao


答案:


你可以使用mex版本,即 ismemberoneoutput。 mex版本要快得多。

b=[1,2,9,100];
A=[1,2,3,4,5,6,7,8,9];
tic;for ii=1:1e5,ismember(b,A);end;toc
%Elapsed time is 9.537219 seconds. On my pc

% A must be sorted!!! In this example it is already sorted,
% so no need for this here.
tic;for ii=1:1e5,builtin('_ismemberoneoutput',b,A);end;toc
%Elapsed time is 0.376556 seconds. On my pc

13
2017-07-18 04:40



非常感谢!顺便说一下,“_ismemberoneoutput”在哪里?“编辑_ismemberoneoutput”无法找到该功能。你怎么知道这个功能呢?它在哪里? - lihaitao
@lihaitao你可以尝试其他无证版本, ismembc(b,A)。我通过检查Matlab的ismember.m来源了解了buildin - Marcin
为了完整性:我认为在这个例子中花费超过9秒的主要原因是因为 ismember 不是内置的,因此该测试循环不能被JIT控制。换句话说,你的测试是非一般的;结果仅适用于以下情况 ismember 用于循环。再次测试真的很大 b 和 A,你会发现两者都具有相似的性能。正如您所指出的,使用MEX变体是脆弱且不可移植的,因为它会对特定的MATLAB版本产生依赖性。仅用于性能关键部件,并将其记录良好。 - Rody Oldenhuis
+1:还有 ismembc。 - Eitan T
@lihaitao: _ismemberoneoutput R2012a +支持,所以你应该拥有它我相信。但你不能像普通的功能那样运行它。你必须打电话 builtin('_ismemberoneoutput',b,A) 正如@Marcin所示,因为它是一个mex C ++函数。列出了另外两个C ++ mex函数 ismember 如果你输入 edit ismember 并看看第577+行左右。最后, ismembc 是一个更老的C mex功能,你会发现。 - horchler


这可能无法避免,但计算速度太慢的一个原因是因为您没有打电话 ismember 以矢量化的方式。

试试这个,它简单快捷:

bigb = repmat(b,1e6,1);
ismember(bigb,A);

0
2017-07-18 10:32



我运行它一百万次只是为了测试效率,而不是真的想要运行它一百万次。 - lihaitao
@lihaitao是的,像ismember这样强大的函数对于小规模的例子来说效率不高。但我的观点是,除非你已经运行了几百次,否则解决小规模问题所需的时间可能不是最相关的效率衡量标准。 - Dennis Jaheruddin