arrays - 嵌套 for 循环在 MATLAB 中非常慢(预分配)

标签 arrays performance matlab loops for-loop

我正在尝试学习 MATLAB,我遇到的第一个问题是从带有静态相机和移动物体的图像序列中猜测背景。一开始,我只想随时间对像素求平均值或中值,所以它只是我想应用于 4 维数组的其中一行的单个函数

我已将我的 RGB 图像加载到具有以下尺寸的 4 维数组中:

uint8 [ num_images, width, height, RGB ]

这是我编写的函数,其中包含 4 个嵌套循环。我使用预分配,但它仍然非常慢。在 C++ 中,我相信这个函数的运行速度至少可以提高 10 到 20 倍,而且我认为在 CUDA 上它实际上可以实时运行。在 MATLAB 中,4 个嵌套循环大约需要 20 秒。我的堆栈是 100 张尺寸为 640x480x3 的图像。

function background = calc_background(stack)
tic;

si = size(stack,1);
sy = size(stack,2);
sx = size(stack,3);
sc = size(stack,4);

background = zeros(sy,sx,sc);
A = zeros(si,1);

for x = 1:sx
    for y = 1:sy
        for c = 1:sc
            for i = 1:si
                A(i) = stack(i,y,x,c);
            end
            background(y,x,c) = median(A);
        end
    end
end

background = uint8(background);

disp(toc);
end

你能告诉我如何使这段代码更快吗?我已经尝试尝试以某种方式仅使用索引直接从数组中获取数据,而且速度似乎快得多。它在 3 秒与 20 秒内完成,因此只需编写一个更小的函数即可实现 7 倍的性能差异。

function background = calc_background2(stack)
    tic;

    % bad code, confusing
    % background = uint8(squeeze(median(stack(:, 1:size(stack,2), 1:size(stack,3), 1:3 ))));

    % good code (credits: Laurent)
    background=uint8((squeeze(median(stack,1)));

    disp(toc);
end

所以现在我不明白如果 MATLAB 可以这么快那么为什么嵌套循环版本这么慢?我没有进行任何动态调整大小并且 MATLAB 必须运行相同的 4 个嵌套循环里面。

为什么会这样?

有没有办法让嵌套循环运行得更快,就像它在 C++ 中自然发生一样?

或者我应该习惯以这种疯狂的单行语句方式对 MATLAB 进行编程以获得最佳性能吗?

更新

谢谢大家的精彩解答,现在我明白了很多。我的原始代码 stack(:, 1:size(stack,2), 1:size(stack,3), 1:3 )) 没有任何意义,它是完全一样的作为 stack,我很幸运,因为 median 的默认选项是使用第一个维度作为其工作范围。

我觉得在别的问题里问how to write an efficient question比较好,所以就在这里问了:

How to write vectorized functions in MATLAB

最佳答案

如果我理解您的问题,您是在问为什么 Matlab 对于矩阵运算比对于过程编程调用更快。答案很简单that's how it's designed .如果你真的想知道是什么让它成为这样,你可以阅读 this newsletter from Matlab's website其中讨论了一些基础技术,但您可能不会得到很好的答案,因为该软件是专有的。我还找到了一些 relevant pages通过简单的谷歌搜索,和this old SO question 似乎也解决了您的问题。

关于arrays - 嵌套 for 循环在 MATLAB 中非常慢(预分配),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7811239/

相关文章:

c# - 如何将 double 转换为任意大小的字节数组?

python - Python 中未知大小的二维数组

java - 非常快速的均匀分布随机数生成器

java - Log4j DailyRollingFileAppender 与 ConsoleAppender 性能对比

C crypt_r真的比crypt慢32倍吗?

matlab - 在 MATLAB 中经常附加文本的最佳方法

matlab - 计算 Matlab 中元胞数组的集并集

android - Kotlin (Android) - 为非可变函数传播一个数组/列表

Matlab:kmeans 聚类给出了意想不到的聚类

python - 在numpy中将int数组转换为字符串数组而不截断