【问题标题】:a faster way to achieve what intersect() is giving me?一种更快的方法来实现 intersect() 给我的东西?
【发布时间】:2011-12-30 20:39:58
【问题描述】:

我发现在我的 matlab 函数中花费了 很多 时间在这段代码中:

intersect(freq_bins, our_bins);

两者都可以是相当大的向量,并且仅由整数组成。我只需要知道两者中都有哪些整数。这确实是 intersect() 的原始目的,所以我怀疑答案是:它并没有变得更好。但也许有人有一些建议。

【问题讨论】:

  • 1) 它是“组成”而不是“组成”:) 2) 原则上,相交的未排序列表需要 O(N^2),但相交的排序列表需要 O(N)。排序本身是 O(Nlog(N)),所以正如@Jonas 所说,你可以用排序的向量自己做得更好。
  • @MikeDunlavey:在这种情况下提高速度的主要原因是您可以避免输入检查以及调用多个函数的开销。
  • @Jonas:我相信你是对的。我最喜欢的例子是用于乘法/缩放矩阵的 LAPACK 例程 DGEMM。人们会期望它被优化到第 n 级,但除非矩阵非常大,否则它会花费大部分时间调用 LSAME 来对其输入标志进行分类。它的真正目标是为程序员节省编码工作,而不一定是速度。

标签: performance matlab optimization intersection


【解决方案1】:

如果您可以假设您的输入包含唯一整数的排序列表,那么您可以使用非常简单的算法在线性时间内做到这一点:

function c = intersect_sorted(a,b)
  ia = 1;
  na = length(a);
  ib = 1;
  nb = length(b);
  ic = 0;
  cn = min(na,nb);
  c = zeros(1,cn);

  while (ia <= na && ib <= nb)
    if (a(ia) > b(ib))
      ib = ib + 1;
    elseif a(ia) < b(ib)
      ia = ia + 1;
    else % a(ia) == b(ib)
      ic = ic + 1;
      c(ic) = a(ia);
      ib = ib + 1;
      ia = ia + 1;
    end
  end
  c = c(1:ic);
end

长度为 n 和 m 的列表的最大运行时间为 O(n+m)。

>>a = unique(randi(1000,100,1));
>>b = unique(randi(1000,100,1));
>>tic;for i = 1:10000, intersect(a,b); end,toc
Elapsed time is 1.224514 seconds.
>> tic;for i = 1:10000, intersect_sorted(a,b); end,toc
Elapsed time is 0.289075 seconds.

【讨论】:

    【解决方案2】:

    intersect 调用 ismember。在您的情况下,您不需要 intersect 所做的所有复杂检查,因此您可以节省一些开销并直接调用 ismember(注意:我确保在计时之前调用这两个函数):

    a = randi(1000,100,1);
    b = randi(1000,100,1);
    
    >> tic,intersect(a,b),toc
    ans =
        76
       338
       490
       548
       550
       801
       914
       930
    Elapsed time is 0.027104 seconds.
    
    >> tic,a(ismember(a,b)),toc
    ans =
       914
       801
       490
       548
       930
       550
        76
       338
    Elapsed time is 0.000613 seconds.
    

    您可以通过直接调用执行实际测试的函数ismembc 来加快速度。请注意,ismembc 需要排序数组(因此,如果您的输入已经排序,则可以放弃排序!)

    tic,a=sort(a);b=sort(b);a(ismembc(a,b)),toc
    ans =
        76
       338
       490
       548
       550
       801
       914
       930
    Elapsed time is 0.000473 seconds.
    

    【讨论】:

    • 太棒了,伙计!我衷心感谢您的回复。我的两个向量都已经保证被排序。只是将我的运行时间加快了 30% :)
    猜你喜欢
    • 2023-03-17
    • 2013-09-28
    • 2013-08-26
    • 1970-01-01
    • 2010-10-05
    • 2012-04-15
    • 2017-04-23
    • 2015-07-07
    • 1970-01-01
    相关资源
    最近更新 更多