【问题标题】:making gradient and del2 in matlab even faster使matlab中的梯度和del2更快
【发布时间】:2013-09-30 13:45:25
【问题描述】:

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

1. 首先,我尝试计算图像的梯度。我之前使用过 MATLAB 的 gradient operator,但发现它很慢。所以我写下了我自己的代码。请在my gradient code here! 找到我的代码

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

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

2. 其次,我需要在我的代码中使用拉普拉斯算子,发现它是我程序的瓶颈之一。我已经阅读了 matlab 文档并阅读了链接 Discrepancy between Matlab del2 and Matlab gradient of gradientUnderstanding DEL2 function in Matlab in order to code it in 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;

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

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

提前致谢!

编辑:经过一整天的努力,终于设法删除了违规矩阵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;

我绘制了速度比较。请检查,伙计们给你的cmets。

【问题讨论】:

    标签: matlab optimization image-processing matrix


    【解决方案1】:

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

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

    【讨论】:

    • 感谢您的信息!我会试试看,让你知道。其实我不知道如何在 matlab 中运行 MEX 函数。我使用的是 Windows 7 64 位操作系统并且没有安装 C/C++。这就是我搜索内置 matlab 命令的原因.....无论如何,你能提出任何提高 del2 性能的建议吗?
    【解决方案2】:

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

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

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

    (3) 我建议您查看del2(带有edit del2)和gradient 背后的代码,以了解为什么将拉普拉斯算子计算为del2 与您的代码中的xx+yy 会有所不同。它与连续一阶和二阶导数的不同有限差分近似有关。

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

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

    【讨论】:

    • @roni 这是一个有趣的结果。当我有更多时间时,我会相信你的话并尝试计算:)。如果您查看函数gradient,在解析输入、根据需要应用排列时会有一些开销(正如我所提到的),而且我认为最重要的是(但尚未验证!)将差异除以 步骤大小,你不做的事情。由于除法成本很高,如果您的例程(基本上删除了所有上述步骤)更快,我并不感到惊讶。然而,2 的因数有点令人印象深刻。
    • @roni 另一方面,如果您对性能很认真,而不仅仅是练习使用不同的算法,请按照上一个问题提供的建议并使用图像处理工具箱附带的例程(如果您拥有它)或在 matlab 中心查看类似的例程。这些已针对大型数据集的重型处理进行了优化(使用编译的 mex 例程)。
    • @roni 我检查了你的计算,结果和你报告的一样。看到修改gradient 中的代码(尤其是I/O 处理)对时间有很大影响,我真的很惊讶。正如我所提到的,主要影响是由于按步长数组划分。如果没有大量时间投入,我没有分析器来详细检查这些更改的效果。但是,您用于计算梯度的代码看起来不错。请记住,您缺少步长。
    • 顺便说一句,如果这回答了您的问题,请随时单击答案旁边的复选标记。
    • @Try Hard 我只是想让你知道,我见过一些自定义代码比 Matlab 的默认代码更快的例子。这些案例通常是专门的,但并不少见。一个很好的例子是使用 fft->multiply->ifft 而不是 conv。编译代码(有时)更快的原因是因为编译器尝试使用定义的规则集重新组织/重写代码以提高性能。不过,即使在编写脚本时,Matlab 也有一个“及时”编译器,它应该在运行脚本之前对脚本进行一定程度的优化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 2013-01-25
    • 2013-08-01
    • 2014-01-25
    相关资源
    最近更新 更多