我是一个有用的助手,可以为您翻译文本。
现在我不明白为什么嵌套循环的版本如此缓慢,如果MATLAB可以这么快,那么为什么要这样做?我没有进行任何动态调整大小,MATLAB必须在内部运行相同的4个嵌套循环。为什么会发生这种情况?是否有方法使嵌套循环运行得更快,就像在C++中自然发生的那样?还是应该习惯使用一行代码的方式来编写MATLAB以获得最佳性能?更新:感谢所有伟大的答案,现在我理解了很多。我的原始代码
我正在尝试学习MATLAB,遇到的第一个问题之一是从具有静态摄像头和移动物体的图像序列中猜测背景。首先,我只想在时间上对像素进行平均或中位数,因此它只是要应用于4维数组的其中一行的单个函数。
我已经将RGB图像加载到了具有以下维度的4维数组中:
uint8 [ num_images, width, height, RGB ]
这是我写的一个包含4个嵌套循环的函数。虽然我使用了预分配(preallocation),但仍然非常慢。我相信在C++中,这个函数至少可以运行快10倍到20倍,而且我认为在CUDA上它实际上可以实时运行。在MATLAB中,使用4个嵌套循环需要大约20秒的时间。我的堆栈(stack)有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函数默认选项,将第一个维度用作其工作范围。我认为最好在另一个问题中询问如何编写高效的问题,因此我在这里提出了这个问题:如何在MATLAB中编写向量化函数。