【问题标题】:Fast check if element is in MATLAB matrix快速检查元素是否在 MATLAB 矩阵中
【发布时间】:2015-02-09 00:26:52
【问题描述】:

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

一开始我是这样实现的:

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

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

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

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

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

谢谢。

【问题讨论】:

  • 你可以试试ismember,但我不确定它会更快。如果你的matrix 是二维的,你也可以试试sum(sum(matrix==element)),这样可以避免使用(:) 展开矩阵,可能会节省一点时间。
  • 14 秒!你的矩阵有多大?它是双精度矩阵吗(class(matrix)class(element) 是什么?)?

标签: performance matlab optimization


【解决方案1】:

如果你只需要知道一个值是否存在于一个矩阵中,使用 find 的第二个参数来指定你只想要一个值会比使用 @987654322 稍微快一些(25-50%)甚至快一点@,至少在我的机器上。一个例子:

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

但是,在最近的 Matlab 版本中(我使用的是 R2014b),nnz 最终对这个操作更快了,所以:

matrix = randi(100,1e4,1e4);
element = 50;
nnz(matrix==element)~=0

在我的机器上,对于提供的示例,这比任何其他方法(包括使用any,奇怪的是)快大约 2.8 倍。在我看来,这个解决方案还具有可读性最强的优点。

【讨论】:

  • 在我的笔记本电脑上,any 比测试nnz 更快
  • @Adrien:您可能使用的是较旧的 version 的 Matlab。 nnz 一直比看似更复杂的方案慢,但看起来终于优化了。在我的 MacBook Pro(OS X 10.10.1 和 R2014)上,上面的示例使用 nnz 需要 0.18 秒,而 anyfind 需要 0.51 秒。虽然我自己使用any 会更快。
  • 我在 MacBook Pro (OSX 10.9.5) 上使用 R2014a。对于 30000 x 30000 矩阵。 nnz 方式需要 1.8 秒,与比赛的位置无关(nnz(matrix==matrix(1))nnz(matrix==matrix(end)))。 any 需要 1.2 到 1.6 秒,具体取决于比赛的位置。我假设如果any 编码正确,它会在找到匹配项时立即退出,而nnz 需要检查整个矩阵。这就是说我认为我们在一个很小的问题上争论:)
  • 所以看起来加速可能从 R2014b 开始,然后(我想它可能与操作系统有关,但我对此表示怀疑)。
【解决方案2】:

在我看来,您可以尝试以下几件事来提高性能:

  1. 按照您最初的想法,我会使用函数any 来测试是否有任何相等性测试成功:

    if any(matrix(:) == element)

我在 1000 x 1000 矩阵上对此进行了测试,它比您测试过的解决方案要快。

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

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

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

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

  5. 如果性能真的很关键,您可能需要编写自己的 mex 文件,对于此任务,您甚至可以使用 openmp 进行一些简单的并行化。

希望这会有所帮助,

阿德里安。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    相关资源
    最近更新 更多