快速检查元素是否在MATLAB矩阵中

时间:2014-12-10 17:32:48

标签: performance matlab optimization

我想验证一个元素是否存在于MATLAB矩阵中。

一开始,我实现如下:

if ~isempty(find(matrix(:) == element))

这显然很慢。因此,我改为:

if sum(matrix(:) == element) ~= 0

但这又慢了:我多次调用包含该指令的函数,每次丢失14秒!

有没有办法进一步优化这条指令?

感谢。

2 个答案:

答案 0 :(得分:5)

如果您只需要知道矩阵中是否存在值,则使用find的第二个参数来指定您只需要一个值将稍快(25-50%),甚至比使用{{ 1}},至少在我的机器上。一个例子:

sum

然而,在Matlab的最新版本中(我使用R2014b),nnz最终更快地进行此操作,因此:

matrix = randi(100,1e4,1e4);
element = 50;
~isempty(find(matrix(:)==element,1))

在我的机器上,对于提供的示例,这比任何其他方法(包括奇怪地使用matrix = randi(100,1e4,1e4); element = 50; nnz(matrix==element)~=0 )快约2.8倍。在我看来,这个解决方案还具有最易读的优点。

答案 1 :(得分:3)

在我看来,有几件事可以尝试提高绩效:

  1. 按照你最初的想法,我会去函数any来测试任何相等测试是否成功:

    if any(matrix(:) == element)

  2. 我在1000 x 1000矩阵上测试了它,它比你测试的解决方案更快。

    1. 我不认为展开matrix(:)是有害的,因为它等同于重塑,而Matlab以一种聪明的方式做到这一点,因为你没有实际分配和移动内存,因为你没有修改临时对象matrix(:)

    2. 如果您在函数调用之间没有变化或很少更改,您可以简单地使用另一个包含矩阵所有元素的向量,但已排序。通过这种方式,您可以使用更有效的搜索算法O(log(N))测试您的元素是否存在。

    3. 我个人喜欢这种问题的ismember函数。它可能不是最快的,但对于代码的非关键部分,它极大地提高了可读性和代码维护(我宁愿花一个小时编写一些需要一天运行的东西,而不是花一天时间编写一小时运行的代码(这当然取决于你使用这个程序的频率,但这是人们永远不会忘记的事情)

    4. 如果您可以拥有矩阵元素的排序副本,则可以考虑使用未记录的Matlab函数ismembc,但请记住输入必须按非稀疏非NaN值排序。

    5. 如果性能确实很重要,您可能想编写自己的mex文件,对于此任务,您甚至可以使用openmp包含一些简单的并行化。

    6. 希望这有帮助,

      阿德里安。