我想验证一个元素是否存在于MATLAB矩阵中。
一开始,我实现如下:
if ~isempty(find(matrix(:) == element))
这显然很慢。因此,我改为:
if sum(matrix(:) == element) ~= 0
但这又慢了:我多次调用包含该指令的函数,每次丢失14秒!
有没有办法进一步优化这条指令?
感谢。
答案 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)
在我看来,有几件事可以尝试提高绩效:
按照你最初的想法,我会去函数any
来测试任何相等测试是否成功:
if any(matrix(:) == element)
我在1000 x 1000矩阵上测试了它,它比你测试的解决方案更快。
我不认为展开matrix(:)
是有害的,因为它等同于重塑,而Matlab以一种聪明的方式做到这一点,因为你没有实际分配和移动内存,因为你没有修改临时对象matrix(:)
如果您在函数调用之间没有变化或很少更改,您可以简单地使用另一个包含矩阵所有元素的向量,但已排序。通过这种方式,您可以使用更有效的搜索算法O(log(N))测试您的元素是否存在。
我个人喜欢这种问题的ismember
函数。它可能不是最快的,但对于代码的非关键部分,它极大地提高了可读性和代码维护(我宁愿花一个小时编写一些需要一天运行的东西,而不是花一天时间编写一小时运行的代码(这当然取决于你使用这个程序的频率,但这是人们永远不会忘记的事情)
如果您可以拥有矩阵元素的排序副本,则可以考虑使用未记录的Matlab函数ismembc,但请记住输入必须按非稀疏非NaN值排序。
如果性能确实很重要,您可能想编写自己的mex文件,对于此任务,您甚至可以使用openmp包含一些简单的并行化。
希望这有帮助,
阿德里安。