1

我有几个问题。请忍受我。我写了一个程序并试图优化它。我只发布我认为可以进一步优化的代码片段。

1.首先我试图计算图像的梯度。我以前使用过 MATLAB 的梯度算子,但发现它很慢。所以我写下了我自己的代码。请在我的渐变代码中找到我的代码!

我在 MATLAB 上运行分析器,发现我的程序仍然存在一些瓶颈。我在这里张贴一张图片: 梯度剖面

如您所见,我使用了两个额外的矩阵 A 和 B 两次,用于计算水平和垂直方向的梯度。真的有必要吗?如果不使用额外的矩阵 A 和 B,就不能将操作集成到第 5 行和第 8 行中。删除额外的矩阵 A 和 B 会使我的代码运行得更快吗?

2.其次,我需要在我的代码中使用拉普拉斯算子,发现它是我程序的瓶颈之一。我已经阅读了 matlab 文档,还阅读了Matlab del2 和 Matlab 梯度梯度之间的差异和在 Matlab 中理解 DEL2 函数的链接,以便用 C++ 对其进行编码

然后我检查了 del2 的配置文件并找到了这个。在此处输入图像描述. 我的问题是,在这种情况下,子函数parse_inputsipermut的功能是什么?需要注意的是,我正在使用大小始终大于 64X64 的图像矩阵。

我阅读了 permute 的解释,它说“ Permute 以便 del2 始终沿列显示。 ”。实际上是什么意思?我在某处读到 MATLAB 使用列主要格式。谁能解释一下这是什么意思?

关于 parse_inputs 子功能,我阅读了说明,其中指出

 %PARSE_INPUTS
                  %   [ERR,F,LOC,CFLAG] = PARSE_INPUTS(F,V) returns the spacing LOC
                  %   along the x,y,z,... directions and a column vector flag CFLAG. ERR
                  %   will be true if there is an error.

我不知道这个函数是做什么的。请问谁能解释一下?

3 . 我还尝试为matlab写下我自己的del2函数,以使其更快,但奇怪的是我只能处理内部点。MATLAB 中的实现对于 del2 是否正确?为什么它在边界点进行外推?

拉普拉斯算子的基础不应该总是它应该保持等式吗?

laplacian = del2(image);

[x, y] = gradient(image);
[xx, xy] = gradient(x);
[yx, yy] = gradient(y);
laplacian = xx + yy;

此代码取自请检查代码。我阅读了那里的所有帖子,但解释并不令我满意。请你解释一下为什么上面的代码没有给出相同的输出?

感谢大家阅读这组冗长而无聊的问题。任何帮助将不胜感激。如果有人有问题,我会将问题分开并单独发布。就这么说吧伙计们!

提前致谢 !

编辑:经过一整天的努力,终于设法删除了有问题的矩阵 A 和 B。我正在写下下面的代码:

function [dx dy] = gradient_my_code(I)
dx=[I(:,2)-I(:,1) (I(:,3:end)-I(:,1:end-2))./2 I(:,end)-I(:,end-1)];
dy=[I(2,:)-I(1,:) ; (I(3:end,:)-I(1:end-2,:))./2 ; I(end,:)-I(end-1,:)];

出于计时目的,我这样做了:

xaxis = [10,20,30,40,50,60,70,80,90,100,200,300,400,500,600,700,800,900,1000,2000,3000,4000,5000];
n1 = zeros(1,length(xaxis));
n2 = zeros(1,length(xaxis));
for i=1:length(xaxis);
    x=xaxis(i);
    u=magic(x);
    tic
    [dx dy] = gradient(u);
    n1(i)=toc;
    tic
    [dx dy] = gradient_my_code(u);
    n2(i)=toc;
end
plot(n1,'r','LineWidth',3);
hold on;
plot(n2,'b','LineWidth',3);
hold off;

matlab的梯度和我的代码速度比较

我绘制了速度比较。请检查并提出您的意见。

4

2 回答 2

3

尝试使用 Jan Simon 的DGradient MEX 函数。它比梯度快 10-20 倍,并提供相同的结果。然后,您可以修改其源代码以实现对del2性能的类似改进。

这确实是一个罕见的例子,Mex 文件通过如此显着的加速超过了原生 Matlab 函数。

于 2013-10-10T16:36:29.487 回答
2

鉴于我试图总结的大量问题:

(1) Matlab 是高度优化的,所以你不太可能打败 Mathworks 的人基于广泛的数值研究编写的本机例程。需要注意的是,由于 Mathworks 代码经常对输入执行错误、数据类型和维度检查,因此您可以通过编写不执行这些任务的代码在执行期间节省一些时间,但我不建议您这样做,除非您有一个非常这样做的充分理由。如果您有一个大型项目,您还可以编写mex可以(但我无法验证)可以节省一些执行时间的函数。

(2) Matlab 例程通常被编写为按列处理数组(因为编写例程是为了利用按列数据存储)。例如,如果您阅读函数背后的代码,gradient您会发现其中一个步骤是“置换,以便始终沿列采用渐变”。

del2(3) 我建议您查看(with edit del2)后面的代码,并gradient了解为什么在您的代码中计算 Laplacian asdel2xx+yyas 会有所不同。它与连续一阶和二阶导数的不同有限差分近似有关。

就边缘处的行为而言del2,事实证明算法中的一个步骤是“从内部线性外推二阶差分”。这只是一种为输入数组中的所有点获取拉普拉斯近似值的方法,包括在只有单边近似值的边缘处。

最后, on parse_inputs:这只是一个函数,它负责为梯度计算中使用的所有变量分配值,根据情况使用用户输入或默认值。

于 2013-09-25T14:46:43.653 回答