如何在八度音程中优化以下双循环?

时间:2013-05-20 19:17:51

标签: performance optimization for-loop octave

我在八度音中有以下代码:

dist=0;
for i = 1:length(x);        
    for j = 1:length(y);
        v  = x(i,:) - y(j,:);
        distvect(j) = norm(v);
    endfor 
    dist = dist + min(distvect);
endfor

其中x和y是大小为n x 2和m x 2的矩阵。我的主要问题:我需要多次运行上面的代码。

我很确定有一种方法可以优化它,每次在内部for循环中使用可能只有一个矩阵而不是v向量,但我找不到它。我在网上搜索,发现了一个arrayfun函数,这可能有所帮助,但我无法弄清楚如何使用。

感谢您的帮助, 灰鹤

1 个答案:

答案 0 :(得分:2)

在这种情况下,您可以做出的最佳优化是自己实现norm以利用矩阵乘法,而不是循环遍历各个元素。

回想一下,对于矢量值,norm(v)计算norm(v, 2),这是欧几里德距离

norm(v, 2) = (sum (abs (v) .^ 2)) ^ (1/2)

由于您只需要找到最小距离,因此实际上您不需要采用平方根直到稍后。为了实现紧凑性,请a = x(i, :)b = y(j, :)M = length(x)N = length(y)。由于您的变量v包含差异向量,因此我们可以将distvect的计算扩展为

distvect   = norm(v)
           = norm(x(i, :) - y(j, :))
           = norm(a - b)
           = (sum (abs( a - b ) .^ 2)) ^ (1/2)
distvect^2 = sum (abs ( a - b ) .^ 2)

现在,展开二次项(a - b)^2 = a^2 - 2ab + b^2,这会使abs函数变为冗余

distvect^2 = sum (sum(a.*a) * ones(1,N) - 2*a*b' + ones(M,1) * sum(b'.*b') )

最后的优化,它跨多个值应用函数。这是通过使用xy矩阵的外积来创建length(x)length(y)矩阵来完成的。然后只需沿每列取最小距离并求结果的平方根

xx   = sum(x .* x, 2) * ones(1, length(y))
xy   = x * y'
yy   = ones(length(x), 1) * sum(y' .* y')

dist = sum(sqrt(min(xx - 2.*xy + yy)))