Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays MATLAB中的嵌套for循环速度极慢(预分配)_Arrays_Performance_Matlab_Loops_For Loop - Fatal编程技术网

Arrays MATLAB中的嵌套for循环速度极慢(预分配)

Arrays MATLAB中的嵌套for循环速度极慢(预分配),arrays,performance,matlab,loops,for-loop,Arrays,Performance,Matlab,Loops,For Loop,我正在尝试学习MATLAB,我遇到的第一个问题是用静态相机和运动物体从图像序列中猜测背景。首先,我只想计算一段时间内像素的平均值或中值,所以这是一个函数,我想应用于四维数组中的一行 我已将RGB图像加载到具有以下维度的4维阵列中: uint8 [ num_images, width, height, RGB ] 下面是我编写的函数,它包含4个嵌套循环。我使用了预分配,但仍然非常慢。在C++中,我相信这个函数可以运行至少10X-20X更快,我认为CUDA可以实时运行。在MATLAB中,使用4个嵌

我正在尝试学习MATLAB,我遇到的第一个问题是用静态相机和运动物体从图像序列中猜测背景。首先,我只想计算一段时间内像素的平均值或中值,所以这是一个函数,我想应用于四维数组中的一行

我已将RGB图像加载到具有以下维度的4维阵列中:

uint8 [ num_images, width, height, RGB ]
下面是我编写的函数,它包含4个嵌套循环。我使用了预分配,但仍然非常慢。在C++中,我相信这个函数可以运行至少10X-20X更快,我认为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++中自然发生一样?p> 或者我应该习惯用这种疯狂的单行语句方式编程MATLAB以获得最佳性能吗

更新

谢谢你的回答,现在我明白了很多。我的原始代码与
stack(:,1:size(stack,2),1:size(stack,3),1:3))
没有任何意义,它与
stack
完全相同,我只是幸运地使用了median的默认选项,即使用第一维作为其工作范围

我认为最好在另一个问题中问如何写一个有效的问题,所以我在这里问:


Matlab是一种解释语言,这意味着它必须计算脚本中的每一行代码

评估是一个漫长的过程,因为它必须解析、编译并解释每一行
*
。 使用带有简单操作的for循环意味着matlab解析/编译所需的时间远远超过实际执行代码所需的时间

另一方面,内置函数是用编译语言编写的,并且经过了大量优化。它们速度很快,因此速度不同

一句话:我们非常习惯过程语言和for循环,但是几乎总是有一种好的、快速的方法以矢量化的方式完成同样的事情

*
完成并向应得荣誉的人致敬:最近版本的Matlab实际上试图通过分析重复操作来加速循环,将重复操作的块编译成本机可执行文件。这被称为即时编译(JIT),并在下面的评论中指出


原始答复:

如果我理解得很好(并且你想要第一维度的中值),你可以尝试:

background=uint8((squeeze(median(stack,1)));

两者的区别在于它们执行代码的方法。粗略地描述一下:在C语言中,你把你的代码输入到一个编译器,编译器会试图优化你的代码,或者无论如何把它转换成机器代码。这需要一些时间,但当您实际执行程序时,它已经在机器代码中,因此执行速度非常快。您的编译器可能会花费大量时间来为您优化代码,一般来说,您并不关心编译一个发行版就绪的程序需要1分钟还是10分钟

MATLAB(和其他解释语言)通常不是这样工作的。当您执行程序时,解释器将解释每一行代码,并将其转换为一系列机器代码。如果您编写for循环,这会稍微慢一点,因为它必须反复解释代码(至少在原则上,对于最新版本的MATLAB来说,还有其他开销可能更重要)。这里的障碍是,所有事情都必须在运行时完成:解释器可以执行一些优化,但是执行耗时的优化是没有用的,在某些情况下,这些优化可能会大大提高性能,因为在大多数其他情况下,它们会导致性能下降

您可能会问,使用MATLAB获得了什么?您可以获得灵活性和清晰的语义。当你想做一个矩阵乘法,你只需要这样写;在C中,这将产生一个双
for
循环。您不必担心数据类型、内存管理等等

在幕后,MATLAB使用编译代码(Fortan/C/C++,如果我没有弄错的话)来执行大型运算:因此矩阵乘法实际上是由另一种语言编译的机器代码执行的。对于较小的操作,情况也是如此,但您不会注意到这些计算的速度,因为大部分时间都花在管理代码上(传递变量、分配内存等等)

总而言之:是的,你应该习惯这种紧凑的陈述。如果您看到类似Laurent示例的一行代码,您会立即看到它计算堆栈的中值。您的代码需要11行代码来表达相同的内容,因此当您查看类似于您的代码(可能嵌入在数百行其他代码中)时,您将很难理解发生了什么,也很难确定某个操作的执行位置

更进一步的论证是:你不应该像在C/C++中编程那样在MATLAB中编程;你也不应该反过来做。每种语言都有它的强项和弱项,要学会了解它们,并将每种语言用于它的用途。你可以写一整封信