【问题标题】:Why is caching answers taking LONGER in MATLAB?为什么在 MATLAB 中缓存答案需要更长的时间?
【发布时间】:2008-12-15 13:29:21
【问题描述】:

我在 MATLAB 中有一个长时间运行的函数,我试图通过添加缓存来加速它,结果显着降低了我的性能。我的代码基本上是在边缘检测图像中搜索连续的“水平”线,原始代码如下所示:

function lineLength = getLineLength(img, startRow, startCol)
    [nRows, nCols] = size(img);
    lineLength = 0;
    if startRow < 1 || startRow > nRows
        return;
    end

    for curCol = startCol:nCols
        if img(curCol)
            lineLength = lineLength + 1;
            continue;
        elseif lineLength > 0
            lengths = zeros(2,1);
            lengths(1) = getLineLength(img, startRow - 1, curCol);
            lengths(2) = getLineLength(img, startRow + 1, curCol);
            increment = max(lengths);
            lineLength = lineLength + increment;
        end
        break; %// At this point the end of the current line has been reached
    end
end function

由于这个函数的性能不是我想要的,我想我会从任何一点添加长度缓存,如下所示:

function lineLength = getLineLength(img, startRow, startCol)
persistent pointCache; 
    if startRow == 0 && startCol == 0
        pointCache = zeros(size(img, 1), size(img, 2), 2);
    end
    [nRows, nCols] = size(img);
    lineLength = 0;
    if startRow < 1 || startRow > nRows
        return;
    end

    for curCol = startCol:nCols
        if pointCache(startRow, curCol, 2)
            lineLength = lineLength + pointCache(startRow, curCol, 1);
            break;
        end
        if img(curCol)
            lineLength = lineLength + 1;
            continue;
        elseif lineLength > 0
            lengths = zeros(2,1);
            lengths(1) = getLineLength(img, startRow - 1, curCol);
            lengths(2) = getLineLength(img, startRow + 1, curCol);
            increment = max(lengths);
            lineLength = lineLength + increment;
        end
        break; %// At this point the end of the current line has been reached
    end
    pointCache(startRow, startCol, 1) = lineLength;
    pointCache(startRow, startCol, 2) = 1;
end function

让我感到惊讶的是,实施这种缓存实际上使我的性能更差,而不是更好。我的最佳猜测是 global 变量给我带来了麻烦,或者它使用了额外的内存,但我没有足够的 MATLAB 经验知道。

已编辑...

正如 Gautam 正确指出的那样,原始代码中存在忽略递归结果的错误。这就是实际代码的作用。我确信这很明显,但 MATLAB 不是我的母语,所以如果有更 MATLAB 的方式来做到这一点,我会喜欢这些建议。

【问题讨论】:

    标签: performance matlab


    【解决方案1】:

    我很确定全局不是问题,但就风格而言,您应该使用persistent,它在每次调用中保持其值,但对于函数来说是本地的。

    任何时候你有性能问题,配置文件。调用profile on,然后调用你的函数,然后调用profile report。它会指出你真正的性能问题。直觉很少有利于分析问题,尤其是在 matlab 中。您可以阅读帮助,但它是不言自明的。

    【讨论】:

    • 谢谢 Marc,我不知道持久性。我更喜欢拥有更本地化的范围,只是不知道如何实现它。
    【解决方案2】:

    我不清楚该函数的作用。特别是,你为什么递归调用 getLineLength 然后有效地丢弃结果(你只测试增量是否大于零)?

    我对为什么 pointCache 没有帮助的猜测:您的函数可能不会使用相同的参数(startRow、startCol)重复调用自身。您是否尝试记录特定 startRow 和 startCol 调用 getLineLength 的次数?

    无论您的算法是什么,使用递归迭代图像完全不适合 MATLAB 的优势。如果您想要高性能:

    1. 将您的算法设置为使用迭代而不是递归,并且
    2. 弄清楚如何向量化迭代的部分。

    关于矢量化的一些技巧:

    • 使用sumcumsumdiffbsxfunaccumarray 等内置函数直接对图像矩阵进行操作。
    • 图像上复杂的双迭代计算有时可以重新表示为矩阵乘法。

    【讨论】:

    • 你说得对,这是一个错误,因为实际代码在另一台没有互联网连接的机器上,所以我是从内存中重写的。我确实检查了我的缓存命中率,它似乎应该有所帮助。既然您可以看到我的实际意图,还有更多的 MATLAB 方法可以做到吗?
    【解决方案3】:

    我的猜测是您缓存了错误的代码部分。 elseif 部分的递归似乎是真正的瓶颈。整个算法对我来说有点奇怪,也许你最好试试这样的东西(虽然我不确定这是否是你想要的):

    for every pixel p in img
      if (pixel p set)
        linelength = 1
        p2 = p
        while (pixel p2 set) and (p2 in same column as p)
          p++ // don't check lines twice
          p2++
          linelength++
        endwhile
      endif
    

    【讨论】:

      【解决方案4】:

      据我所知,您正在尝试查找每列的非零元素的数量,尽管代码似乎并没有完全做到这一点。会像以下工作:

      lineLengths = max(cumsum(img~=0, 1), 1)
      

      如果您尝试从图像中提取 blob,请考虑使用 BWLABEL 函数。

      我赞同 Gautam 所说的在 Matlab 中通常运行良好的内容。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-09
        • 2022-01-24
        相关资源
        最近更新 更多