【问题标题】:How to optimize the following double for loop in octave?如何在八度音程中优化以下双循环?
【发布时间】:2013-05-15 10:30:53
【问题描述】:

我有以下八度代码:

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 函数,这可能会有所帮助,但我不知道如何使用。

感谢您的帮助, 格鲁斯

【问题讨论】:

    标签: performance optimization for-loop octave


    【解决方案1】:

    在这种情况下,您可以进行的最佳优化是自己实现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) by 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)))
    

    【讨论】:

    • 我认为有一些错误。试试这个 x=rand(440,2), y=rand(740,2);
    • 谢谢,我想它现在已经修好了。我在错误的轴上求和。
    • 太好了,非常感谢。这正是我想要的,这样更快。
    猜你喜欢
    • 1970-01-01
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 2015-07-24
    • 1970-01-01
    • 2017-04-06
    相关资源
    最近更新 更多